Merge branch 'master' into artilleryTables

This commit is contained in:
PabstMirror 2019-08-12 15:01:28 -05:00
commit 65e81864f9
207 changed files with 2128 additions and 1381 deletions

View File

@ -61,6 +61,7 @@ Clon1998 <ps.patti1998@gmail.com>
Codingboy
Coren <coren4@gmail.com>
Crusty
C0kkie
Dharma Bellamkonda <dharma.bellamkonda@gmail.com>
Dimaslg <dimaslg@telecable.es>
diwako

View File

@ -47,8 +47,8 @@ if (!hasInterface) exitWith {};
[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];
}] call FUNC(addDutyFactor);
[QEGVAR(medical,bloodVolume), { // 100->1.0, 90->1.1, 80->1.2
linearConversion [6, 0, (_this getVariable [QEGVAR(medical,bloodVolume), 100]), 1, 2, true];
[QEGVAR(medical,bloodVolume), { // 6->1.0, 5->1.167, 4->1.33
linearConversion [6, 0, (_this getVariable [QEGVAR(medical,bloodVolume), 6]), 1, 2, true];
}] call FUNC(addDutyFactor);
};
if (["ACE_Dragging"] call EFUNC(common,isModLoaded)) then {

View File

@ -123,6 +123,7 @@
</Key>
<Key ID="STR_ACE_Advanced_Fatigue_SwayFactor">
<English>Sway factor</English>
<German>Verwacklungsfaktor</German>
<Japanese>手ぶれ因数</Japanese>
<Chinesesimp>抖动因数</Chinesesimp>
<Chinese>抖動因素</Chinese>
@ -133,6 +134,7 @@
</Key>
<Key ID="STR_ACE_Advanced_Fatigue_SwayFactor_Description">
<English>Influences the amount of weapon sway. Higher means more sway.</English>
<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>

View File

@ -26,3 +26,8 @@ TRACE_1("Fired",_this);
{
_this call _x;
} forEach ((_this select 0) 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]);

View File

@ -3,6 +3,7 @@
<Package name="ai">
<Key ID="STR_ACE_ai_GarrisonInvalidPosition">
<English>Invalid position provided.</English>
<German>Ungültige Position</German>
<French>Position invalide fourni</French>
<Japanese>位置が無効です。</Japanese>
<Italian>Posizione invalida fornita.</Italian>
@ -14,6 +15,7 @@
</Key>
<Key ID="STR_ACE_ai_GarrisonNoUnits">
<English>No units provided.</English>
<German>Keine Einheit ausgewählt</German>
<French>Aucune unité fourni</French>
<Japanese>ユニットがありません。</Japanese>
<Italian>Nessuna unità fornita.</Italian>
@ -25,6 +27,7 @@
</Key>
<Key ID="STR_ACE_ai_GarrisonNotEnoughPos">
<English>There aren't enough positions to place all units.</English>
<German>Es gibt nicht genug Positionen, um alle Einheiten zu platzieren</German>
<French>Il n'y a pas assez de positions pour placer toutes les unités</French>
<Japanese>全ユニットを置くために十分な位置がありません。</Japanese>
<Italian>Non ci sono abbastanza posizioni per piazzare tutte le unità.</Italian>
@ -36,6 +39,7 @@
</Key>
<Key ID="STR_ACE_ai_GarrisonNoBuilding">
<English>No building found.</English>
<German>Kein Gebäude gefunden</German>
<French>Aucun bâtiment trouvé</French>
<Japanese>建物がありません。</Japanese>
<Italian>Nessun edificio trovato.</Italian>

View File

@ -749,6 +749,7 @@
</Key>
<Key ID="STR_ACE_Arsenal_buttonLoadoutsTooltip">
<English>Open the loadouts screen</English>
<German>Öffnet das Ausrüstungsmenü</German>
<French>Affiche la page des équipements</French>
<Chinese>開啟裝備選單</Chinese>
<Chinesesimp>开启装备选单</Chinesesimp>
@ -759,6 +760,7 @@
</Key>
<Key ID="STR_ACE_Arsenal_buttonExportTooltip">
<English>Export current / default loadouts</English>
<German>Exportiert aktuelles / standard Loadout</German>
<French>Exporte l'équipement actuel ou la liste d'équipements de base</French>
<Chinese>匯出當前/預設的裝備</Chinese>
<Chinesesimp>汇出当前/预设的装备</Chinesesimp>
@ -769,6 +771,7 @@
</Key>
<Key ID="STR_ACE_Arsenal_buttonImportTooltip">
<English>Import current / default loadouts</English>
<German>Importiert aktuelles / standard Loadout</German>
<French>Importer l'équipement actuel ou la liste d'équipements de base</French>
<Chinese>匯入當前/預設的裝備</Chinese>
<Chinesesimp>汇入当前/预设的装备</Chinesesimp>
@ -845,6 +848,7 @@
</Key>
<Key ID="STR_ACE_Arsenal_page">
<English>Page</English>
<German>Seite</German>
<French>Page</French>
<Japanese>ページ</Japanese>
<Chinesesimp>页面</Chinesesimp>
@ -855,6 +859,7 @@
</Key>
<Key ID="STR_ACE_Arsenal_enableIdentityTabsSettings">
<English>Enable the faces / voices / insignias tabs</English>
<German>Aktiviere die Gesichter-, Stimmen- und Abzeichenübersicht</German>
<French>Activer les onglets faces / voix / insignes</French>
<Japanese>顔 / 声 / 記章タブを有効化</Japanese>
<Chinesesimp>启用脸谱/声音/徽章/选项 </Chinesesimp>
@ -865,6 +870,7 @@
</Key>
<Key ID="STR_ACE_Arsenal_buttonClearContainerTooltip">
<English>Empty the selected container</English>
<German>Aktuellen Container leeren</German>
<French>Vider le conteneur selectionné</French>
<Japanese>選択されたコンテナは空です</Japanese>
<Chinesesimp>选择的箱子是空的</Chinesesimp>
@ -875,6 +881,7 @@
</Key>
<Key ID="STR_ACE_Arsenal_exportedClassnameText">
<English>Exported class name to clipboard</English>
<German>Der Klassenname wurde in die Zwischenablage exportiert</German>
<French>Nom de classe exporté dans le presse papier</French>
<Japanese>クリップボードへクラスネームをエクスポート</Japanese>
<Chinesesimp>将种类复制到剪贴板</Chinesesimp>
@ -917,6 +924,7 @@
</Key>
<Key ID="STR_ACE_Arsenal_Blacklist">
<English>Blacklist</English>
<German>Blacklist</German>
<Japanese>禁止リスト</Japanese>
<Italian>Lista Nera</Italian>
<Polish>Czarna lista (lista wykluczeń)</Polish>
@ -940,6 +948,7 @@
</Key>
<Key ID="STR_ACE_Arsenal_AttributeExport_Tooltip">
<English>Export current items list as an array for use in scripts</English>
<German>Exportiert aktuelle Gegenstände als Array, um es in Scripten zu verwenden</German>
<Japanese>スクリプト用に現在のアイテム リストをアレイでエクスポートします</Japanese>
<Italian>Esporta l'attuale lista di elementi come un array, per essere usati negli script</Italian>
<Polish>Eksportuj obecną listę przedmiotów jako tablicę do wykorzystania w skryptach</Polish>
@ -947,24 +956,28 @@
</Key>
<Key ID="STR_ACE_Arsenal_AttributeImport_Tooltip">
<English>Import items list array from clipboard (should be the same format as export)</English>
<German>Importiert alles aus der Zwischenablage (Sollte im gleichen Format sein, wie beim Exportieren)</German>
<Polish>Zaimportuj listę przedmiotów ze schowka (lista musi być w tym samym formacie jak przy exporcie)</Polish>
<Japanese>クリップボードからアイテムリストをアレイでインポートします (エクスポートと同じフォーマットである必要があります)</Japanese>
<Russian>Импорт массива списка предметов из буфера (должен иметь тот же формат, что при экспорте)</Russian>
</Key>
<Key ID="STR_ACE_Arsenal_AttributeAddCompatible_DisplayName">
<English>Add Compatible Items</English>
<German>Füge kompatible Gegenstände hinzu</German>
<Polish>Dodaj kompatybilne przedmioty</Polish>
<Japanese>対応アイテムを追加</Japanese>
<Russian>Добавить совместимые предметы</Russian>
</Key>
<Key ID="STR_ACE_Arsenal_AttributeAddCompatible_Tooltip">
<English>Will automatically add compatible attachments or magazines (based on selected category) for all weapons in current items list</English>
<German>Es werden automatisch kompatible Aufsätze oder Magazine für alle ausgewählten Waffen hinzugefügt</German>
<Polish>Automatycznie doda kompatybilne dodatki oraz magazynki (odpowiednio do każdej kategorii) dla wszystkich broni na liście</Polish>
<Japanese>現在のアイテム リスト内にある全武器に対応するアタッチメントと弾倉 (選択したカテゴリに基づき) を自動的に追加します</Japanese>
<Russian>Добавляет совместимые приспособления или магазины (в зависимости от выбранной категории) для всего оружия в текущем списке предметов</Russian>
</Key>
<Key ID="STR_ACE_Arsenal_statTTL">
<English>Time to live</English>
<German>Lebenszeit</German>
<French>Durée de vie</French>
<Japanese>有効時間</Japanese>
<Polish>Czas by żyć</Polish>

View File

@ -2283,6 +2283,7 @@
</Key>
<Key ID="STR_ACE_Ballistics_statBarrelTwist">
<English>Barrel twist</English>
<German>Dralllänge</German>
<Japanese>銃身の転度</Japanese>
<Chinesesimp>膛线缠距</Chinesesimp>
<Chinese>膛線扭度</Chinese>
@ -2292,6 +2293,7 @@
</Key>
<Key ID="STR_ACE_Ballistics_statBarrelLength">
<English>Barrel length</English>
<German>Lauflänge</German>
<French>Longueur du canon</French>
<Japanese>銃身長</Japanese>
<Chinesesimp>身管长度</Chinesesimp>
@ -2302,6 +2304,7 @@
</Key>
<Key ID="STR_ACE_Ballistics_statBallisticCoef">
<English>Ballistic coefficient</English>
<German>Ballistischer Koeffizient</German>
<French>Coefficient ballistique</French>
<Japanese>弾道係数</Japanese>
<Chinesesimp>弹道系数</Chinesesimp>
@ -2312,6 +2315,7 @@
</Key>
<Key ID="STR_ACE_Ballistics_statBulletMass">
<English>Bullet mass</English>
<German>Projektilgewicht</German>
<French>Masse d'une balle</French>
<Japanese>弾丸重量</Japanese>
<Chinesesimp>弹头重量</Chinesesimp>
@ -2322,6 +2326,7 @@
</Key>
<Key ID="STR_ACE_Ballistics_statMuzzleVelocity">
<English>Muzzle velocity</English>
<German>Mündungsgeschwindigkeit</German>
<French>Vitesse à la bouche</French>
<Japanese>銃口初速</Japanese>
<Chinesesimp>枪口初速</Chinesesimp>

View File

@ -63,6 +63,11 @@ class CfgVehicles {
GVAR(space) = 4;
GVAR(hasCargo) = 1;
};
class Tank_F: Tank {};
class UGV_02_Base_F: Tank_F {
GVAR(space) = 0;
GVAR(hasCargo) = 0;
};
class Car_F;
class Truck_F: Car_F {

View File

@ -11,5 +11,6 @@ PREP_RECOMPILE_END;
GVAR(initializedItemClasses) = [];
GVAR(initializedVehicleClasses) = [];
GVAR(cargoHolderTypes) = ["Car", "Air", "Tank", "Ship", "Cargo_base_F", "Land_PaperBox_closed_F"];
GVAR(disableParadropEffectsClasstypes) = ["Car_F"];
ADDON = true;

View File

@ -69,8 +69,10 @@ _itemObject setVelocity ((velocity _vehicle) vectorAdd ((vectorNormalized (vecto
_item attachTo [_parachute, [0,0,1]];
_parachute setVelocity _velocity;
private _light = "Chemlight_yellow" createVehicle [0,0,0];
_light attachTo [_item, [0,0,0]];
if ((GVAR(disableParadropEffectsClasstypes) findIf {_item isKindOf _x}) == -1) then {
private _light = "Chemlight_yellow" createVehicle [0,0,0];
_light attachTo [_item, [0,0,0]];
};
}, [_itemObject], 0.7] call CBA_fnc_waitAndExecute;
@ -83,8 +85,10 @@ _itemObject setVelocity ((velocity _vehicle) vectorAdd ((vectorNormalized (vecto
};
if (getPos _item select 2 < 1) then {
private _smoke = "SmokeshellYellow" createVehicle [0,0,0];
_smoke attachTo [_item, [0,0,0]];
if ((GVAR(disableParadropEffectsClasstypes) findIf {_item isKindOf _x}) == -1) then {
private _smoke = "SmokeshellYellow" createVehicle [0,0,0];
_smoke attachTo [_item, [0,0,0]];
};
[_this select 1] call CBA_fnc_removePerFrameHandler;
};

View File

@ -322,6 +322,7 @@
</Key>
<Key ID="STR_ACE_Cargo_loadTimeCoefficient">
<English>Load Time Coefficient</English>
<German>Ladezeitmultiplikator</German>
<Japanese>積載時間の係数</Japanese>
<Polish>Współczynnik czasu załadowania</Polish>
<Italian>Coefficente Tempo Caricamento</Italian>
@ -329,6 +330,7 @@
</Key>
<Key ID="STR_ACE_Cargo_loadTimeCoefficient_description">
<English>Modifies how long it takes to load/unload items.\nTime, in seconds, is the size of the item multiplied by this value.</English>
<German>Gibt an, wie lange das Laden / Entladen von Gegenständen dauern soll.\nZeit in Sekunden, die mit der Größe des Gegenstandes multipliziert wird.</German>
<Japanese>アイテムの積み下ろし作業にかかる時間を編集できます。\nアイテムの大きさにこの値が乗法され、時間 (秒) を変更できます。</Japanese>
<Polish>Modyfikuje, jak długo zajmuje załadowywanie/wyładowywanie przedmiotów. \nCzasem, w sekundach, jest wielkość przedmiotu razy jego wartość.</Polish>
<Italian>Modifica quanto tempo ci impiega a caricare o scaricare gli oggetti.\n Tempo, in secondi, è la dimensione dell'oggetto moltiplicata per questo valore</Italian>

View File

@ -21,6 +21,9 @@ LOG("Adding ACE_Settings to CBA_settings");
GVAR(cbaSettings_forcedSettings) = [];
GVAR(cbaSettings_missionSettings) = [];
GVAR(settings) = []; // will stay empty - for BWC?
#ifdef DEBUG_MODE_FULL
GVAR(settingsMovedToSQF) = [];
#endif
// Add Event Handlers:
[QGVAR(setSetting), {
@ -66,6 +69,13 @@ GVAR(settings) = []; // will stay empty - for BWC?
false
} count GVAR(runAtSettingsInitialized);
GVAR(runAtSettingsInitialized) = nil; //cleanup
#ifdef DEBUG_MODE_FULL
INFO_1("checking settingsMovedToSQF [%1]",count GVAR(settingsMovedToSQF));
{
if (isNil _x) then { WARNING_1("setting [%1] NOT moved to sqf",_x); };
} forEach GVAR(settingsMovedToSQF);
#endif
}] call CBA_fnc_addEventHandler;
private _start = diag_tickTime;
@ -81,6 +91,10 @@ for "_index" from 0 to (_countOptions - 1) do {
} else {
WARNING_1("Setting [%1] - Already defined from somewhere else??",_varName);
};
#ifdef DEBUG_MODE_FULL
} else {
GVAR(settingsMovedToSQF) pushBack configName _optionEntry;
#endif
};
};

View File

@ -16,6 +16,7 @@
*/
params ["_state"];
TRACE_1("disableUserInput",_state);
if (_state) then {
disableSerialization;

View File

@ -13,11 +13,11 @@
* is the unit an EOD <BOOL>
*
* Example:
* isSpecialist = [player] call FUNC(isEOD);
* [player] call ace_common_fnc_isEOD
*
* Public: Yes
*/
params ["_unit"];
_unit getVariable ["ACE_isEOD", _unit getUnitTrait "explosiveSpecialist"] // return
(_unit getVariable ["ACE_isEOD", _unit getUnitTrait "explosiveSpecialist"]) in [1, true]

View File

@ -16,7 +16,8 @@
* Public: Yes
*/
params ["_id", "_disable"];
params [["_id", "#", [""]], ["_disable", false, [false]]];
TRACE_2("setDisableUserInputStatus",_id,_disable);
if (isNil QGVAR(DISABLE_USER_INPUT_COLLECTION)) then {
GVAR(DISABLE_USER_INPUT_COLLECTION) = [];

View File

@ -507,6 +507,7 @@
</Key>
<Key ID="STR_ACE_Common_CheckPBOsAction">
<English>Check PBO Action</English>
<German>PBO Überprüfung</German>
<Italian>Controlla Azioni PBO</Italian>
<Chinese>檢查PBO動作</Chinese>
<Chinesesimp>检查PBO动作</Chinesesimp>
@ -517,6 +518,7 @@
</Key>
<Key ID="STR_ACE_Common_CheckPBOsCheckAll">
<English>Check PBO All</English>
<German>Alle PBOs überprüfen</German>
<Italian>Controlla Tutti i PBO</Italian>
<Chinese>檢查所有PBO</Chinese>
<Chinesesimp>检查所有PBO</Chinesesimp>
@ -527,6 +529,7 @@
</Key>
<Key ID="STR_ACE_Common_CheckPBOsWhitelist">
<English>Check PBO Whitelist</English>
<German>PBO Whitelist</German>
<Italian>Controlla Whitelist PBO</Italian>
<Chinese>檢查PBO白名單</Chinese>
<Chinesesimp>检查PBO白名单</Chinesesimp>
@ -1004,6 +1007,7 @@
</Key>
<Key ID="STR_ACE_Common_Always">
<English>Always</English>
<German>Immer</German>
<Japanese>常に</Japanese>
<Russian>Всегда</Russian>
</Key>
@ -1015,7 +1019,7 @@
<German>Überall</German>
<Czech>Kdekoliv</Czech>
<Portuguese>Qualquer lugar</Portuguese>
<French>PArtout</French>
<French>Partout</French>
<Hungarian>Akárhol</Hungarian>
<Italian>Ovunque</Italian>
<Japanese>どこでも</Japanese>
@ -1084,11 +1088,13 @@
<Key ID="STR_ACE_Common_Confirm">
<English>Confirm</English>
<Japanese>確認</Japanese>
<German>Bestätigen</German>
<Russian>Подтвердить</Russian>
</Key>
<Key ID="STR_ACE_Common_Never">
<English>Never</English>
<Japanese>行わない</Japanese>
<German>Nie</German>
<Russian>Никогда</Russian>
</Key>
<Key ID="STR_ACE_Common_VehiclesOnly">
@ -1282,6 +1288,7 @@
</Key>
<Key ID="STR_ACE_Common_FlagBlack">
<English>Flag (ACE - Black)</English>
<German>Flagge (Ace - Schwarz)</German>
<Chinesesimp>旗帜(ACE-黑色):</Chinesesimp>
<Chinese>旗幟(ACE-黑色)</Chinese>
<Italian>Bandiera (ACE - Nera)</Italian>
@ -1291,6 +1298,7 @@
</Key>
<Key ID="STR_ACE_Common_FlagWhite">
<English>Flag (ACE - White)</English>
<German>Flagge (Ace - Weiß)</German>
<Chinesesimp>旗帜(ACE-白色):</Chinesesimp>
<Chinese>旗幟(ACE-白色)</Chinese>
<Italian>Bandiera (ACE - Bianca)</Italian>

View File

@ -15,11 +15,13 @@
</Key>
<Key ID="STR_ACE_CookOff_enable_hd_name">
<English>Damage handling and turret effects</English>
<German>Schadensberechnung und Geschützturmeffekte</German>
<Japanese>損傷処理と砲塔の効果</Japanese>
<Russian>Обработка урона и эффектов срыва башни</Russian>
</Key>
<Key ID="STR_ACE_CookOff_enable_hd_tooltip">
<English>Changes damage handling for cook off and turret explosion effects</English>
<German>Ändert die Schadensberechnung für die Durchzündung und die Explosionseffekte des Geschützturmes</German>
<Japanese>誘爆の損傷処理と砲塔の爆発効果を変更します。</Japanese>
<Russian>Изменяет обработку урона для возгорания и эффекта срыва башни</Russian>
</Key>

View File

@ -73,7 +73,7 @@ class CfgVehicles {
};
class GVAR(kordTripodLow): GVAR(kordTripod) {
class ADDON {
disassembleTo = QGVAR(kordCarryTripod);
disassembleTo = QGVAR(kordCarryTripodLow);
};
};
class GVAR(sag30Tripod): GVAR(baseTripod) {

View File

@ -49,7 +49,7 @@ class CfgWeapons {
};
class GVAR(kordCarryTripodLow): GVAR(kordCarryTripod) {
class ADDON {
class ADDON: ADDON {
deploy = QGVAR(kordTripodLow);
};
displayName = CSTRING(kordTripodFoldedLow_displayName);

View File

@ -81,6 +81,7 @@
</Key>
<Key ID="STR_ACE_Dogtags_IGUI_Description">
<English>Onscreen display for checking dogtags</English>
<German>Anzeige um Hundemarke zu überprüfen</German>
<Chinese>在畫面中顯示檢查兵籍牌</Chinese>
<Japanese>確認中のドッグタグを画面上で表示します</Japanese>
<Italian>Display su schermo per il controllo delle piastrine</Italian>

View File

@ -164,7 +164,7 @@ class CfgAmmo {
class ACE_IEDLandSmall_Command_Ammo: IEDLandSmall_Remote_Ammo {
mineTrigger = "RemoteTrigger";
};
class ACE_IEDLandSmall_Range_Ammo: IEDLandBig_Remote_Ammo {
class ACE_IEDLandSmall_Range_Ammo: IEDLandSmall_Remote_Ammo {
mineTrigger = "RangeTriggerShort";
};

View File

@ -1021,6 +1021,7 @@
</Key>
<Key ID="STR_ACE_Explosives_statExploRange">
<English>Explosive range</English>
<German>Explosionsradius</German>
<French>Portée du détonateur</French>
<Japanese>爆発範囲</Japanese>
<Chinesesimp>爆炸范围</Chinesesimp>
@ -1031,6 +1032,7 @@
</Key>
<Key ID="STR_ACE_Explosives_ExplosiveTimer">
<English>Explosive Timer</English>
<German>Detonationszeit</German>
<Italian>Timer di detonazione</Italian>
<Japanese>爆発タイマー</Japanese>
<Polish>Czasomierz Wybuchu</Polish>

View File

@ -147,6 +147,7 @@
</Key>
<Key ID="STR_ACE_Fastroping_Interaction_deployRopes12">
<English>Deploy 12m ropes</English>
<German>12m Seile einsetzen</German>
<French>Déployer les cordes 12m</French>
<Japanese>12m ロープを展開</Japanese>
<Polish>Wysuń linę o długości 12 m.</Polish>
@ -154,6 +155,7 @@
</Key>
<Key ID="STR_ACE_Fastroping_Interaction_deployRopes15">
<English>Deploy 15m ropes</English>
<German>15m Seile einsetzen</German>
<French>Déployer les cordes 15m</French>
<Japanese>15m ロープを展開</Japanese>
<Polish>Wysuń linę o długości 15 m.</Polish>
@ -161,6 +163,7 @@
</Key>
<Key ID="STR_ACE_Fastroping_Interaction_deployRopes18">
<English>Deploy 18m ropes</English>
<German>18m Seile einsetzen</German>
<French>Déployer les cordes 18m</French>
<Japanese>18m ロープを展開</Japanese>
<Polish>Wysuń linę o długości 18 m.</Polish>
@ -168,6 +171,7 @@
</Key>
<Key ID="STR_ACE_Fastroping_Interaction_deployRopes27">
<English>Deploy 27m ropes</English>
<German>27m Seile einsetzen</German>
<French>Déployer les cordes 27m</French>
<Japanese>27m ロープを展開</Japanese>
<Polish>Wysuń linę o długości 27 m.</Polish>
@ -175,6 +179,7 @@
</Key>
<Key ID="STR_ACE_Fastroping_Interaction_deployRopes36">
<English>Deploy 36m ropes</English>
<German>36m Seile einsetzen</German>
<French>Déployer les cordes 36m</French>
<Japanese>36m ロープを展開</Japanese>
<Polish>Wysuń linę o długości 36 m.</Polish>
@ -182,6 +187,7 @@
</Key>
<Key ID="STR_ACE_Fastroping_Ropesupply">
<English>[ACE] Ropes Supply crate</English>
<German>[ACE] Seil Versorgungskiste</German>
<French>[ACE] Caisse de Cordes</French>
<Japanese>[ACE] ロープ収納箱</Japanese>
<Polish>Skrzynia z linami ACE</Polish>
@ -189,6 +195,7 @@
</Key>
<Key ID="STR_ACE_Fastroping_descriptionShort">
<English>Used to do deploy ropes from a compatibile helicopter</English>
<German>Wird zum Bereitstellen von Seilen aus einem kompatiblen Hubschrauber verwendet</German>
<French>Utilisé pour déployer des cordes depuis un hélicoptère compatible</French>
<Japanese>対応するヘリコプターからロープを展開する為に使用されます</Japanese>
<Polish>Używane do opuszczania lin z kompatybilnych smigłowców</Polish>
@ -196,6 +203,7 @@
</Key>
<Key ID="STR_ACE_Fastroping_Rope_12_Display">
<English>Rope 12.2 meters</English>
<German>12.2 Meter Seil</German>
<French>Corde 12.2 mètres</French>
<Japanese>ロープ (12.2 メートル)</Japanese>
<Polish>Lina, długość 12,2 m.</Polish>
@ -203,6 +211,7 @@
</Key>
<Key ID="STR_ACE_Fastroping_Rope_15_Display">
<English>Rope 15.2 meters</English>
<German>15.2 Meter Seil</German>
<French>Corde 15.2 mètres</French>
<Japanese>ロープ (15.2 メートル)</Japanese>
<Polish>Lina, długość 15,2 m.</Polish>
@ -210,6 +219,7 @@
</Key>
<Key ID="STR_ACE_Fastroping_Rope_18_Display">
<English>Rope 18.3 meters</English>
<German>18.3 Meter Seil</German>
<French>Corde 18.3 mètres</French>
<Japanese>ロープ (18.3 メートル)</Japanese>
<Polish>Lina, długość 18,3 m.</Polish>
@ -217,6 +227,7 @@
</Key>
<Key ID="STR_ACE_Fastroping_Rope_27_Display">
<English>Rope 27.4 meters</English>
<German>27.4 Meter Seil</German>
<French>Corde 27.4 mètres</French>
<Japanese>ロープ (27.4 メートル)</Japanese>
<Polish>Lina, długość 27,4 m.</Polish>
@ -224,6 +235,7 @@
</Key>
<Key ID="STR_ACE_Fastroping_Rope_36_Display">
<English>Rope 36.6 meters</English>
<German>36.6 Meter Seil</German>
<French>Corde 36.6 mètres</French>
<Japanese>ロープ (36.6 メートル)</Japanese>
<Polish>Lina, długość 36,6 m.</Polish>
@ -231,6 +243,7 @@
</Key>
<Key ID="STR_ACE_Fastroping_setting_requireRopeItems_displayName">
<English>Require rope item to deploy</English>
<German>Seil-Item zum aufbauen benötigt</German>
<French>Exiger une corde pour déployer</French>
<Japanese>展開にはロープ アイテムを必須に</Japanese>
<Polish>Wymaga przedmiotu typu lina </Polish>

View File

@ -93,6 +93,7 @@
</Key>
<Key ID="STR_ACE_Flashlights_statMapLightColor">
<English>Map light color</English>
<German>Farbe des Kartenlichts</German>
<French>Couleur de la lampe sur carte</French>
<Japanese>光の色</Japanese>
<Chinesesimp>地图上手电的颜色</Chinesesimp>

View File

@ -33,6 +33,7 @@
</Key>
<Key ID="STR_ACE_gforces_statGReduction">
<English>G-force reduction</English>
<German>G-Kräfte Reduzierung</German>
<French>Reduction des Gs</French>
<Japanese>耐 G 性</Japanese>
<Chinesesimp>减少G力</Chinesesimp>

View File

@ -284,6 +284,7 @@
</Key>
<Key ID="STR_ACE_Hearing_statHearingProtection">
<English>Hearing protection</English>
<German>Gehörschutz</German>
<French>Protection auditive</French>
<Japanese>聴覚保護</Japanese>
<Chinesesimp>听力保护</Chinesesimp>
@ -294,6 +295,7 @@
</Key>
<Key ID="STR_ACE_Hearing_statHearingLowerVolume">
<English>Volume muffling</English>
<German>Lautstärkedämpfung</German>
<French>Étouffement des sons</French>
<Japanese>音量低下</Japanese>
<Chinesesimp>降低音量</Chinesesimp>
@ -304,6 +306,7 @@
</Key>
<Key ID="STR_ACE_Hearing_earplugsVolume_DisplayName">
<English>Earplugs Volume</English>
<German>Lautstärke Ohrenstöpsel</German>
<Japanese>耳栓時の音量</Japanese>
<Chinesesimp>耳塞时音量</Chinesesimp>
<Chinese>耳塞時音量</Chinese>
@ -313,6 +316,7 @@
</Key>
<Key ID="STR_ACE_Hearing_earplugsVolume_Description">
<English>Volume when using earplugs.</English>
<German>Lautstärke wenn man Ohrenstöpsel benutzt</German>
<Japanese>耳栓使用時の音量を決定します。</Japanese>
<Chinesesimp>决定带上耳塞时的音量</Chinesesimp>
<Chinese>使用耳塞時音量</Chinese>
@ -322,6 +326,7 @@
</Key>
<Key ID="STR_ACE_Hearing_unconsciousnessVolume_DisplayName">
<English>Unconscious Volume</English>
<German>Lautstärke Bewusstlosigkeit</German>
<Japanese>気絶時の音量</Japanese>
<Chinesesimp>无意识时音量</Chinesesimp>
<Chinese>昏迷時音量</Chinese>
@ -331,6 +336,7 @@
</Key>
<Key ID="STR_ACE_Hearing_unconsciousnessVolume_Description">
<English>Volume when unconscious.</English>
<German>Lautstärke während man Bewusstlos ist</German>
<Japanese>気絶時の音量を決定します。</Japanese>
<Chinesesimp>决定处于无意识时的音量</Chinesesimp>
<Chinese>昏迷時使用耳塞的音量</Chinese>

View File

@ -27,6 +27,7 @@
</Key>
<Key ID="STR_ACE_HOT_hotMissile">
<English>HOT Missile</English>
<German>Lenkflugkörper</German>
<Polish>Pocisk HOT</Polish>
<Italian>Missile HOT</Italian>
<Japanese>HOT ミサイル</Japanese>
@ -34,6 +35,7 @@
</Key>
<Key ID="STR_ACE_HOT_hot1">
<English>HOT 1</English>
<German>HOT 1</German>
<Polish>HOT 1</Polish>
<Italian>HOT 1</Italian>
<Japanese>HOT 1</Japanese>
@ -41,6 +43,7 @@
</Key>
<Key ID="STR_ACE_HOT_hot2">
<English>HOT 2</English>
<German>HOT 2</German>
<Polish>HOT 2</Polish>
<Italian>HOT 2</Italian>
<Japanese>HOT 2</Japanese>
@ -48,6 +51,7 @@
</Key>
<Key ID="STR_ACE_HOT_hot2mp">
<English>HOT 2MP</English>
<German>HOT 2MP</German>
<Polish>HOT 2MP</Polish>
<Italian>HOT 2MP</Italian>
<Japanese>HOT 2MP</Japanese>
@ -55,6 +59,7 @@
</Key>
<Key ID="STR_ACE_HOT_hot3">
<English>HOT 3</English>
<German>HOT 3</German>
<Polish>HOT 3</Polish>
<Italian>HOT 3</Italian>
<Japanese>HOT 3</Japanese>
@ -62,6 +67,7 @@
</Key>
<Key ID="STR_ACE_HOT_missileType_Description_AP">
<English>Wire-Guided Missile (Anti-Personnel)</English>
<German>Anti Personen Lenkflugkörper</German>
<Polish>Pocisk kierowany przewodowo (przeciwpiechotny)</Polish>
<Italian>Missile filoguidato antiuomo</Italian>
<Japanese>ワイヤ有線誘導ミサイル (対人)</Japanese>
@ -69,6 +75,7 @@
</Key>
<Key ID="STR_ACE_HOT_hot1_1">
<English>1x HOT 1 [ACE]</English>
<German>1x HOT 1 [ACE]</German>
<Polish>1x HOT 1 [ACE]</Polish>
<Italian>1x HOT1 [ACE]</Italian>
<Japanese>1x HOT 1 [ACE]</Japanese>
@ -76,6 +83,7 @@
</Key>
<Key ID="STR_ACE_HOT_hot1_3">
<English>3x HOT 1 [ACE]</English>
<German>3x HOT 1 [ACE]</German>
<Polish>3x HOT 1 [ACE]</Polish>
<Italian>3x HOT 1 [ACE]</Italian>
<Japanese>3x HOT 1 [ACE]</Japanese>
@ -83,6 +91,7 @@
</Key>
<Key ID="STR_ACE_HOT_hot1_4">
<English>4x HOT 1 [ACE]</English>
<German>4x HOT 1 [ACE]</German>
<Polish>4x HOT 1 [ACE]</Polish>
<Italian>4x HOT 1 [ACE]</Italian>
<Japanese>4x HOT 1 [ACE]</Japanese>
@ -90,6 +99,7 @@
</Key>
<Key ID="STR_ACE_HOT_hot2_1">
<English>1x HOT 2 [ACE]</English>
<German>1x HOT 2 [ACE]</German>
<Polish>1x HOT 2 [ACE]</Polish>
<Italian>1x HOT 2 [ACE]</Italian>
<Japanese>1x HOT 2 [ACE]</Japanese>
@ -97,6 +107,7 @@
</Key>
<Key ID="STR_ACE_HOT_hot2_3">
<English>3x HOT 2 [ACE]</English>
<German>3x HOT 2 [ACE]</German>
<Polish>3x HOT 2 [ACE]</Polish>
<Italian>3x HOT 2 [ACE]</Italian>
<Japanese>3x HOT 2 [ACE]</Japanese>
@ -104,6 +115,7 @@
</Key>
<Key ID="STR_ACE_HOT_hot2_4">
<English>4x HOT 2 [ACE]</English>
<German>4x HOT 2 [ACE]</German>
<Polish>4x HOT 2 [ACE]</Polish>
<Italian>4x HOT 2 [ACE]</Italian>
<Japanese>4x HOT 2 [ACE]</Japanese>
@ -111,6 +123,7 @@
</Key>
<Key ID="STR_ACE_HOT_hot2mp_1">
<English>1x HOT 2MP [ACE]</English>
<German>1x HOT 2MP [ACE]</German>
<Polish>1x HOT 2MP [ACE]</Polish>
<Italian>1x HOT 2MP [ACE]</Italian>
<Japanese>1x HOT 2MP [ACE]</Japanese>
@ -118,6 +131,7 @@
</Key>
<Key ID="STR_ACE_HOT_hot2mp_3">
<English>3x HOT 2MP [ACE]</English>
<German>3x HOT 2MP [ACE]</German>
<Polish>3x HOT 2MP [ACE]</Polish>
<Italian>3x HOT 2MP [ACE]</Italian>
<Japanese>3x HOT 2MP [ACE]</Japanese>
@ -125,6 +139,7 @@
</Key>
<Key ID="STR_ACE_HOT_hot2mp_4">
<English>4x HOT 2MP [ACE]</English>
<German>4x HOT 2MP [ACE]</German>
<Polish>4x HOT 2MP [ACE]</Polish>
<Italian>4x HOT 2MP [ACE]</Italian>
<Japanese>4x HOT 2MP [ACE]</Japanese>
@ -132,6 +147,7 @@
</Key>
<Key ID="STR_ACE_HOT_hot3_1">
<English>1x HOT 3 [ACE]</English>
<German>1x HOT 3 [ACE]</German>
<Polish>1x HOT 3 [ACE]</Polish>
<Italian>1x HOT 3 [ACE]</Italian>
<Japanese>1x HOT 3 [ACE]</Japanese>
@ -139,6 +155,7 @@
</Key>
<Key ID="STR_ACE_HOT_hot3_4">
<English>4x HOT 3 [ACE]</English>
<German>4x HOT 3 [ACE]</German>
<Polish>4x HOT 3 [ACE]</Polish>
<Italian>4x HOT 3 [ACE]</Italian>
<Japanese>4x HOT 3 [ACE]</Japanese>
@ -146,6 +163,7 @@
</Key>
<Key ID="STR_ACE_HOT_hot3_3">
<English>3x HOT 3 [ACE]</English>
<German>3x HOT 3 [ACE]</German>
<Polish>3x HOT 3 [ACE]</Polish>
<Italian>3x HOT 3 [ACE]</Italian>
<Japanese>3x HOT 3 [ACE]</Japanese>

View File

@ -74,4 +74,38 @@ GVAR(lastTimeSearchedActions) = -1000;
// Init zeus menu
[] call FUNC(compileMenuZeus);
// Handle addActionToClass with Inheritance flag set (CAManBase actions are seperated for speed)
GVAR(inheritedActionsAll) = [];
GVAR(inheritedClassesAll) = [];
GVAR(inheritedActionsMan) = [];
GVAR(inheritedClassesMan) = [];
["All", "InitPost", {
BEGIN_COUNTER(InitPost);
params ["_object"];
private _type = typeOf _object;
if (GVAR(inheritedClassesAll) pushBackUnique _type == -1) exitWith { END_COUNTER(InitPost); };
{
_x params ["_objectType", "_typeNum", "_parentPath", "_action"];
if (_object isKindOf _objectType) then {
[_type, _typeNum, _parentPath, _action] call FUNC(addActionToClass);
};
} forEach GVAR(inheritedActionsAll);
END_COUNTER(InitPost);
}] call CBA_fnc_addClassEventHandler;
["CAManBase", "InitPost", {
BEGIN_COUNTER(InitPost);
params ["_object"];
private _type = typeOf _object;
if (GVAR(inheritedClassesMan) pushBackUnique _type == -1) exitWith { END_COUNTER(InitPost); };
{
_x params ["_typeNum", "_parentPath", "_action"];
[_type, _typeNum, _parentPath, _action] call FUNC(addActionToClass);
} forEach GVAR(inheritedActionsMan);
END_COUNTER(InitPost);
}] call CBA_fnc_addClassEventHandler;
ADDON = true;

View File

@ -25,21 +25,24 @@ if (!params [["_objectType", "", [""]], ["_typeNum", 0, [0]], ["_parentPath", []
ERROR("Bad Params");
[]
};
TRACE_4("params",_objectType,_typeNum,_parentPath,_action);
TRACE_4("addActionToClass",_objectType,_typeNum,_parentPath,_action);
if (param [4, false, [false]]) exitwith {
if (isNil QGVAR(inheritedActions)) then {GVAR(inheritedActions) = [];};
private _index = GVAR(inheritedActions) pushBack [[], _typeNum, _parentPath, _action];
private _initEH = compile format ['
params ["_object"];
private _typeOf = typeOf _object;
(GVAR(inheritedActions) select %1) params ["_addedClasses", "_typeNum", "_parentPath", "_action"];
if (_typeOf in _addedClasses) exitWith {};
_addedClasses pushBack _typeOf;
[_typeOf, _typeNum, _parentPath, _action] call FUNC(addActionToClass);
', _index];
TRACE_2("Added inheritable action",_objectType,_index);
[_objectType, "init", _initEH, true, [], true] call CBA_fnc_addClassEventHandler;
BEGIN_COUNTER(addAction);
if (_objectType == "CAManBase") then {
GVAR(inheritedActionsMan) pushBack [_typeNum, _parentPath, _action];
{
[_x, _typeNum, _parentPath, _action] call FUNC(addActionToClass);
} forEach GVAR(inheritedClassesMan);
} else {
GVAR(inheritedActionsAll) pushBack [_objectType, _typeNum, _parentPath, _action];
{
if (_x isKindOf _objectType) then {
[_x, _typeNum, _parentPath, _action] call FUNC(addActionToClass);
};
} forEach GVAR(inheritedClassesAll);
};
END_COUNTER(addAction);
// Return the full path
(_parentPath + [_action select 0])

View File

@ -122,7 +122,7 @@ private _actions = [_actionsCfg, 0] call _recurseFnc;
// ace_interaction_fnc_addPassengerAction expects ACE_MainActions to be first
// Other mods can change the order that configs are added, so we should verify this now and resort if needed
if (_objectType isKindOf "CaManBase") then {
if (_objectType isKindOf "CAManBase") then {
if ((((_actions select 0) select 0) select 0) != "ACE_MainActions") then {
INFO_1("ACE_MainActions not first for man [%1]",_objectType);
private _mainActions = [];

View File

@ -448,6 +448,7 @@
</Key>
<Key ID="STR_ACE_Interact_Menu_SelectorColor">
<English>Selector Color</English>
<German>Farbauswahl</German>
<Japanese>セレクターの色</Japanese>
<Chinesesimp>选择器颜色</Chinesesimp>
<Chinese>選單的顏色</Chinese>

View File

@ -844,6 +844,7 @@
</Key>
<Key ID="STR_ACE_Interaction_Flip">
<English>Flip</English>
<German>Umdrehen</German>
<Russian>Перевернуть</Russian>
<Japanese>ひっくり返す</Japanese>
<Chinese></Chinese>
@ -1091,6 +1092,7 @@
</Key>
<Key ID="STR_ACE_Interaction_PullOutBody">
<English>Pull out body</English>
<German>Person herausziehen</German>
<Russian>Вытащить тело</Russian>
<Japanese>身体を引き出す</Japanese>
<Italian>Estrai il corpo</Italian>

View File

@ -31,7 +31,7 @@ _vehicle setVariable [QGVAR(targetObject), _targetObject, true];
private _laserMethod = QFUNC(findLaserSource);
private _vehicleSourceSelection = "";
if (_vehicle isKindOf "CaManBase") then {
if (_vehicle isKindOf "CAManBase") then {
_vehicleSourceSelection = "pilot";
} else {
{ // Go through turrets on vehicle and find the laser

View File

@ -3,6 +3,7 @@
<Package name="MagazineRepack">
<Key ID="STR_ACE_MagazineRepack_DisplayName">
<English>Magazine Repack</English>
<German>Magazine umpacken</German>
<Italian>Riempimento Caricatori</Italian>
<Chinese>重新整理彈匣</Chinese>
<Chinesesimp>重新整理弹匣</Chinesesimp>

View File

@ -7,7 +7,7 @@ class CfgPatches {
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {
"A3_Data_F_Tank_Loadorder",
"A3_Data_F_Enoch_Loadorder",
"A3_Data_F_Mod_Loadorder",
// CBA
"cba_ui",

View File

@ -9,7 +9,7 @@
#define VERSION_AR MAJOR,MINOR,PATCHLVL,BUILD
// MINIMAL required version for the Mod. Components can specify others..
#define REQUIRED_VERSION 1.88
#define REQUIRED_VERSION 1.94
#define REQUIRED_CBA_VERSION {3,11,2}
#ifdef COMPONENT_BEAUTIFIED

View File

@ -24,8 +24,10 @@ TRACE_2("params",_dir,_params);
if ((_button == 0) && {GVAR(freedrawing) || _ctrlKey}) exitWith {
if (GVAR(freedrawing) && {_dir == 0}) then {
GVAR(freedrawing) = false;
GVAR(drawPosEnd) = _control ctrlMapScreenToWorld [_screenPosX, _screenPosY];
TRACE_2("Ending Line",GVAR(freedrawing),GVAR(drawPosEnd));
if (_shiftKey) exitWith {
TRACE_1("using vanilla straight line",_shiftKey);
};
TRACE_2("Ending Line",GVAR(freedrawing),GVAR(freeDrawingData));
[{
if (allMapMarkers isEqualTo []) exitWith {};
private _markerName = allMapMarkers select (count allMapMarkers - 1);

View File

@ -1,7 +1,23 @@
class CfgVehicles {
// Backwards compatibility
// Left as dumb modules so that old missions don't error about missing vehicles
class Logic;
// Left as dumb logic so that old missions don't error about missing vehicle
class ACE_moduleMedicalSettings: Logic {
scope = 1;
class Module_F: Logic {
class EventHandlers;
};
class ACE_moduleMedicalSettings: Module_F {
author = ECSTRING(common,ACETeam);
scope = 1;
displayName = "[ACE] Retired Medical module (will have no effect)";
class EventHandlers: EventHandlers {
init = "diag_log text format ['[ACE] (Medical) Warning retired module [%1] placed (will have no effect)', typeOf (_this select 0)];";
};
};
class ACE_moduleBasicMedicalSettings: ACE_moduleMedicalSettings {};
class ACE_moduleAdvancedMedicalSettings: ACE_moduleMedicalSettings {};
class ACE_moduleReviveSettings: ACE_moduleMedicalSettings {};
class ACE_moduleAssignMedicRoles: ACE_moduleMedicalSettings {};
class ACE_moduleAssignMedicVehicle: ACE_moduleMedicalSettings {};
class ACE_moduleAssignMedicalFacility: ACE_moduleMedicalSettings {};
class ACE_moduleMedicalMenuSettings: ACE_moduleMedicalSettings {};
};

View File

@ -17,3 +17,7 @@ class CfgPatches {
#include "ACE_Settings.hpp"
#include "CfgEventHandlers.hpp"
#include "CfgVehicles.hpp"
class ACE_Tests {
medicalHitpoints = QPATHTOF(dev\test_hitpointConfigs.sqf);
};

View File

@ -23,7 +23,11 @@
if (!isNull cursorTarget && {cursorTarget isKindOf "CAManBase"}) then {
private _targetState = [cursorTarget, EGVAR(medical,STATE_MACHINE)] call CBA_statemachine_fnc_getCurrentState;
drawIcon3D ["", [0.6, 0, 0, 1], cursorTarget modelToWorldVisual (cursorTarget selectionPosition "pelvis"), 0, 0, 0, format ["State: %1", _targetState], 2, 40 * pixelH, "RobotoCondensed"];
private _targetStateAI = "";
if (!isNil QEGVAR(medical_ai,stateMachine)) then {
_targetStateAI = [cursorTarget, EGVAR(medical_ai,stateMachine)] call CBA_statemachine_fnc_getCurrentState;
};
drawIcon3D ["", [0.6, 0, 0, 1], cursorTarget modelToWorldVisual (cursorTarget selectionPosition "pelvis"), 0, 0, 0, format ["State: %1 / %2", _targetState,_targetStateAI], 2, 40 * pixelH, "RobotoCondensed"];
};
}, 0 ,[]] call CBA_fnc_addPerFrameHandler;
}, []] call CBA_fnc_waitUntilAndExecute;

View File

@ -0,0 +1,33 @@
// PabstMirror
// ["medicalHitpoints"] call ace_common_fnc_runTests;
// execVM "\z\ace\addons\medical\dev\test_hitpointConfigs.sqf"
#include "\z\ace\addons\medical\script_component.hpp"
// UAV-AI should get filtered by scope check
private _mans = configProperties [configFile >> "CfgVehicles", "(isClass _x) && {(getNumber (_x >> 'scope')) == 2} && {configName _x isKindOf 'CAManBase'}", true];
INFO_1("Checking mans for medical hitpoints [%1 mans]",count _mans);
private _testPass = true;
{
private _typeOf = configName _x;
private _hitpoints = (configProperties [_x >> "HitPoints", "isClass _x", true]) apply {configName _x};
// _typeOf createUnit [position player, group player, "z = this"];
// deleteVehicle z;
private _lastHitpoint = (_hitpoints param [(count _hitpoints) - 1, "#array"]);
if (_lastHitpoint != "ACE_HDBracket") then {
WARNING_2("%1 has bad last hitpoint: %2",_typeOf,_hitpoints);
_testPass = false;
};
if (((_hitpoints findIf {_x == "HitLeftArm"}) == -1) || {(_hitpoints findIf {_x == "HitLeftArm"}) == -1}
|| {(_hitpoints findIf {_x == "HitLeftLeg"}) == -1} || {(_hitpoints findIf {_x == "HitRightLeg"}) == -1}
|| {(_hitpoints findIf {_x == "HitHead"}) == -1} || {(_hitpoints findIf {_x == "HitBody"}) == -1}) then {
WARNING_2("%1 missing ace hitpoints: %2",_typeOf,_hitpoints);
_testPass = false;
};
} forEach _mans;
_testPass

View File

@ -19,12 +19,16 @@
_return pushBack "";
// State:
private _hasStableVitals = [_unit] call EFUNC(medical_status,hasStableVitals);
private _targetState = [_unit, EGVAR(medical,STATE_MACHINE)] call CBA_statemachine_fnc_getCurrentState;
if (!local _unit) then {_targetState = "NotLocal";};
private _color = switch (_targetState) do {case "Default": {"33FF33"}; case "Injured": {"FF3333"}; case "Unconscious": {"FF8833"}; case "CardiacArrest": {"FF33AA"}; default {"555555"}};
private _unconcFlag = if IS_UNCONSCIOUS(_unit) then {"[<t color='#FFFFFF'>U</t>]"} else {""};
_return pushBack format ["<t color='#%1'>State: %2</t> [StableVitals: %3] %4", _color, _targetState, _hasStableVitals, _unconcFlag];
_return pushBack format ["<t color='#%1'>State: %2</t>", _color, _targetState];
private _hasStableVitals = ["N", "Y"] select ([_unit] call EFUNC(medical_status,hasStableVitals));
private _hasStableCondition = ["N", "Y"] select ([_unit] call EFUNC(medical_status,isInStableCondition));
private _unconcFlag = if IS_UNCONSCIOUS(_unit) then {"[<t color='#BBFFBB'>U</t>]"} else {""};
private _timeLeft = _unit getVariable [QEGVAR(medical_statemachine,cardiacArrestTimeLeft), -1];
private _cardiactArrestFlag = if IN_CRDC_ARRST(_unit) then {format ["[<t color='#BBBBFF'>CA</t> %1]", _timeLeft toFixed 1]} else {""};
_return pushBack format ["[StableVitals: %1] [StableCon: %2] %3 %4", _hasStableVitals, _hasStableCondition, _unconcFlag, _cardiactArrestFlag];
// Blood:
private _bloodVolume = GET_BLOOD_VOLUME(_unit);
@ -85,7 +89,7 @@
// Wounds:
_return pushBack "------- Wounds: -------";
private _wounds = _unit getVariable [QEGVAR(medical,openWounds), []];
private _wounds = GET_OPEN_WOUNDS(_unit);
{
_x params ["_xClassID", "_xBodyPartN", "_xAmountOf", "_xBleeding", "_xDamage"];
_return pushBack format ["%1: [%2] [x%3] [Bld: %4] [Dmg: %5]", ALL_SELECTIONS select _xBodyPartN, _xClassID, _xAmountOf toFixed 1, _xBleeding toFixed 4, _xDamage toFixed 2];
@ -93,7 +97,7 @@
// Bandaged Wounds:
_return pushBack "------- Bandaged Wounds: -------";
private _wounds = _unit getVariable [QEGVAR(medical,bandagedWounds), []];
private _wounds = GET_BANDAGED_WOUNDS(_unit);
{
_x params ["_xClassID", "_xBodyPartN", "_xAmountOf", "_xBleeding", "_xDamage"];
_return pushBack format ["%1: [%2] [x%3] [Bld: %4] [Dmg: %5]", ALL_SELECTIONS select _xBodyPartN, _xClassID, _xAmountOf toFixed 1, _xBleeding toFixed 4, _xDamage toFixed 2];
@ -101,7 +105,7 @@
// Stitched Wounds:
_return pushBack "------- Stitched Wounds: -------";
private _wounds = _unit getVariable [QEGVAR(medical,stitchedWounds), []];
private _wounds = GET_STITCHED_WOUNDS(_unit);
{
_x params ["_xClassID", "_xBodyPartN", "_xAmountOf", "_xBleeding", "_xDamage"];
_return pushBack format ["%1: [%2] [x%3] [Bld: %4] [Dmg: %5]", ALL_SELECTIONS select _xBodyPartN, _xClassID, _xAmountOf toFixed 1, _xBleeding toFixed 4, _xDamage toFixed 2];

View File

@ -2,6 +2,7 @@
/*
* Author: PabstMirror
* Public interface to allow external modules to safely adjust pain levels.
* Added pain can be positive or negative (Note: ignores painCoefficient setting)
*
* Arguments:
* 0: The patient <OBJECT>

View File

@ -61,6 +61,7 @@ if (_knockOut) then {
}, [_unit], _minWaitingTime] call CBA_fnc_waitAndExecute;
};
if (EGVAR(medical,spontaneousWakeUpChance) > 0) then {
TRACE_1("setting lastWakeUpCheck",_minWaitingTime);
_unit setVariable [QEGVAR(medical,lastWakeUpCheck), CBA_missionTime + _minWaitingTime - SPONTANEOUS_WAKE_UP_INTERVAL];
};
};

View File

@ -1,34 +1,30 @@
// CBA Settings [ADDON: ace_medical]:
private _categoryArray = [LELSTRING(medical,Category), "?"];
// todo: Check the description is still accurate
[
QGVAR(spontaneousWakeUpChance), "SLIDER",
[LSTRING(MedicalSettings_spontaneousWakeUpChance_DisplayName), LSTRING(MedicalSettings_spontaneousWakeUpChance_Description)],
_categoryArray,
[0,1,0.05,2], // [min, max, default value, trailing decimals (-1 for whole numbers only)]
true, // isGlobal
{[QGVAR(spontaneousWakeUpChance), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart
QGVAR(limping),
"LIST",
[LSTRING(Limping_DisplayName), LSTRING(Limping_Description)],
LSTRING(Category),
[[0, 1, 2], [ELSTRING(common,Disabled), LSTRING(Limping_LimpOnOpenWounds), LSTRING(Limping_LimpRequiresStitching)], 1],
true,
{[QGVAR(limping), _this] call EFUNC(common,cbaSettings_settingChanged)},
true
] call CBA_settings_fnc_init;
[
QEGVAR(medical,limping), "LIST",
[LSTRING(setting_limping_DisplayName), LSTRING(setting_limping_Description)],
_categoryArray,
[[0,1,2],[LELSTRING(common,disabled), LLSTRING(setting_limping_limpOnOpenWounds), LLSTRING(setting_limping_limpRequiresStitching)], 1], // [values, titles, defaultIndex]
true, // isGlobal
{[QEGVAR(medical,limping), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart
QGVAR(fractures),
"LIST",
[LSTRING(Fractures_DisplayName), LSTRING(Fractures_Description)],
LSTRING(Category),
[[0, 1, 2], [ELSTRING(common,Disabled), LSTRING(Fractures_SplintHealsFully), LSTRING(Fractures_SplintHasEffects)], 1],
true,
{[QGVAR(fractures), _this] call EFUNC(common,cbaSettings_settingChanged)},
true
] call CBA_settings_fnc_init;
[
QEGVAR(medical,fractures), "LIST",
[LSTRING(setting_fractures_DisplayName), LSTRING(setting_fractures_Description)],
_categoryArray,
[[0,1,2],[LELSTRING(common,disabled), LLSTRING(setting_fractures_splintHealsFully), LLSTRING(setting_fractures_splintHasEffects)], 1], // [values, titles, defaultIndex]
true, // isGlobal
{[QEGVAR(medical,fractures), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart
QGVAR(spontaneousWakeUpChance),
"SLIDER",
[LSTRING(SpontaneousWakeUpChance_DisplayName), LSTRING(SpontaneousWakeUpChance_Description)],
LSTRING(Category),
[0, 1, 0.05, 2],
true
] call CBA_settings_fnc_init;

View File

@ -2,7 +2,7 @@
#define COMPONENT_BEAUTIFIED Medical Core
#include "\z\ace\addons\main\script_mod.hpp"
#define DEBUG_MODE_FULL
// #define DEBUG_MODE_FULL
// #define DISABLE_COMPILE_CACHE
// #define ENABLE_PERFORMANCE_COUNTERS

View File

@ -17,117 +17,57 @@
<Chinesesimp>ACE 医疗系统</Chinesesimp>
<Chinese>ACE 醫療系統</Chinese>
</Key>
<Key ID="STR_ACE_Medical_MedicalSettings_level_DisplayName">
<English>Medical Level</English>
<Russian>Сложность медицины</Russian>
<Polish>Poziom medyczny</Polish>
<Spanish>Nivel médico</Spanish>
<German>Stufe des Sanitätssystem</German>
<Czech>Úroveň medického</Czech>
<Portuguese>Nível médico</Portuguese>
<French>Niveau de simulation médicale</French>
<Hungarian>Orvosi szint</Hungarian>
<Italian>Livello Medico</Italian>
<Japanese>医療レベル</Japanese>
<Korean>의료 수준</Korean>
<Chinesesimp>医疗等级</Chinesesimp>
<Chinese>醫療等級</Chinese>
<Key ID="STR_ACE_Medical_SpontaneousWakeUpChance_DisplayName">
<English>Unconscious Wake Up Chance</English>
<German>Wahrscheinlichkeit aufzuwachen</German>
<Japanese>気絶から覚醒する可能性</Japanese>
<Russian>Шанс очнуться при потере сознания</Russian>
</Key>
<Key ID="STR_ACE_Medical_MedicalSettings_level_Description">
<English>What is the medical simulation level?</English>
<Russian>Каков уровень сложности медицинской системы?</Russian>
<Polish>Jaki jest poziom symulacji medycznej?</Polish>
<Spanish>¿Cuál es el nivel de simulación médica?</Spanish>
<German>Wie hoch soll das medizinische Simulationslevel sein?</German>
<Czech>Jaká je úroveň lékařské simulace?</Czech>
<Portuguese>Qual o nível de simulação médica?</Portuguese>
<French>Quel niveau de simulation médicale choisissez-vous?</French>
<Hungarian>Milyen komplex legyen az orvosi szimuláció?</Hungarian>
<Italian>Qual'è il livello di simulazione medica?</Italian>
<Japanese>治療の再現度は?</Japanese>
<Korean>의료 시뮬레이션의 수준</Korean>
<Chinesesimp>选择需要的医疗模拟等级</Chinesesimp>
<Chinese>選擇需要的醫療模擬等級</Chinese>
<Key ID="STR_ACE_Medical_SpontaneousWakeUpChance_Description">
<English>The probablity that a unit with stable vitals will wake up from unconsciousness (checked every 15 seconds).</English>
<German>Wahrscheinlichkeit, dass eine bewusstlose Person mit stabilen Vitalwerten wieder aufwacht ()Überprüfung alle 15 Sekunden)</German>
<Japanese>安定状態にある人が覚醒する確率です。(15 秒毎に確認)</Japanese>
<Russian>Вероятность, что стабилизированный юнит очнется от потери сознания (Проверяется каждые 15 сек)</Russian>
</Key>
<Key ID="STR_ACE_Medical_MedicalSettings_medicSetting_disable">
<English>Disable medics</English>
<Russian>Отключить медиков</Russian>
<Polish>Wyłącz medyków</Polish>
<Spanish>Desactivar médicos</Spanish>
<German>Sanitäter deaktivieren</German>
<Czech>Zakázat zdravotníky</Czech>
<Portuguese>Desativar médicos</Portuguese>
<French>Désactiver les infirmiers</French>
<Hungarian>Orvosok letiltása</Hungarian>
<Italian>Disabilita medici</Italian>
<Japanese>衛生兵を無効化</Japanese>
<Korean>의무병 비활성화</Korean>
<Chinesesimp>关闭医护兵</Chinesesimp>
<Chinese>關閉醫護兵</Chinese>
<Key ID="STR_ACE_Medical_Limping_DisplayName">
<English>Limping</English>
<Russian>Хромота</Russian>
<Japanese>跛行</Japanese>
</Key>
<Key ID="STR_ACE_Medical_MedicalSettings_allowLitterCreation_DisplayName">
<English>Enable Litter</English>
<Russian>Включить мусор</Russian>
<Polish>Aktywuj odpadki</Polish>
<Spanish>Activar restos médicos</Spanish>
<German>Abfälle aktivieren</German>
<Czech>Povolit odpadky</Czech>
<Portuguese>Ativar lixo médico</Portuguese>
<French>Activer les détritus</French>
<Hungarian>Szemét engedélyezése</Hungarian>
<Italian>Abilita Barella</Italian>
<Japanese>医療廃棄物の表示を有効化</Japanese>
<Korean>의료폐기물 활성화</Korean>
<Chinesesimp>启用医疗废弃物</Chinesesimp>
<Chinese>啟用醫療廢棄物</Chinese>
<Key ID="STR_ACE_Medical_Limping_Description">
<English>Limp when unit has leg wounds...(todo)</English>
<Russian>Хромота, когда юнит имеет ранения ног...</Russian>
<Japanese>足を負傷時に引きずって歩くようにします・・・(TODO)</Japanese>
</Key>
<Key ID="STR_ACE_Medical_MedicalSettings_allowLitterCreation_Description">
<English>Enable litter being created upon treatment</English>
<Russian>Включить появление мусора после лечения</Russian>
<Polish>Twórz odpadki medyczne podczas leczenia</Polish>
<Spanish>Activar los restos médicos que se crean en el tratamiento</Spanish>
<German>Aktiviere Abfälle, wenn eine Behandlung durchgeführt wurde</German>
<Czech>Vytváří odpad zdravotnického materiálu pří léčení</Czech>
<Portuguese>Ativar lixo ser criado após tratamento</Portuguese>
<French>Activer la création de détrimus au début des traitements</French>
<Hungarian>Engedélyezi a szemét keletkezését ellátáskor</Hungarian>
<Italian>Abilita la creazione della barella dopo trattamento</Italian>
<Japanese>治療を始めると、医療廃棄物の作成を有効化する</Japanese>
<Korean>의료폐기물이 치료중 주변에 생성되는것을 활성화 합니다</Korean>
<Chinesesimp>本功能启用后,当每次医疗动作结束时,地上会产生相应的医疗废弃物</Chinesesimp>
<Chinese>本功能啟用後,當每次醫療動作結束時,地上會產生相應的醫療廢棄物</Chinese>
<Key ID="STR_ACE_Medical_Limping_LimpOnOpenWounds">
<English>Limp on open wounds</English>
<Russian>Хромота при открытых ранах</Russian>
<Japanese>創傷開放時に跛行</Japanese>
</Key>
<Key ID="STR_ACE_Medical_MedicalSettings_litterCleanUpDelay_DisplayName">
<English>Life time of litter objects</English>
<Russian>Время удаления мусора</Russian>
<Polish>Długość życia odpadków</Polish>
<Spanish>Tiempo de vida de los restos médicos</Spanish>
<German>Dauer des angezeigten Abfalls</German>
<Czech>Životnost pro odpadky</Czech>
<Portuguese>Tempo de vida dos objetos do lixo</Portuguese>
<French>Durée d'affichage des détritus</French>
<Hungarian>Szemétobjektumok élettartama</Hungarian>
<Italian>Tempo di vita delle barelle</Italian>
<Japanese>医療廃棄物の作成限界数を設定</Japanese>
<Korean>의료폐기물 시간제한</Korean>
<Chinesesimp>医疗废弃物存在时间</Chinesesimp>
<Chinese>醫療廢棄物存在時間</Chinese>
<Key ID="STR_ACE_Medical_Limping_LimpRequiresStitching">
<English>Limp on open or bandaged wounds</English>
<Russian>Хромота при открытых или забинтованых ранах</Russian>
<Japanese>負傷時は引きずって歩くようにします</Japanese>
</Key>
<Key ID="STR_ACE_Medical_MedicalSettings_litterCleanUpDelay_Description">
<English>How long should litter objects stay? In seconds. -1 is forever.</English>
<Russian>Как долго мусор будет оставаться на земле? В секундах. -1 означает бесконечное время.</Russian>
<Polish>Ile czasu musi upłynąć, aby odpadki zaczęły znikać? W sekundach. -1 dla nieskończoności.</Polish>
<Spanish>¿Por cuánto tiempo deben permanecer los restos médicos? En segundos. -1 es para siempre.</Spanish>
<German>Wie lange sollen Abfälle am Boden liegen (in Sekunden)? -1 ist für immer.</German>
<Czech>Za jak dlouho začnou odpadky mizet? V sekundách. -1 navždy.</Czech>
<Portuguese>Quanto tempo os objetos do lixo devem ficar? Em segundos. -1 é para sempre.</Portuguese>
<French>Combien de temps doivent rester affiché les détritus? En secondes. -1 pour tout le temps</French>
<Hungarian>Milyen sokáig legyenek jelen a szemétobjektumok (másodpercben)? A -1 végtelen időt jelent.</Hungarian>
<Italian>Per quanto devono restare le barelle? In secondi. -1 è permanente</Italian>
<Japanese>医療廃棄物オブジェクトが表示されつづける時間を設定しますか? -1 は永遠です。</Japanese>
<Korean>얼마동안 폐기물이 존재합니까? 초 단위. -1 은 영구적.</Korean>
<Chinesesimp>定义医疗废弃物存在时间,以秒为单位,-1为永远存在。</Chinesesimp>
<Chinese>定義醫療廢棄物存在時間,以秒為單位,-1為永遠存在。</Chinese>
<Key ID="STR_ACE_Medical_Fractures_DisplayName">
<English>Fractures</English>
<Russian>Переломы</Russian>
<Japanese>骨折</Japanese>
</Key>
<Key ID="STR_ACE_Medical_Fractures_Description">
<English>Limp fractures... (todo)</English>
<Russian>Хромота при переломах...</Russian>
<Japanese>骨折時は引きずって歩くようにします・・・ (TODO)</Japanese>
</Key>
<Key ID="STR_ACE_Medical_Fractures_SplintHealsFully">
<English>Splints fully heal fractures</English>
<Russian>Шины полностью лечат перелом</Russian>
<Japanese>添え木で骨折完治</Japanese>
</Key>
<Key ID="STR_ACE_Medical_Fractures_SplintHasEffects">
<English>Splints heal (but cannot sprint)</English>
<Russian>Шины вылечивают, но не дают бегать</Russian>
<Japanese>添え木で治療しますが、走れません</Japanese>
</Key>
<Key ID="STR_ACE_Medical_MedicalSettings_remoteControlledAI_DisplayName">
<English>Remote Controlled AI</English>
@ -209,21 +149,6 @@
<Chinesesimp>医疗系统将同时对玩家与AI发生作用</Chinesesimp>
<Chinese>醫療系統將同時對玩家與AI發生作用</Chinese>
</Key>
<Key ID="STR_ACE_Medical_BasicMedicalSettings_Module_DisplayName">
<English>Basic Medical Settings [ACE]</English>
<German>Standard Sanitätseinstellungen [ACE]</German>
<Polish>Podstawowe ustawienia medyczne</Polish>
<Spanish>Ajustes médicos básicos [ACE]</Spanish>
<French>Paramètres des soins basiques [ACE]</French>
<Italian>Impostazioni Mediche Di Base [ACE]</Italian>
<Czech>Základní zdravotnické nastavení [ACE]</Czech>
<Portuguese>Ajustes médicos básicos [ACE]</Portuguese>
<Russian>Настройки базовой медицины [ACE]</Russian>
<Japanese>ベーシック医療設定 [ACE]</Japanese>
<Korean>기본 의료 설정 [ACE]</Korean>
<Chinesesimp>基本医疗设定 [ACE]</Chinesesimp>
<Chinese>基本醫療設定 [ACE]</Chinese>
</Key>
<Key ID="STR_ACE_Medical_MedicalSettings_enableFor_DisplayName">
<English>Enabled for</English>
<Russian>Включено для</Russian>
@ -320,21 +245,6 @@
<Chinesesimp>设定人员是否会因为载具冲撞别的物件而产生伤害?</Chinesesimp>
<Chinese>設定人員是否會因為載具衝撞別的物件而產生傷害?</Chinese>
</Key>
<Key ID="STR_ACE_Medical_BasicMedicalSettings_useLocation_basicEpi_Description">
<English>Where can the Epinephrine be used? (Basic Medical)</English>
<German>Wo kann Epiniphrin verwendet werden? (Standard Sanitätseinstellungen)</German>
<Spanish>Configura donde puede usarse Epinefrina (Solo sistema médico básico)</Spanish>
<Polish>Gdzie można korzystać z adrenaliny? (Podstawowy system medyczny)</Polish>
<French>Où peut être utilisé l'épinéphrine ? (Médical basique)</French>
<Italian>Dove si può usare l'epinefrina? (Sistema medico di base)</Italian>
<Czech>Kde může být použit adrenalin? (Pouze základní zdravotní systém)</Czech>
<Portuguese>Onde pode-se usar a Epinefrina? (Somente sistema médico básico)</Portuguese>
<Russian>Где может использоваться адреналин? (Базовая медицина)</Russian>
<Japanese>どこでもアドレナリンを使えるようにしますか? (ベーシック医療のみ)</Japanese>
<Korean>어디에서 에피네프린을 사용할 수 있습니까? (기본 의료)</Korean>
<Chinesesimp>在哪里可以使用肾上腺素? (基本医疗)</Chinesesimp>
<Chinese>在哪裡可以使用腎上腺素? (基本醫療)</Chinese>
</Key>
<Key ID="STR_ACE_Medical_MedicalSettings_healHitPointAfterAdvBandage_DisplayName">
<English>Heal hitpoints</English>
<German>Heile Trefferpunkte</German>
@ -440,20 +350,10 @@
<Chinesesimp>设定当距离超过%1将不能使用治疗动作</Chinesesimp>
<Chinese>設定當距離超過%1將不能使用治療動作</Chinese>
</Key>
<Key ID="STR_ACE_Medical_MedicalSettings_spontaneousWakeUpChance_DisplayName">
<English>Unconscious Wake Up Chance</English>
<Japanese>気絶から覚醒する可能性</Japanese>
<Russian>Шанс очнуться при потере сознания</Russian>
</Key>
<Key ID="STR_ACE_Medical_MedicalSettings_spontaneousWakeUpChance_Description">
<English>Probablity that a unit with stable vitals will wake up from unconscious [Checked every 15 sec]</English>
<Japanese>安定状態にある人が覚醒する確率です。(15 秒毎に確認)</Japanese>
<Russian>Вероятность, что стабилизированный юнит очнется от потери сознания [Проверяется каждые 15 сек]</Russian>
</Key>
<Key ID="STR_ACE_Medical_openLid">
<English>Open lid</English>
<German>Deckel aufklappen</German>
<Japanese>フタをける</Japanese>
<Japanese>フタを開ける</Japanese>
<Italian>Apri lid</Italian>
<Chinese>打開蓋子</Chinese>
<Chinesesimp>打开盖子</Chinesesimp>
@ -464,7 +364,7 @@
<Key ID="STR_ACE_Medical_closeLid">
<English>Close lid</English>
<German>Deckel zuklappen</German>
<Japanese>フタをめる</Japanese>
<Japanese>フタをめる</Japanese>
<Italian>Chiudi lid</Italian>
<Chinese>關閉蓋子</Chinese>
<Chinesesimp>关闭盖子</Chinesesimp>
@ -472,37 +372,5 @@
<Polish>Zamknij pokrywę</Polish>
<Russian>Закрыть крышку</Russian>
</Key>
<Key ID="STR_ACE_Medical_setting_limping_DisplayName">
<English>Limping</English>
<Russian>Хромота</Russian>
</Key>
<Key ID="STR_ACE_Medical_setting_limping_Description">
<English>Limp when unit has leg wounds...(todo)</English>
<Russian>Хромота, когда юнит имеет ранения ног...</Russian>
</Key>
<Key ID="STR_ACE_Medical_setting_limping_limpOnOpenWounds">
<English>Limp on open wounds</English>
<Russian>Хромота при открытых ранах</Russian>
</Key>
<Key ID="STR_ACE_Medical_setting_limping_limpRequiresStitching">
<English>Limp on open or bandaged wounds</English>
<Russian>Хромота при открытых или забинтованых ранах</Russian>
</Key>
<Key ID="STR_ACE_Medical_setting_fractures_DisplayName">
<English>Fractures</English>
<Russian>Переломы</Russian>
</Key>
<Key ID="STR_ACE_Medical_setting_fractures_Description">
<English>Limp fractures... (todo)</English>
<Russian>Хромота при переломах...</Russian>
</Key>
<Key ID="STR_ACE_Medical_setting_fractures_splintHealsFully">
<English>Splints fully heal fractures</English>
<Russian>Шины полностью лечат перелом</Russian>
</Key>
<Key ID="STR_ACE_Medical_setting_fractures_splintHasEffects">
<English>Splints heal (but cannot sprint)</English>
<Russian>Шины вылечивают, но не дают бегать</Russian>
</Key>
</Package>
</Project>

View File

@ -1,86 +0,0 @@
class GVAR(stateMachine) {
list = QUOTE(call EFUNC(common,getLocalUnits));
skipNull = 1;
class Initial {
class Injured {
targetState = "Injured";
condition = QFUNC(isInjured);
};
class HealUnit {
targetState = "HealUnit";
condition = QUOTE((call FUNC(isSafe)) && {call FUNC(wasRequested)});
};
};
class Injured {
#ifdef DEBUG_MODE_FULL
onState = "systemChat format [""%1 is injured"", _this]";
#endif
class InSafety {
targetState = "Safe";
condition = QFUNC(isSafe);
};
};
class Safe {
#ifdef DEBUG_MODE_FULL
onState = "systemChat format [""%1 is injured, but safe"", _this]";
#endif
class RequestMedic {
targetState = "HealSelf";
condition = QFUNC(canRequestMedic);
onTransition = QFUNC(requestMedic);
};
class HealSelf {
targetState = "HealSelf";
condition = "true";
};
};
class HealSelf {
onState = QFUNC(healSelf);
onStateLeaving = QUOTE(_this setVariable [ARR_2(QUOTE(QGVAR(treatmentOverAt)),nil)]);
class Initial {
// Go back to initial state when done healing
targetState = "Initial";
condition = QUOTE( \
!(call FUNC(isInjured)) \
&& {_this getVariable [ARR_2(QUOTE(QGVAR(treatmentOverAt)),CBA_missionTime)] <= CBA_missionTime} \
);
};
class Injured {
// Stop treating when it's no more safe
targetState = "Injured";
condition = QUOTE( \
!(call FUNC(isSafe)) \
&& {_this getVariable [ARR_2(QUOTE(QGVAR(treatmentOverAt)),CBA_missionTime)] <= CBA_missionTime} \
);
};
};
class HealUnit {
onState = QFUNC(healUnit);
onStateLeaving = QUOTE(_this setVariable [ARR_2(QUOTE(QGVAR(treatmentOverAt)),nil)]);
class Initial {
// Go back to initial state when done healing or it's no more safe to treat
targetState = "Initial";
condition = QUOTE( \
!((call FUNC(wasRequested)) && {call FUNC(isSafe)}) \
&& {_this getVariable [ARR_2(QUOTE(QGVAR(treatmentOverAt)),CBA_missionTime)] <= CBA_missionTime} \
);
};
class Injured {
// Treating yourself has priority
targetState = "Injured";
condition = QUOTE( \
(call FUNC(isInjured)) \
&& {_this getVariable [ARR_2(QUOTE(QGVAR(treatmentOverAt)),CBA_missionTime)] <= CBA_missionTime} \
);
};
};
};

View File

@ -1,4 +1,5 @@
PREP(canRequestMedic);
PREP(healingLogic);
PREP(healSelf);
PREP(healUnit);
PREP(isInjured);

View File

@ -1,35 +1,14 @@
#include "script_component.hpp"
/*["ace_settingsInitialized", {
["ace_settingsInitialized", {
TRACE_1("settingsInitialized", GVAR(enabledFor));
if (GVAR(enabledFor) == 0) exitWith {}; // 0: disabled
if ((GVAR(enabledFor) == 1) && {!isServer} && {hasInterface}) exitWith {}; // 1: Don't Run on non-hc Clients
// Only run for AI that does not have to deal with advanced medical
if (EGVAR(medical,enableFor) == 1 || {hasInterface}) exitWith {};
["ace_firedNonPlayer", {
_unit setVariable [QGVAR(lastFired), CBA_missionTime];
}] call CBA_fnc_addEventHandler;
if (hasInterface) then {
["ace_unconscious", {
params ["_unit", "_unconscious"];
if (!_unconscious || {_unit != ACE_player}) exitWith {};
#include "stateMachine.sqf"
}] call CBA_fnc_addEventHandler;
private _medic = objNull;
{
if ((!isPlayer _x) && {[_x] call EFUNC(medical_treatment,isMedic)}) exitWith {
_medic = _x;
};
} forEach (units _unit);
if (isNull _medic) exitWith {};
private _healQueue = _medic getVariable [QGVAR(healQueue), []];
_healQueue pushBack _unit;
_medic setVariable [QGVAR(healQueue), _healQueue];
}] call CBA_fnc_addEventHandler;
};
GVAR(statemachine) = [configFile >> "ACE_Medical_AI_StateMachine"] call CBA_statemachine_fnc_createFromConfig;
}] call CBA_fnc_addEventHandler;*/

View File

@ -16,4 +16,3 @@ class CfgPatches {
#include "ACE_Settings.hpp"
#include "CfgEventHandlers.hpp"
#include "StateMachine.hpp"

View File

@ -10,7 +10,7 @@
* Can request medic <BOOL>
*
* Example:
* call ACE_medical_ai_fnc_canRequestMedic
* player call ACE_medical_ai_fnc_canRequestMedic
*
* Public: No
*/
@ -21,10 +21,14 @@
if ([_this] call EFUNC(medical_treatment,isMedic) || {vehicle _this != _this}) exitWith {false};
// Search for a medic, prioritize unitReady
private _medic = objNull;
{
if ([_x] call EFUNC(medical_treatment,isMedic) && {!([_x] call EFUNC(common,isPlayer))}) exitWith {
_this setVariable [QGVAR(assignedMedic), _x];
true
};
false
if ([_x] call EFUNC(medical_treatment,isMedic) && {!([_x] call EFUNC(common,isPlayer))} && {
_medic = _x;
(unitReady _medic)
}) exitWith {};
} forEach (units _this);
_this setVariable [QGVAR(assignedMedic), _medic];
!isNull _medic

View File

@ -18,41 +18,8 @@
// Player will have to do this manually of course
if ([_this] call EFUNC(common,isPlayer)) exitWith {};
// Can't heal self when unconscious
if IS_UNCONSCIOUS(_this) exitWith {};
// Check if we're still treating
if ((_this getVariable [QGVAR(treatmentOverAt), CBA_missionTime]) > CBA_missionTime) exitWith {};
private _needsBandaging = GET_BLOOD_LOSS(_this) > 0;
private _needsMorphine = GET_PAIN(_this) > 0.2;
switch (true) do {
case _needsBandaging: {
// Select first wound and bandage it
private _openWounds = _this getVariable [QEGVAR(medical,openWounds), []];
private _partIndex = {
_x params ["", "", "_index", "_amount", "_percentage"];
if (_amount * _percentage > 0) exitWith {
_index
};
} forEach _openWounds;
private _selection = ALL_BODY_PARTS select _partIndex;
[_this, "BasicBandage", _selection] call EFUNC(medical_treatment,treatmentBandageLocal);
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 is bandaging selection %2", _this, _selection];
#endif
// Play animation
[_this, true, true] call FUNC(playTreatmentAnim);
_this setVariable [QGVAR(treatmentOverAt), CBA_missionTime + 5];
};
case _needsMorphine: {
[_this, "Morphine", 2] call EFUNC(medical_treatment,treatmentMedicationLocal);
[_this, false, true] call FUNC(playTreatmentAnim);
_this setVariable [QGVAR(treatmentOverAt), CBA_missionTime + 2];
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 is giving himself morphine", _this];
#endif
};
if IS_UNCONSCIOUS(_this) exitWith {
_this setVariable [QGVAR(currentTreatment), nil];
};
[_this, _this] call FUNC(healingLogic);

View File

@ -14,11 +14,12 @@
*
* Public: No
*/
// Player will have to do this manually of course
if ([_this] call EFUNC(common,isPlayer)) exitWith {};
// Can't heal other units when unconscious
if IS_UNCONSCIOUS(_this) exitWith {};
// Check if we're still treating
if ((_this getVariable [QGVAR(treatmentOverAt), CBA_missionTime]) > CBA_missionTime) exitWith {};
if IS_UNCONSCIOUS(_this) exitWith {
_this setVariable [QGVAR(currentTreatment), nil];
};
// Find next unit to treat
private _healQueue = _this getVariable [QGVAR(healQueue), []];
@ -26,74 +27,34 @@ private _target = _healQueue select 0;
// If unit died or was healed, be lazy and wait for the next tick
if (isNull _target || {!alive _target} || {!(_target call FUNC(isInjured))}) exitWith {
_this forceSpeed -1;
_target forceSpeed -1;
_healQueue deleteAt 0;
_this getVariable [QGVAR(healQueue), _healQueue];
_this forceSpeed -1;
_this setVariable [QGVAR(healQueue), _healQueue];
// return to formation instead of going where the injured unit was if it healed itself in the mean time
_this doFollow leader _this;
_this setVariable [QGVAR(movingToInjured), false];
_this setVariable [QGVAR(nextMoveOrder), nil];
_this setVariable [QGVAR(currentTreatment), nil];
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 finished healing %2", _this, _target];
systemChat format ["%1 finished healing %2", _this, _target];
#endif
};
// Move to target...
if (_this distance _target > 2) exitWith {
if !(_this getVariable [QGVAR(movingToInjured), false]) then {
_this setVariable [QGVAR(movingToInjured), true];
if (_this distance _target > 2.5) exitWith {
_this setVariable [QGVAR(currentTreatment), nil];
if (CBA_missionTime >= (_this getVariable [QGVAR(nextMoveOrder), CBA_missionTime])) then {
_this setVariable [QGVAR(nextMoveOrder), CBA_missionTime + 10];
_this doMove getPosATL _target;
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 moving to %2", _this, _target];
#endif
};
};
_this setVariable [QGVAR(movingToInjured), false];
// ...and make sure medic and target don't move
_this forceSpeed 0;
_target forceSpeed 0;
private _needsBandaging = GET_BLOOD_LOSS(_target) > 0;
private _needsMorphine = GET_PAIN(_target) > 0.2;
private _needsEpinephrine = IS_UNCONSCIOUS(_target);
switch (true) do {
case _needsBandaging: {
// Select first wound and bandage it
private _openWounds = _target getVariable [QEGVAR(medical,openWounds), []];
private _partIndex = {
_x params ["", "", "_index", "_amount", "_percentage"];
if (_amount * _percentage > 0) exitWith {
_index
};
} forEach _openWounds;
private _selection = ALL_BODY_PARTS select _partIndex;
[_target, "BasicBandage", _selection] call EFUNC(medical_treatment,treatmentBandageLocal);
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 is bandaging selection %2 on %3", _this, _selection, _target];
#endif
// Play animation
[_this, true, false] call FUNC(playTreatmentAnim);
_this setVariable [QGVAR(treatmentOverAt), CBA_missionTime + 5];
};
case _needsMorphine: {
[_this, "Morphine", 2] call EFUNC(medical_treatment,treatmentMedicationLocal);
[_this, false, false] call FUNC(playTreatmentAnim);
_this setVariable [QGVAR(treatmentOverAt), CBA_missionTime + 2];
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 is giving %2 morphine", _this, _target];
#endif
};
//ToDo - Figure out how to connect to new medical
// case _needsEpinephrine: {
// [_this, _target] call EFUNC(medical,treatmentBasic_epipen);
// [_this, false, false] call FUNC(playTreatmentAnim);
// _this setVariable [QGVAR(treatmentOverAt), CBA_missionTime + 2];
// #ifdef DEBUG_MODE_FULL
// systemChat format ["%1 is using an epipen on %2", _this, _target];
// #endif
// };
};
[_this, _target] call FUNC(healingLogic);

View File

@ -0,0 +1,117 @@
#include "script_component.hpp"
/*
* Author: BaerMitUmlaut, PabstMirror
* Applies healing to target
*
* Arguments:
* 0: Healer <OBJECT>
* 1: Target <OBJECT>
*
* Return Value:
* Nothing
*
* Example:
* [a, b] call ACE_medical_ai_fnc_healingLogic
*
* Public: No
*/
params ["_healer", "_target"];
(_healer getVariable [QGVAR(currentTreatment), [-1]]) params ["_finishTime", "_treatmentTarget", "_treatmentEvent", "_treatmentArgs"];
// Treatment in progress, check if finished and apply
if (_finishTime > 0) exitWith {
if (CBA_missionTime >= _finishTime) then {
TRACE_4("treatment finished",_finishTime,_treatmentTarget,_treatmentEvent,_treatmentArgs);
_healer setVariable [QGVAR(currentTreatment), nil];
if ((_treatmentTarget == _target) && {(_treatmentEvent select [0, 1]) != "#"}) then {
[_treatmentEvent, _treatmentArgs, _target] call CBA_fnc_targetEvent;
#ifdef DEBUG_MODE_FULL
INFO_4("%1->%2: %3 - %4",_healer,_target,_treatmentEvent,_treatmentArgs);
systemChat format ["Applying [%1->%2]: %3", _healer, _treatmentTarget, _treatmentEvent];
#endif
};
};
};
private _isMedic = [_healer] call EFUNC(medical_treatment,isMedic);
private _heartRate = GET_HEART_RATE(_target);
private _fractures = GET_FRACTURES(_target);
private _treatmentEvent = "#none";
private _treatmentArgs = [];
private _treatmentTime = 6;
switch (true) do {
case (GET_WOUND_BLEEDING(_target) > 0): {
// Select first bleeding wound and bandage it
private _openWounds = GET_OPEN_WOUNDS(_target);
private _selection = "?";
{
_x params ["", "_index", "_amount", "_percentage"];
if ((_amount * _percentage) > 0) exitWith { _selection = ALL_BODY_PARTS select _index; };
} forEach _openWounds;
_treatmentEvent = QEGVAR(medical_treatment,bandageLocal);
_treatmentTime = 5;
_treatmentArgs = [_target, _selection, "FieldDressing"];
};
case (_isMedic && {GET_BLOOD_VOLUME(_target) < BLOOD_VOLUME_CLASS_2_HEMORRHAGE}): {
private _bloodBags = _target getVariable [QEGVAR(medical,ivBags), []];
if ((count _bloodBags) >= 2) exitWith {
_treatmentEvent = "#waitForBlood";
};
_treatmentEvent = QEGVAR(medical_treatment,ivBagLocal);
_treatmentTime = 5;
_treatmentArgs = [_target, selectRandom ["leftarm", "rightarm", "leftleg", "rightleg"], "SalineIV"];
};
case ((count (_target getVariable [VAR_MEDICATIONS, []])) >= 6): {
_treatmentEvent = "#tooManyMeds";
};
case ((_fractures select 4) == 1): {
_treatmentEvent = QEGVAR(medical_treatment,splintLocal);
_treatmentTime = 6;
_treatmentArgs = [_healer, _target, "leftleg"];
};
case ((_fractures select 5) == 1): {
_treatmentEvent = QEGVAR(medical_treatment,splintLocal);
_treatmentTime = 6;
_treatmentArgs = [_healer, _target, "rightleg"];
};
case (IS_UNCONSCIOUS(_target) || {_heartRate <= 50}): {
if (CBA_missionTime < (_target getVariable [QGVAR(nextEpinephrine), -1])) exitWith {
_treatmentEvent = "#waitForEpinephrineToTakeEffect";
};
if (_heartRate > 180) exitWith {
_treatmentEvent = "#waitForSlowerHeart";
};
_target setVariable [QGVAR(nextEpinephrine), CBA_missionTime + 10];
_treatmentEvent = QEGVAR(medical_treatment,medicationLocal);
_treatmentTime = 2.5;
_treatmentArgs = [_target, selectRandom ["leftarm", "rightarm", "leftleg", "rightleg"], "Epinephrine"];
};
case ((GET_PAIN_PERCEIVED(_target) > 0.25) || {_heartRate >= 180}): {
if (CBA_missionTime < (_target getVariable [QGVAR(nextMorphine), -1])) exitWith {
_treatmentEvent = "#waitForMorphineToTakeEffect";
};
if (_heartRate < 60) exitWith {
_treatmentEvent = "#waitForFasterHeart";
};
_target setVariable [QGVAR(nextMorphine), CBA_missionTime + 30];
_treatmentEvent = QEGVAR(medical_treatment,medicationLocal);
_treatmentTime = 2.5;
_treatmentArgs = [_target, selectRandom ["leftarm", "rightarm", "leftleg", "rightleg"], "Morphine"];
};
};
_healer setVariable [QGVAR(currentTreatment), [CBA_missionTime + _treatmentTime, _target, _treatmentEvent, _treatmentArgs]];
// Play animation
if ((_treatmentEvent select [0,1]) != "#") then {
private _treatmentClassname = _treatmentArgs select 2;
if (_treatmentEvent == QEGVAR(medical_treatment,splintLocal)) then { _treatmentClassname = "Splint" };
[_healer, _treatmentClassname, (_healer == _target)] call FUNC(playTreatmentAnim);
};
#ifdef DEBUG_MODE_FULL
TRACE_4("treatment started",_treatmentTime,_target,_treatmentEvent,_treatmentArgs);
systemChat format ["Treatment [%1->%2]: %3", _healer, _target, _treatmentEvent];
#endif

View File

@ -17,8 +17,10 @@
if !(alive _this) exitWith {false};
private _bloodLoss = GET_BLOOD_LOSS(_this);
private _pain = GET_PAIN_PERCEIVED(_this);
private _unconscious = IS_UNCONSCIOUS(_this);
(_bloodLoss > 0) || {_pain > 0.2} || _unconscious
(GET_WOUND_BLEEDING(_this) > 0)
|| {GET_PAIN_PERCEIVED(_this) > 0.25}
|| {IS_UNCONSCIOUS(_this)}
|| {
private _fractures = GET_FRACTURES(_this);
((_fractures select 4) == 1) || {(_fractures select 5) == 1}
}

View File

@ -5,7 +5,7 @@
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Is bandage <BOOL>
* 1: Treatment name <STRING>
* 2: Is self treatment <BOOL>
*
* Return Value:
@ -16,16 +16,11 @@
*
* Public: No
*/
params ["_unit", "_isBandage", "_isSelfTreatment"];
params ["_unit", "_actionName", "_isSelfTreatment"];
TRACE_3("playTreatmentAnim",_unit,_actionName,_isSelfTreatment);
if (vehicle _unit != _unit) exitWith {};
private _animConfig = if (_isBandage) then {
configFile >> "ACE_Medical_Actions" >> "Basic" >> "BasicBandage";
} else {
configFile >> "ACE_Medical_Actions" >> "Basic" >> "Morphine";
};
private _configProperty = "animationMedic";
if (_isSelfTreatment) then {
_configProperty = _configProperty + "Self";
@ -34,7 +29,9 @@ if (stance _unit == "PRONE") then {
_configProperty = _configProperty + "Prone";
};
private _anim = getText (_animConfig >> _configProperty);
private _anim = getText (configFile >> QEGVAR(medical_treatment,Actions) >> _actionName >> _configProperty);
if (_anim == "") exitWith { WARNING_2("no anim [%1, %2]",_actionName,_configProperty); };
private _wpn = switch (true) do {
case ((currentWeapon _unit) == ""): {"non"};
case ((currentWeapon _unit) == (primaryWeapon _unit)): {"rfl"};

View File

@ -1,12 +1,17 @@
// CBA Settings [ADDON: ace_medical_ai]:
private _categoryArray = [ELSTRING(medical,Category), "STR_TEAM_SWITCH_AI"];
[
QGVAR(enabledFor),
"LIST",
QGVAR(enabledFor), "LIST",
[LLSTRING(enableFor_title), LLSTRING(enableFor_desc)],
LLSTRING(settingCategory),
_categoryArray,
[
[0, 1, 2],
[LELSTRING(Common,Disabled), LLSTRING(enabledFor_OnlyServerAndHC), LELSTRING(Common,Enabled)],
2
],
true
true, // isGlobal
{[QGVAR(enabledFor), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart
] call CBA_settings_fnc_init;

View File

@ -0,0 +1,67 @@
GVAR(stateMachine) = [{call EFUNC(common,getLocalUnits)}, true] call CBA_statemachine_fnc_create;
// Add states [statemachine, onState, onStateEntered, onStateLeaving, name]
[GVAR(stateMachine), {}, {}, {}, "Initial"] call CBA_statemachine_fnc_addState;
[GVAR(stateMachine), {
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 is injured", _this];
#endif
}, {}, {}, "Injured"] call CBA_statemachine_fnc_addState;
[GVAR(stateMachine), {
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 is injured and safe", _this];
#endif
}, {}, {}, "Safe"] call CBA_statemachine_fnc_addState;
[GVAR(stateMachine), LINKFUNC(healSelf), {}, {
_this setVariable [QGVAR(treatmentOverAt), nil];
}, "HealSelf"] call CBA_statemachine_fnc_addState;
[GVAR(stateMachine), LINKFUNC(healUnit), {}, {
_this setVariable [QGVAR(treatmentOverAt), nil];
}, "HealUnit"] call CBA_statemachine_fnc_addState;
// Add Transistions [statemachine, originalState, targetState, condition, onTransition, name]
[GVAR(stateMachine), "Initial", "Injured", LINKFUNC(isInjured), {}, "Injured"] call CBA_statemachine_fnc_addTransition;
[GVAR(stateMachine), "Initial", "HealUnit", {(call FUNC(isSafe)) && FUNC(wasRequested)}, {}, "HealUnit"] call CBA_statemachine_fnc_addTransition;
[GVAR(stateMachine), "Injured", "Safe", LINKFUNC(isSafe), {}, "InSafety"] call CBA_statemachine_fnc_addTransition;
[GVAR(stateMachine), "Safe", "HealSelf", LINKFUNC(canRequestMedic), LINKFUNC(requestMedic), "RequestMedic"] call CBA_statemachine_fnc_addTransition;
[GVAR(stateMachine), "Safe", "HealSelf", {true}, {}, "HealSelf"] call CBA_statemachine_fnc_addTransition;
[GVAR(stateMachine), "HealSelf", "Initial", { // Go back to initial state when done healing
!(call FUNC(isInjured)) && {isNil {_this getVariable QGVAR(currentTreatment)}}
}, {
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 finished healing themself", _this];
#endif
}, "Initial"] call CBA_statemachine_fnc_addTransition;
[GVAR(stateMachine), "HealSelf", "Injured", { // Stop treating when it's no more safe
!(call FUNC(isSafe)) && {isNil {_this getVariable QGVAR(currentTreatment)}}
}, {
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 is no longer safe", _this];
#endif
}, "Injured"] call CBA_statemachine_fnc_addTransition;
[GVAR(stateMachine), "HealUnit", "Initial", { // Go back to initial state when done healing or it's no more safe to treat
!((call FUNC(wasRequested)) && FUNC(isSafe)) && {isNil {_this getVariable QGVAR(currentTreatment)}}
}, {
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 finished healing someone", _this];
#endif
}, "Initial"] call CBA_statemachine_fnc_addTransition;
[GVAR(stateMachine), "HealUnit", "Injured", { // Treating yourself has priority
(call FUNC(isInjured)) && {isNil {_this getVariable QGVAR(currentTreatment)}}
}, {
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 was injured while healing someone", _this];
#endif
}, "Injured"] call CBA_statemachine_fnc_addTransition;

View File

@ -1,18 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<Project name="ACE">
<Package name="medical_ai">
<Key ID="STR_ACE_medical_ai_settingCategory">
<English>ACE Medical - AI</English>
<Japanese>ACE 医療 - AI</Japanese>
<Russian>ACE Медицина - ИИ</Russian>
</Key>
<Key ID="STR_ACE_medical_ai_enableFor_title">
<English>Medic AI</English>
<German>Sanitäts KI</German>
<Japanese>AI 衛生兵</Japanese>
<Russian>ИИ Медик</Russian>
</Key>
<Key ID="STR_ACE_medical_ai_enableFor_desc">
<English>AI will respond to injury and unconsciousness</English>
<German>KI reagiert auf Verletzungen und Bewusstlosigkeit</German>
<Japanese>AI が負傷者と気絶している人に対して行動するようになります。</Japanese>
<Russian>ИИ будет реагировать на травмы и потерю сознания</Russian>
</Key>

View File

@ -1,4 +1,3 @@
class Extended_PreStart_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_FILE(XEH_preStart));

View File

@ -1,7 +1,7 @@
ace_medical_blood
===============
=================
Adds blood visual effect on the ground near a bleeding player.
Creates blood drops on the ground near bleeding units.
## Maintainers

View File

@ -1,7 +1,7 @@
PREP(cleanupLoop);
PREP(createBlood);
PREP(handleWoundReceived);
PREP(init);
PREP(isBleeding);
PREP(onBleeding);
PREP(createBlood);
PREP(serverCleanupBlood);
PREP(spurt);

View File

@ -10,33 +10,18 @@ if (isServer) then {
[QGVAR(bloodDropCreated), {
params ["_bloodDrop"];
// Add to created queue with format [expireTime, object]
private _index = GVAR(bloodDrops) pushBack [(CBA_missionTime + BLOOD_OBJECT_LIFETIME), _bloodDrop];
if (count GVAR(bloodDrops) >= MAX_BLOOD_OBJECTS) then {
// Add to created queue with format: [expire time, blood object]
private _index = GVAR(bloodDrops) pushBack [CBA_missionTime + GVAR(bloodLifetime), _bloodDrop];
if (count GVAR(bloodDrops) >= GVAR(maxBloodObjects)) then {
(GVAR(bloodDrops) deleteAt 0) params ["", "_deletedBloodDrop"];
deleteVehicle _deletedBloodDrop;
};
if (_index == 1) then { // Start the waitAndExecute loop
[FUNC(serverCleanupBlood), [], BLOOD_OBJECT_LIFETIME] call CBA_fnc_waitAndExecute;
// Start the cleanup loop
if (_index == 0) then {
[FUNC(cleanupLoop), [], GVAR(bloodLifetime)] call CBA_fnc_waitAndExecute;
};
}] call CBA_fnc_addEventHandler;
};
["ace_settingsInitialized", {
TRACE_1("settingsInitialized", GVAR(enabledFor));
if (GVAR(enabledFor) == 0) exitWith {}; // 0: disabled
if ((GVAR(enabledFor) == 1) && {!hasInterface}) exitWith {}; // 1: enabledFor_OnlyPlayers
private _listcode = if (GVAR(enabledFor) == 1) then {
{if (alive ACE_player) then {[ACE_player]} else {[]}} // ace_player is only possible local player
} else {
EFUNC(common,getLocalUnits) // filter all local units
};
private _stateMachine = [_listcode, true] call CBA_statemachine_fnc_create;
[_stateMachine, LINKFUNC(onBleeding), {}, {}, "Bleeding"] call CBA_statemachine_fnc_addState;
[QEGVAR(medical,woundReceived), FUNC(handleWoundReceived)] call CBA_fnc_addEventHandler;
}] call CBA_fnc_addEventHandler;

View File

@ -14,5 +14,5 @@ class CfgPatches {
};
};
#include "ACE_Settings.hpp"
#include "CfgEventHandlers.hpp"
#include "ACE_Settings.hpp"

View File

@ -1,23 +1,26 @@
#include "script_component.hpp"
/*
* Author: PabstMirror
* Loop that cleans up blood
* Handles cleaning up blood objects that have reached the end of their lifetime.
*
* Arguments:
* None
*
* ReturnValue:
* Return Value:
* None
*
* Example:
* [] call ace_medical_blood_fnc_cleanupLoop
*
* Public: No
*/
(GVAR(bloodDrops) deleteAt 0) params ["", "_deletedBloodDrop"];
deleteVehicle _deletedBloodDrop;
// If we cleaned out the array, exit loop
// Exit the loop if we have cleaned out the array
if (GVAR(bloodDrops) isEqualTo []) exitWith {};
// Wait until the next blood drop in the queue will expire
(GVAR(bloodDrops) select 0) params ["_expireTime"];
[FUNC(serverCleanupBlood), [], (_expireTime - CBA_missionTime)] call CBA_fnc_waitAndExecute;
[FUNC(cleanupLoop), [], _expireTime - CBA_missionTime] call CBA_fnc_waitAndExecute;

View File

@ -1,15 +1,15 @@
#include "script_component.hpp"
/*
* Author: Glowbal
* Spawn a blood drop.
* Creates a blood object and handles its cleanup.
* Available blood drop classes are blooddrop_1 through blooddrop_4.
*
* Arguments:
* 0: classname of blood drop <OBJECT>
* 0: Blood Drop Type <STRING>
* 1: Position <ARRAY>
*
* Return Value:
* Created blood drop <OBJECT>
* Blood Drop <OBJECT>
*
* Example:
* ["blooddrop_2", getPos player] call ace_medical_blood_fnc_createBlood
@ -17,15 +17,15 @@
* Public: No
*/
params ["_type", "_pos"];
TRACE_2("creating blood",_type,_pos);
params ["_type", "_position"];
TRACE_2("Creating blood",_type,_position);
private _model = GVAR(models) getVariable _type;
private _object = createSimpleObject [_model, [0,0,0]];
_object setDir random 360;
_object setPos _pos;
private _bloodDrop = createSimpleObject [_model, [0, 0, 0]];
_bloodDrop setDir random 360;
_bloodDrop setPos _position;
[QGVAR(bloodDropCreated), [_object]] call CBA_fnc_serverEvent;
[QGVAR(bloodDropCreated), _bloodDrop] call CBA_fnc_serverEvent;
_object
_bloodDrop

View File

@ -1,13 +1,13 @@
#include "script_component.hpp"
/*
* Author: Glowbal, commy2
* Handle wounds received event.
* Handles the wounds received event by triggering any needed blood creation.
*
* Arguments:
* 0: unit <OBJECT>
* 1: bodyPart <String>
* 2: damage <NUMBER>
* 3: shooter <OBJECT>
* 0: Unit <OBJECT>
* 1: Body Part (not used) <STRING>
* 2: Damage <NUMBER>
* 3: Shooter <OBJECT>
*
* Return Value:
* None
@ -20,16 +20,16 @@
params ["_unit", "", "_damage", "_shooter"];
if (GVAR(enabledFor) == 1 && {!isPlayer _unit && {_unit != ACE_player}}) exitWith {};
if (vehicle _unit != _unit && {!((vehicle _unit) isKindOf "StaticWeapon")}) exitWith {}; // Don't bleed on ground if mounted
// Don't bleed when players only and a non-player unit is wounded
if (GVAR(enabledFor) == BLOOD_ONLY_PLAYERS && {!isPlayer _unit && {_unit != ACE_player}}) exitWith {};
_damage = _damage min 1;
// Don't bleed on the ground if in a vehicle
if (vehicle _unit != _unit && {!(vehicle _unit isKindOf "StaticWeapon")}) exitWith {};
if (isNull _shooter) exitWith { // won't be able to calculate the direction properly, so instead we pick something at random
[QGVAR(spurt), [_unit, random 360, _damage]] call CBA_fnc_serverEvent;
private _bulletDir = if (isNull _shooter) then {
random 360 // Cannot calculate the direction properly, pick a random direction
} else {
_shooter getDir _unit // Calculate the bullet direction
};
// Calculate bulletDirection
private _bulletDir = _shooter getDir _unit;
[QGVAR(spurt), [_unit, _bulletDir, _damage]] call CBA_fnc_serverEvent;
[QGVAR(spurt), [_unit, _bulletDir, _damage min 1]] call CBA_fnc_serverEvent;

View File

@ -0,0 +1,65 @@
#include "script_component.hpp"
/*
* Author: mharis001
* Initializes the medical blood system based on the given mode.
* Should only be called from the CBA setting changed script.
*
* Arguments:
* 0: Mode <NUMBER>
*
* Return Value:
* None
*
* Example:
* [2] call ace_medical_blood_fnc_init
*
* Public: No
*/
params ["_mode"];
// Exit if setting is refreshed to the same value
if (!isNil QGVAR(currentSetup) && {_mode == GVAR(currentSetup)}) exitWith {
TRACE_2("Setting refreshed to current setup",GVAR(currentSetup),_mode);
};
// Track this new configuration that will be set up
GVAR(currentSetup) = _mode;
// Delete current state machine if it exists
if (!isNil QGVAR(stateMachine)) then {
GVAR(stateMachine) call CBA_statemachine_fnc_delete;
GVAR(stateMachine) = nil;
};
// Remove wound received if it was previously added
if (!isNil QGVAR(woundReceivedEH)) then {
[QEGVAR(medical,woundReceived), GVAR(woundReceivedEH)] call CBA_fnc_removeEventHandler;
GVAR(woundReceivedEH) = nil;
};
// Don't need to set up anything if blood is disabled or players only on a non-player machine
if (_mode == BLOOD_DISABLED || {_mode == BLOOD_ONLY_PLAYERS && {!hasInterface}}) exitWith {
TRACE_1("Mode does not require any setup",_mode);
};
private _listCode = if (_mode == BLOOD_ONLY_PLAYERS) then {
// ACE_player is the only possible local player
{
if (alive ACE_player) then {
[ACE_player]
} else {
[]
};
}
} else {
// Filter all local units
EFUNC(common,getLocalUnits)
};
GVAR(stateMachine) = [_listCode, true] call CBA_statemachine_fnc_create;
[GVAR(stateMachine), LINKFUNC(onBleeding), {}, {}, "Bleeding"] call CBA_statemachine_fnc_addState;
GVAR(woundReceivedEH) = [QEGVAR(medical,woundReceived), FUNC(handleWoundReceived)] call CBA_fnc_addEventHandler;
TRACE_3("Set up state machine and wounds event",_mode,GVAR(stateMachine),GVAR(woundReceivedEH));

View File

@ -1,13 +1,13 @@
#include "script_component.hpp"
/*
* Author: Glowbal
* Check if is bleeding
* Checks if the given unit is bleeding. Handles both ACE Medical and Vanilla.
*
* Arguments:
* 0: unit <TYPE>
* 0: Unit <OBJECT>
*
* Return Value:
* is Bleeding <BOOL>
* Is Bleeding <BOOL>
*
* Example:
* [player] call ace_medical_blood_fnc_isBleeding

View File

@ -1,13 +1,14 @@
#include "script_component.hpp"
/*
* Author: Glowbal
* handle bleeding state (state machine)
* Handles periodically creating blood for a bleeding unit.
* Called from the medical_blood state machine.
*
* Arguments:
* 0: unit <TYPE>
* 0: Unit <OBJECT>
*
* Return Value:
* is Bleeding <BOOL>
* None
*
* Example:
* [player] call ace_medical_blood_fnc_onBleeding
@ -17,20 +18,20 @@
params ["_unit"];
if (!([_unit] call FUNC(isBleeding))) exitWith {};
if (((vehicle _unit) != _unit) && {!((vehicle _unit) isKindOf "StaticWeapon")}) exitWith {}; // Don't bleed on ground if mounted
// Nothing to do if unit is not bleeding
if !(_unit call FUNC(isBleeding)) exitWith {};
// Don't bleed on the ground if in a vehicle
if (vehicle _unit != _unit && {!(vehicle _unit isKindOf "StaticWeapon")}) exitWith {};
if (CBA_missionTime > (_unit getVariable [QGVAR(nextTime), -10])) then {
private _bloodLoss = (if (GVAR(useAceMedical)) then {GET_BLOOD_LOSS(_unit) * 2.5} else {getDammage _unit * 2}) min 6;
TRACE_2("",_unit,_bloodLoss);
_unit setVariable [QGVAR(nextTime), CBA_missionTime + 8 + random 2 - _bloodLoss];
TRACE_2("Creating blood drop for bleeding unit",_unit,_bloodLoss);
private _position = getPosASL _unit;
_position = _position vectorAdd [
random 0.4 - 0.2,
random 0.4 - 0.2,
0
];
_position = _position vectorAdd [random 0.4 - 0.2, random 0.4 - 0.2, 0];
_position set [2, 0];
private _bloodDrop = ["blooddrop_1", "blooddrop_2", "blooddrop_3", "blooddrop_4"] select floor (_bloodLoss min 3);

View File

@ -1,18 +1,18 @@
#include "script_component.hpp"
/*
* Author: Sickboy
* Spurt blood on the ground
* Spurts blood on the ground based on the direction and damage.
*
* Arguments:
* 0: unit <OBJECT>
* 1: direction <NUMBER>
* 2: damage <NUMBER>
* 0: Unit <OBJECT>
* 1: Direction <NUMBER>
* 2: Damage <NUMBER>
*
* Return Value:
* None
*
* Example:
* [UNIT, random 360, 1] call ace_medical_blood_fnc_spurt
* [player, random 360, 1] call ace_medical_blood_fnc_spurt
*
* Public: No
*/
@ -21,20 +21,20 @@
#define DISTANCE_BETWEEN_DROPS 0.20
#define OFFSET 0.25
params ["_unit", "_dir", "_damage"];
params ["_unit", "_direction", "_damage"];
private _distanceBetweenDrops = DISTANCE_BETWEEN_DROPS * _damage;
private _offset = OFFSET + _distanceBetweenDrops;
private _pos = _unit getPos [_offset, _dir];
private _position = _unit getPos [_offset, _direction];
["blooddrop_2", _pos, _dir] call FUNC(createBlood);
["blooddrop_2", _position, _direction] call FUNC(createBlood);
private _dropAmount = ceil (MAXIMUM_DROPS * _damage);
TRACE_2("spurt blood",_dropAmount,_damage);
TRACE_2("Spurting blood",_dropAmount,_damage);
if (_dropAmount > 1) then {
for "_i" from 2 to _dropAmount do {
_pos = _pos getPos [_distanceBetweenDrops, _dir];
["blooddrop_1", _pos, _dir] call FUNC(createBlood);
_position = _position getPos [_distanceBetweenDrops, _direction];
["blooddrop_1", _position, _direction] call FUNC(createBlood);
};
};

View File

@ -1,13 +1,27 @@
// CBA Settings [ADDON: ace_medical_blood]:
private _categoryArray = [LELSTRING(medical,Category), LLSTRING(subCategory)];
[
QGVAR(enabledFor),
"LIST",
[LSTRING(EnabledFor_DisplayName), LSTRING(EnabledFor_Description)],
[ELSTRING(medical,Category), LSTRING(SubCategory)],
[[BLOOD_DISABLED, BLOOD_ONLY_PLAYERS, BLOOD_ENABLED], [ELSTRING(Common,Disabled), LSTRING(OnlyPlayers), ELSTRING(Common,Enabled)], 2],
true,
LINKFUNC(init)
] call CBA_settings_fnc_init;
[
QGVAR(enabledFor), "LIST",
[LSTRING(MedicalBloodSettings_enabledFor_DisplayName), LSTRING(MedicalBloodSettings_enabledFor_Description)],
_categoryArray,
[[0,1,2],[LELSTRING(Common,Disabled),LLSTRING(enabledFor_OnlyPlayers),LELSTRING(Common,Enabled)],2], // [values, titles, defaultIndex]
true, // isGlobal
{[QGVAR(enabledFor), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart
QGVAR(maxBloodObjects),
"LIST",
[LSTRING(MaxBloodObjects_DisplayName), LSTRING(MaxBloodObjects_Description)],
[ELSTRING(medical,Category), LSTRING(SubCategory)],
[[50, 100, 200, 300, 400, 500, 1000, 2000, 3000, 4000, 5000], [/* settings function will auto create names */], 5],
true
] call CBA_settings_fnc_init;
[
QGVAR(bloodLifetime),
"TIME",
[LSTRING(BloodLifetime_DisplayName), LSTRING(BloodLifetime_Description)],
[ELSTRING(medical,Category), LSTRING(SubCategory)],
[1, 3600, 900],
true
] call CBA_settings_fnc_init;

View File

@ -2,7 +2,7 @@
#define COMPONENT_BEAUTIFIED Medical Blood
#include "\z\ace\addons\main\script_mod.hpp"
// #define DEBUG_ENABLED_MEDICAL_BLOOD
// #define DEBUG_MODE_FULL
// #define DISABLE_COMPILE_CACHE
// #define ENABLE_PERFORMANCE_COUNTERS
@ -17,5 +17,6 @@
#include "\z\ace\addons\medical_engine\script_macros_medical.hpp"
#include "\z\ace\addons\main\script_macros.hpp"
#define MAX_BLOOD_OBJECTS 500
#define BLOOD_OBJECT_LIFETIME 900
#define BLOOD_DISABLED 0
#define BLOOD_ONLY_PLAYERS 1
#define BLOOD_ENABLED 2

View File

@ -1,24 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project name="ACE">
<Package name="medical_blood">
<Key ID="STR_ACE_medical_blood_subCategory">
<English>Bleeding Effect</English>
<Japanese>出血中の効果</Japanese>
<Russian>Эффекты кровотечения</Russian>
<Package name="Medical_Blood">
<Key ID="STR_ACE_Medical_Blood_SubCategory">
<English>Blood</English>
<French>Sang</French>
<Spanish>Sangre</Spanish>
<Italian>Sangue</Italian>
<Polish>Krew</Polish>
<Russian>Кровь</Russian>
<German>Blut</German>
<Czech>Krev</Czech>
<Portuguese>Sangue</Portuguese>
<Korean>혈흔</Korean>
<Japanese>血痕</Japanese>
</Key>
<Key ID="STR_ACE_medical_blood_enabledFor_OnlyPlayers">
<English>Only Players</English>
<Japanese>プレイヤーのみ</Japanese>
<German>Nur Spieler</German>
<Korean>오직 플레이어만</Korean>
<Polish>Tylko gracze</Polish>
<French>Joueurs seulement</French>
<Italian>Solo Giocatori</Italian>
<Chinesesimp>只有玩家</Chinesesimp>
<Chinese>只有玩家</Chinese>
<Russian>Только игроки</Russian>
</Key>
<Key ID="STR_ACE_medical_blood_MedicalBloodSettings_enabledFor_DisplayName">
<Key ID="STR_ACE_Medical_Blood_EnabledFor_DisplayName">
<English>Enable Blood Drops</English>
<Japanese>血痕を有効化</Japanese>
<German>Aktiviere Blutspritzer</German>
@ -30,17 +26,37 @@
<Chinese>開啟血液滴落效果</Chinese>
<Russian>Разрешить капли крови</Russian>
</Key>
<Key ID="STR_ACE_medical_blood_MedicalBloodSettings_enabledFor_Description">
<English>Enable or disable Blood Drops created on bleeding and taking damage</English>
<Japanese>ダメージを受けたり、出血していると出る血痕の有効か無効化</Japanese>
<German>Aktiviere oder deaktiviere Blutspritzer, die durch Blutungen oder bei Schadensnahme entstehen.</German>
<Polish>Włącz lub wyłącz pozostawianie śladów krwi na ziemi kiedy postać odnosi obrażenia bądź krwawi</Polish>
<French>(Dés)active les gouttes de sang lors d'un saignement ou de blessure</French>
<Italian>Abilita o disabilita la Perdite di Sangue create sanguinando e prendendo danno</Italian>
<Chinesesimp>开启后, 会让受伤时伤口有血液滴落的效果</Chinesesimp>
<Chinese>開啟後, 會讓受傷時傷口有血液滴落的效果</Chinese>
<Korean>출혈이나 부상을 입었을 때, 떨어지는 혈액을 활성화 하거나 비활성화 합니다.</Korean>
<Russian>Включает или отключает капли крови при кровотечении и получении урона</Russian>
<Key ID="STR_ACE_Medical_Blood_EnabledFor_Description">
<English>Enables the creation of blood drops when units are bleeding or take damage.</English>
<Japanese>ユニットが出血かダメージを受けた時に、血痕を残すようにします。</Japanese>
</Key>
<Key ID="STR_ACE_Medical_Blood_MaxBloodObjects_DisplayName">
<English>Max Blood Objects</English>
<Japanese>最大血痕数</Japanese>
</Key>
<Key ID="STR_ACE_Medical_Blood_MaxBloodObjects_Description">
<English>Sets the maximum number of blood drop objects which can be spawned, excessive amounts can cause FPS lag.</English>
<Japanese>生成される血痕オブジェクト数を設定できます。極端に増やすと FPS ラグを引き起こします。</Japanese>
</Key>
<Key ID="STR_ACE_Medical_Blood_BloodLifetime_DisplayName">
<English>Blood Lifetime</English>
<Japanese>血痕の寿命</Japanese>
</Key>
<Key ID="STR_ACE_Medical_Blood_BloodLifetime_Description">
<English>Controls the lifetime of blood drop objects.</English>
<Japanese>血痕オブジェクトの寿命を決定します。</Japanese>
</Key>
<Key ID="STR_ACE_Medical_Blood_OnlyPlayers">
<English>Only Players</English>
<Japanese>プレイヤーのみ</Japanese>
<German>Nur Spieler</German>
<Korean>오직 플레이어만</Korean>
<Polish>Tylko gracze</Polish>
<French>Joueurs seulement</French>
<Italian>Solo Giocatori</Italian>
<Chinesesimp>只有玩家</Chinesesimp>
<Chinese>只有玩家</Chinese>
<Russian>Только игроки</Russian>
</Key>
</Package>
</Project>

View File

@ -1,4 +1,4 @@
// bleeding - maximum possible bleeding rate for a given wound type (0 .. 1)
// bleeding - maximum possible percentage of cardiac output bled for a given wound type (0 .. 1)
// pain - maximum possible pain level for a given wound type (0 .. 1)
class ACE_Medical_Injuries {
@ -16,7 +16,7 @@ class ACE_Medical_Injuries {
// Occur when an entire structure or part of it is forcibly pulled away, such as the loss of a permanent tooth or an ear lobe. Explosions, gunshots, and animal bites may cause avulsions.
class Avulsion {
causes[] = {"explosive", "vehiclecrash", "collision", "grenade", "shell", "bullet", "backblast", "bite"};
bleeding = 0.25;
bleeding = 0.1;
pain = 1.0;
minDamage = 0.01;
causeLimping = 1;
@ -24,7 +24,7 @@ class ACE_Medical_Injuries {
// Also called bruises, these are the result of a forceful trauma that injures an internal structure without breaking the skin. Blows to the chest, abdomen, or head with a blunt instrument (e.g. a football or a fist) can cause contusions.
class Contusion {
causes[] = {"bullet", "backblast", "punch", "vehiclecrash", "collision", "falling"};
bleeding = 0.0;
bleeding = 0;
pain = 0.3;
minDamage = 0.02;
maxDamage = 0.35;
@ -41,7 +41,7 @@ class ACE_Medical_Injuries {
// Slicing wounds made with a sharp instrument, leaving even edges. They may be as minimal as a paper cut or as significant as a surgical incision.
class Cut {
causes[] = {"vehiclecrash", "collision", "grenade", "explosive", "shell", "backblast", "stab", "unknown"};
bleeding = 0.04;
bleeding = 0.01;
pain = 0.1;
minDamage = 0.1;
};
@ -56,7 +56,7 @@ class ACE_Medical_Injuries {
// Also called velocity wounds, they are caused by an object entering the body at a high speed, typically a bullet or small peices of shrapnel.
class VelocityWound {
causes[] = {"bullet", "grenade","explosive", "shell", "unknown"};
bleeding = 0.5;
bleeding = 0.2;
pain = 0.9;
minDamage = 0.35;
causeLimping = 1;

View File

@ -28,7 +28,7 @@ _bodyPartDamage params ["_headDamage", "_bodyDamage", "_leftArmDamage", "_rightA
if (_bodyPartN == 1 && {_damage < PENETRATION_THRESHOLD}) then {
_bodyDamage = _bodyDamage - (_amountOf * _damage);
};
} forEach (_unit getVariable [QEGVAR(medical,openWounds), []]);
} forEach GET_OPEN_WOUNDS(_unit);
private _damageThreshold = [
EGVAR(medical,AIDamageThreshold),

View File

@ -32,7 +32,7 @@ if (isNil {GVAR(allDamageTypesData) getVariable _typeOfDamage} ) then {
};
// Administration for open wounds and ids
private _openWounds = _unit getVariable [QEGVAR(medical,openWounds), []];
private _openWounds = GET_OPEN_WOUNDS(_unit);
private _woundID = _unit getVariable [QEGVAR(medical,lastUniqueWoundID), 1]; // Unique wound ids are not used anywhere: ToDo Remove from openWounds array
TRACE_4("extension call",_bodyPart,_damage,_typeOfDamage,_woundID);
@ -128,7 +128,7 @@ private _bodyPartVisParams = [_unit, false, false, false, false]; // params arra
};
} forEach _woundsCreated;
_unit setVariable [QEGVAR(medical,openWounds), _openWounds, true];
_unit setVariable [VAR_OPEN_WOUNDS, _openWounds, true];
_unit setVariable [QEGVAR(medical,bodyPartDamage), _bodyPartDamage, true];
[_unit] call EFUNC(medical_status,updateWoundBloodLoss);
@ -141,4 +141,4 @@ if (_critialDamage || {_painLevel > PAIN_UNCONSCIOUS}) then {
[_unit] call FUNC(handleIncapacitation);
};
TRACE_5("exit",_unit,_painLevel,GET_PAIN(_unit),_unit getVariable QEGVAR(medical,openWounds),_woundsCreated);
TRACE_5("exit",_unit,_painLevel,GET_PAIN(_unit),GET_OPEN_WOUNDS(_unit),_woundsCreated);

View File

@ -65,7 +65,7 @@ private _allPossibleInjuries = [];
if (_highestPossibleSpot < 0) exitWith { TRACE_2("no wounds possible",_damage,_highestPossibleSpot); };
// Administration for open wounds and ids
private _openWounds = _unit getVariable [QEGVAR(medical,openWounds), []];
private _openWounds = GET_OPEN_WOUNDS(_unit);
private _updateDamageEffects = false;
private _painLevel = 0;
@ -75,11 +75,11 @@ private _bodyPartVisParams = [_unit, false, false, false, false]; // params arra
{
_x params ["_thresholdMinDam", "_thresholdWoundCount"];
if (_thresholdMinDam <= _damage) exitWith {
if (_damage > _thresholdMinDam) exitWith {
private _woundDamage = _damage / (_thresholdWoundCount max 1); // If the damage creates multiple wounds
for "_i" from 1 to _thresholdWoundCount do {
// Find the injury we are going to add. Format [ classID, allowdSelections, bleedingRate, injuryPain]
private _oldInjury = if (random 1 >= 0.85) then {
// Find the injury we are going to add. Format [ classID, allowedSelections, bleedingRate, injuryPain]
private _oldInjury = if (random 1 < 0.15) then {
_woundTypes select _highestPossibleSpot
} else {
selectRandom _allPossibleInjuries
@ -93,17 +93,24 @@ private _bodyPartVisParams = [_unit, false, false, false, false]; // params arra
_bodyPartVisParams set [[1,2,3,3,4,4] select _bodyPartNToAdd, true]; // Mark the body part index needs updating
// The higher the nastiness likelihood the higher the change to get a painful and bloody wound
private _nastinessLikelihood = linearConversion [0, 20, (_woundDamage / _thresholdWoundCount), 0.5, 30, true];
private _bleedingModifier = 0.25 + 8 * exp ((random [-4.5, -5, -6]) / _nastinessLikelihood);
private _painModifier = 0.05 + 2 * exp (-2 / _nastinessLikelihood);
// Damage to limbs/head is scaled higher than torso by engine
// Anything above this value is guaranteed worst wound possible
private _worstDamage = [2, 1, 4, 4, 4, 4] select _bodyPartNToAdd;
private _bleeding = _injuryBleedingRate * _bleedingModifier;
// More wounds means more likely to get nasty wound
private _countModifier = 1 + random(_i - 1);
// Config specifies bleeding and pain for worst possible wound
// Worse wound correlates to higher damage, damage is not capped at 1
private _bleedModifier = linearConversion [0.1, _worstDamage, _woundDamage * _countModifier, 0.25, 1, true];
private _painModifier = (_bleedModifier * random [0.7, 1, 1.3]) min 1; // Pain isn't directly scaled to bleeding
private _bleeding = _injuryBleedingRate * _bleedModifier;
private _pain = _injuryPain * _painModifier;
_painLevel = _painLevel + _pain;
// wound category (minor [0..0.5], medium[0.5..1.0], large[1.0+])
private _category = floor linearConversion [0, 1, _bleedingModifier, 0, 2, true];
// wound category (minor [0.25-0.5], medium [0.5-0.75], large [0.75+])
private _category = floor linearConversion [0.25, 0.75, _bleedModifier, 0, 2, true];
private _classComplex = 10 * _woundClassIDToAdd + _category;
@ -135,7 +142,6 @@ private _bodyPartVisParams = [_unit, false, false, false, false]; // params arra
};
case (_causeFracture && {EGVAR(medical,fractures) > 0} && {_bodyPartNToAdd > 1} && {_woundDamage > FRACTURE_DAMAGE_THRESHOLD}): {
TRACE_1("limb fracture",_bodyPartNToAdd);
// todo: play sound?
private _fractures = GET_FRACTURES(_unit);
_fractures set [_bodyPartNToAdd, 1];
_unit setVariable [VAR_FRACTURES, _fractures, true];
@ -180,7 +186,7 @@ if (_updateDamageEffects) then {
[_unit] call EFUNC(medical_engine,updateDamageEffects);
};
_unit setVariable [QEGVAR(medical,openWounds), _openWounds, true];
_unit setVariable [VAR_OPEN_WOUNDS, _openWounds, true];
_unit setVariable [QEGVAR(medical,bodyPartDamage), _bodyPartDamage, true];
[_unit] call EFUNC(medical_status,updateWoundBloodLoss);
@ -193,4 +199,4 @@ if (_critialDamage || {_painLevel > PAIN_UNCONSCIOUS}) then {
[_unit] call FUNC(handleIncapacitation);
};
TRACE_4("exit",_unit,_painLevel,GET_PAIN(_unit),_unit getVariable QEGVAR(medical,openWounds));
TRACE_4("exit",_unit,_painLevel,GET_PAIN(_unit),GET_OPEN_WOUNDS(_unit));

View File

@ -1,23 +1,17 @@
// CBA Settings [ADDON: ace_medical_damage]:
private _categoryArray = [LELSTRING(medical,Category), LLSTRING(subCategory)];
[
QEGVAR(medical,playerDamageThreshold), "SLIDER",
[LSTRING(playerDamageThreshold_DisplayName), LSTRING(playerDamageThreshold_Description)],
_categoryArray,
[0,25,1,2], // [min, max, default value, trailing decimals (-1 for whole numbers only)]
true, // isGlobal
{[QEGVAR(medical,playerDamageThreshold), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart
QEGVAR(medical,playerDamageThreshold),
"SLIDER",
[LSTRING(PlayerDamageThreshold_DisplayName), LSTRING(PlayerDamageThreshold_Description)],
ELSTRING(medical,Category),
[0, 25, 1, 2],
true
] call CBA_settings_fnc_init;
[
QEGVAR(medical,AIDamageThreshold), "SLIDER",
QEGVAR(medical,AIDamageThreshold),
"SLIDER",
[LSTRING(AIDamageThreshold_DisplayName), LSTRING(AIDamageThreshold_Description)],
_categoryArray,
[0,25,1,2], // [min, max, default value, trailing decimals (-1 for whole numbers only)]
true, // isGlobal
{[QEGVAR(medical,AIDamageThreshold), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart
ELSTRING(medical,Category),
[0, 25, 1, 2],
true
] call CBA_settings_fnc_init;

View File

@ -1,77 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project name="ACE">
<Package name="Medical_Damage">
<Container name="Settings">
<Key ID="STR_ACE_Medical_damage_subCategory">
<English>Damage Threshold</English>
<Japanese>損傷のしきい値</Japanese>
<Russian>Порог повреждения</Russian>
</Key>
<Key ID="STR_ACE_Medical_damage_playerDamageThreshold_DisplayName">
<English>Player Damage</English>
<Russian>Урон игроку</Russian>
<Polish>Próg obrażeń graczy</Polish>
<Spanish>Daño de jugador</Spanish>
<German>Spielerschaden</German>
<Czech>Poškození hráče</Czech>
<Portuguese>Dano do jogador</Portuguese>
<French>Dégats du joueur</French>
<Hungarian>Játékos sérülés</Hungarian>
<Italian>Danno Giocatore</Italian>
<Japanese>プレイヤーへの損傷</Japanese>
<Korean>플레이어 부상</Korean>
<Chinesesimp>玩家伤害</Chinesesimp>
<Chinese>玩家傷害</Chinese>
</Key>
<Key ID="STR_ACE_Medical_damage_playerDamageThreshold_Description">
<English>What is the damage a player can take before being killed?</English>
<Russian>Какой уровень урона необходим, чтобы убить игрока?</Russian>
<Polish>Jaki jest próg obrażeń, jakie gracz może otrzymać zanim zostanie zabity?</Polish>
<Spanish>¿Cuál es el daño que un jugador puede sufrir antes de morir?</Spanish>
<German>Wie viel Schaden kann ein Spieler erleiden, bevor er getötet wird?</German>
<Czech>Jaké poškození může hráč dostat než bude zabit?</Czech>
<Portuguese>Qal é o dano que um jogador pode sofrer antes de morrer?</Portuguese>
<French>Quels dégâts peut subir un joueur avant d'être tué</French>
<Hungarian>Mennyi sérülést szenvedhet el egy játékos, mielőtt meghal?</Hungarian>
<Italian>Quanto è il danno che un giocatore può sostenere prima di essere ucciso?</Italian>
<Japanese>プレイヤーが死に始める前に損傷を受けるようにしますか?</Japanese>
<Korean>얼마정도의 부상을 플레이어가 죽기 전까지 버틸 수 있습니까?</Korean>
<Chinesesimp>玩家死亡前所能承受的伤害程度</Chinesesimp>
<Chinese>玩家死亡前所能承受的傷害程度</Chinese>
</Key>
<Key ID="STR_ACE_Medical_damage_AIDamageThreshold_DisplayName">
<English>AI Damage</English>
<Russian>Урон ботам</Russian>
<Polish>Próg obrażeń AI</Polish>
<Spanish>Daño IA</Spanish>
<German>KI-Schaden</German>
<Czech>Poškození AI</Czech>
<Portuguese>Dano da IA</Portuguese>
<French>Dégâts des IA</French>
<Hungarian>AI sérülés</Hungarian>
<Italian>Danno AI</Italian>
<Japanese>AI への損傷</Japanese>
<Korean>인공지능 부상</Korean>
<Chinesesimp>AI伤害</Chinesesimp>
<Chinese>AI傷害</Chinese>
</Key>
<Key ID="STR_ACE_Medical_damage_AIDamageThreshold_Description">
<English>What is the damage an AI can take before being killed?</English>
<Russian>Какой уровень урона необходим, чтобы убить бота?</Russian>
<Polish>Jaki jest próg obrażeń, jakie AI może otrzymać zanim zostanie zabite?</Polish>
<Spanish>¿Cuál es el daño que la IA puede sufrir antes de morir?</Spanish>
<German>Wie viel Schaden kann eine KI erleiden, bis sie getötet wird?</German>
<Czech>Jaké poškození může AI dostat než bude zabito?</Czech>
<Portuguese>Qual é o dano que uma IA pode sofrer antes de morrer?</Portuguese>
<French>Quels dégâts peut subir une IA avant d'être tuée</French>
<Hungarian>Mennyi sérülést szenvedhet el egy AI, mielőtt meghal?</Hungarian>
<Italian>Quanto è il danno che un'IA può sostenere prima di essere uccisa?</Italian>
<Japanese>AI が死に始める前に損傷を受けるようにしますか?</Japanese>
<Korean>얼마정도의 부상을 인공지능이 죽기 전까지 버틸 수 있습니까?</Korean>
<Chinesesimp>AI 死亡前所能承受的伤害程度</Chinesesimp>
<Chinese>AI 死亡前所能承受的傷害程度</Chinese>
</Key>
</Container>
<Key ID="STR_ACE_Medical_Damage_PlayerDamageThreshold_DisplayName">
<English>Player Critical Damage Threshold</English>
<Japanese>プレイヤーのクリティカル ダメージしきい値</Japanese>
</Key>
<Key ID="STR_ACE_Medical_Damage_PlayerDamageThreshold_Description">
<English>Sets the amount of damage a player can receive before going unconscious.</English>
<Japanese>プレイヤーが気絶になる前に受けられるダメージ量を決定できます。</Japanese>
</Key>
<Key ID="STR_ACE_Medical_Damage_AIDamageThreshold_DisplayName">
<English>AI Critical Damage Threshold</English>
<Japanese>AI のクリティカル ダメージしきい値</Japanese>
</Key>
<Key ID="STR_ACE_Medical_Damage_AIDamageThreshold_Description">
<English>Sets the amount of damage an AI unit can receive before going unconscious.</English>
<Japanese>AI が気絶になる前に受けられるダメージ量を決定できます。</Japanese>
</Key>
<Key ID="STR_ACE_Medical_Damage_Abrasion">
<English>Scrape</English>
<German>Kratzer</German>

View File

@ -63,6 +63,11 @@ class CfgVehicles {
ADD_ACE_HITPOINTS(1,1);
};
};
class B_Protagonist_VR_F: B_Soldier_base_F {
class HitPoints {
ADD_ACE_HITPOINTS(1,1);
};
};
class O_Soldier_VR_F: O_Soldier_base_F {
class HitPoints {
ADD_ACE_HITPOINTS(1,1);
@ -73,10 +78,7 @@ class CfgVehicles {
ADD_ACE_HITPOINTS(1,1);
};
};
// Civilians
class C_man_1;
class C_Soldier_VR_F: C_man_1 {
class I_Protagonist_VR_F: I_Soldier_base_F {
class HitPoints {
ADD_ACE_HITPOINTS(1,1);
};
@ -86,6 +88,19 @@ class CfgVehicles {
ADD_ACE_HITPOINTS(1,1);
};
};
class C_man_1;
class C_Protagonist_VR_F: C_man_1 {
class HitPoints {
ADD_ACE_HITPOINTS(1,1);
};
};
// Civilians
class C_Soldier_VR_F: C_man_1 {
class HitPoints {
ADD_ACE_HITPOINTS(1,1);
};
};
// APEX
class O_V_Soldier_Viper_F: O_Soldier_base_F {

View File

@ -82,6 +82,11 @@ if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
_allDamages sort false;
(_allDamages select 0) params ["_receivedDamage", "", "_woundedHitPoint"];
if (_damageHead >= HEAD_DAMAGE_THRESHOLD) then {
TRACE_3("reporting fatal head damage instead of max",_damageHead,_receivedDamage,_woundedHitPoint);
_receivedDamage = _damageHead;
_woundedHitPoint = "Head";
};
// We know it's structural when no specific hitpoint is damaged
if (_receivedDamage == 0) then {

View File

@ -46,9 +46,9 @@ if (EGVAR(medical,fractures) > 0) then {
};
if (!_isLimping && {EGVAR(medical,limping) > 0}) then {
private _woundsToCheck = _unit getVariable [QEGVAR(medical,openWounds), []];
private _woundsToCheck = GET_OPEN_WOUNDS(_unit);
if (EGVAR(medical,limping) == 2) then {
_woundsToCheck = _woundsToCheck + (_unit getVariable [QEGVAR(medical,bandagedWounds), []]); // do not append
_woundsToCheck = _woundsToCheck + GET_BANDAGED_WOUNDS(_unit); // do not append
};
{
_x params ["_xClassID", "_xBodyPartN", "_xAmountOf", "", "_xDamage"];

View File

@ -1,5 +1,5 @@
#define COMPONENT medical_engine
#define COMPONENT_BEAUTIFIED Medical (Engine)
#define COMPONENT_BEAUTIFIED Medical Engine
#include "\z\ace\addons\main\script_mod.hpp"
// #define DEBUG_MODE_FULL

View File

@ -118,38 +118,45 @@
// - Unit Variables ----------------------------------------------------
// These variables get stored in object space and used across components
// Defined here for easy consistency with GETVAR/SETVAR (also a list for reference)
#define VAR_BLOOD_PRESS QEGVAR(medical,bloodPressure)
#define VAR_BLOOD_VOL QEGVAR(medical,bloodVolume)
#define VAR_WOUND_BLEEDING QEGVAR(medical,woundBleeding)
#define VAR_CRDC_ARRST QEGVAR(medical,inCardiacArrest)
#define VAR_HEART_RATE QEGVAR(medical,heartRate)
#define VAR_PAIN QEGVAR(medical,pain)
#define VAR_PAIN_SUPP QEGVAR(medical,painSuppress)
#define VAR_PERIPH_RES QEGVAR(medical,peripheralResistance)
#define VAR_UNCON "ACE_isUnconscious"
#define VAR_BLOOD_PRESS QEGVAR(medical,bloodPressure)
#define VAR_BLOOD_VOL QEGVAR(medical,bloodVolume)
#define VAR_WOUND_BLEEDING QEGVAR(medical,woundBleeding)
#define VAR_CRDC_ARRST QEGVAR(medical,inCardiacArrest)
#define VAR_HEART_RATE QEGVAR(medical,heartRate)
#define VAR_PAIN QEGVAR(medical,pain)
#define VAR_PAIN_SUPP QEGVAR(medical,painSuppress)
#define VAR_PERIPH_RES QEGVAR(medical,peripheralResistance)
#define VAR_UNCON "ACE_isUnconscious"
#define VAR_OPEN_WOUNDS QEGVAR(medical,openWounds)
#define VAR_BANDAGED_WOUNDS QEGVAR(medical,bandagedWounds)
#define VAR_STITCHED_WOUNDS QEGVAR(medical,stitchedWounds)
// These variables track gradual adjustments (from medication, etc.)
#define VAR_MEDICATIONS QEGVAR(medical,medications)
#define VAR_MEDICATIONS QEGVAR(medical,medications)
// These variables track the current state of status values above
#define VAR_HEMORRHAGE QEGVAR(medical,hemorrhage)
#define VAR_IN_PAIN QEGVAR(medical,inPain)
#define VAR_TOURNIQUET QEGVAR(medical,tourniquets)
#define VAR_FRACTURES QEGVAR(medical,fractures)
#define VAR_HEMORRHAGE QEGVAR(medical,hemorrhage)
#define VAR_IN_PAIN QEGVAR(medical,inPain)
#define VAR_TOURNIQUET QEGVAR(medical,tourniquets)
#define VAR_FRACTURES QEGVAR(medical,fractures)
// - Unit Functions ---------------------------------------------------
// Retrieval macros for common unit values
// Defined for easy consistency and speed
#define GET_BLOOD_VOLUME(unit) (unit getVariable [VAR_BLOOD_VOL,DEFAULT_BLOOD_VOLUME])
#define GET_WOUND_BLEEDING(unit) (unit getVariable [VAR_WOUND_BLEEDING,0])
#define GET_HEART_RATE(unit) (unit getVariable [VAR_HEART_RATE,DEFAULT_HEART_RATE])
#define GET_HEMORRHAGE(unit) (unit getVariable [VAR_HEMORRHAGE,0])
#define GET_PAIN(unit) (unit getVariable [VAR_PAIN,0])
#define GET_PAIN_SUPPRESS(unit) (unit getVariable [VAR_PAIN_SUPP,0])
#define GET_SM_STATE(_unit) ([_unit, EGVAR(medical,STATE_MACHINE)] call CBA_statemachine_fnc_getCurrentState)
#define GET_BLOOD_VOLUME(unit) (unit getVariable [VAR_BLOOD_VOL, DEFAULT_BLOOD_VOLUME])
#define GET_WOUND_BLEEDING(unit) (unit getVariable [VAR_WOUND_BLEEDING, 0])
#define GET_HEART_RATE(unit) (unit getVariable [VAR_HEART_RATE, DEFAULT_HEART_RATE])
#define GET_HEMORRHAGE(unit) (unit getVariable [VAR_HEMORRHAGE, 0])
#define GET_PAIN(unit) (unit getVariable [VAR_PAIN, 0])
#define GET_PAIN_SUPPRESS(unit) (unit getVariable [VAR_PAIN_SUPP, 0])
#define GET_TOURNIQUETS(unit) (unit getVariable [VAR_TOURNIQUET, DEFAULT_TOURNIQUET_VALUES])
#define GET_FRACTURES(unit) (unit getVariable [VAR_FRACTURES, DEFAULT_FRACTURE_VALUES])
#define IN_CRDC_ARRST(unit) (unit getVariable [VAR_CRDC_ARRST,false])
#define IN_CRDC_ARRST(unit) (unit getVariable [VAR_CRDC_ARRST, false])
#define IS_BLEEDING(unit) (GET_WOUND_BLEEDING(unit) > 0)
#define IS_IN_PAIN(unit) (unit getVariable [VAR_IN_PAIN,false])
#define IS_UNCONSCIOUS(unit) (unit getVariable [VAR_UNCON,false])
#define IS_IN_PAIN(unit) (unit getVariable [VAR_IN_PAIN, false])
#define IS_UNCONSCIOUS(unit) (unit getVariable [VAR_UNCON, false])
#define GET_OPEN_WOUNDS(unit) (unit getVariable [VAR_OPEN_WOUNDS, []])
#define GET_BANDAGED_WOUNDS(unit) (unit getVariable [VAR_BANDAGED_WOUNDS, []])
#define GET_STITCHED_WOUNDS(unit) (unit getVariable [VAR_STITCHED_WOUNDS, []])
// The following function calls are defined here just for consistency
#define GET_BLOOD_LOSS(unit) ([unit] call EFUNC(medical_status,getBloodLoss))

View File

@ -1,4 +1,5 @@
class ACE_Settings {
/*
// Not currently used anywhere
class GVAR(enableScreams) {
category = ECSTRING(medical,Category_Medical);
@ -7,4 +8,5 @@ class ACE_Settings {
typeName = "BOOL";
value = 1;
};
*/
};

View File

@ -34,4 +34,24 @@ class CfgSounds {
sound[] = {QPATHTOF(sounds\slow_2.wav), "db+1", 1};
titles[] = {};
};
class ACE_fracture_1 {
name = "ACE_fracture_1";
sound[] = {QPATHTOF(sounds\fracture_1.wav), "db+1", 1};
titles[] = {};
};
class ACE_fracture_2 {
name = "ACE_fracture_2";
sound[] = {QPATHTOF(sounds\fracture_2.wav), "db+1", 1};
titles[] = {};
};
class ACE_fracture_3 {
name = "ACE_fracture_3";
sound[] = {QPATHTOF(sounds\fracture_3.wav), "db+1", 1};
titles[] = {};
};
class ACE_fracture_4 {
name = "ACE_fracture_4";
sound[] = {QPATHTOF(sounds\fracture_4.wav), "db+1", 1};
titles[] = {};
};
};

View File

@ -10,6 +10,14 @@
[_unit, "moan", PAIN_TO_MOAN(_painLevel)] call FUNC(playInjuredSound);
}] call CBA_fnc_addEventHandler;
[QEGVAR(medical,fracture), {
params ["_unit"];
if (_unit == ACE_player) then {
playSound SND_FRACTURE;
};
}] call CBA_fnc_addEventHandler;
if (!hasInterface) exitWith {};
GVAR(nextFadeIn) = 0;
@ -22,6 +30,7 @@ GVAR(heartBeatEffectRunning) = false;
params ["_unit", "_unconscious"];
if (_unit != ACE_player) exitWith {};
TRACE_1("player unconscious eh",_unconscious);
if (_unconscious && {cameraView == "GUNNER"} && {(vehicle _unit) != _unit} && {cameraOn == vehicle _unit}) then {
TRACE_2("exiting gunner view",cameraOn,cameraView);

View File

@ -39,7 +39,7 @@ if (GVAR(painEffectType) == 0) then {
GVAR(ppPain) = [
"ColorCorrections",
13502,
[1, 1, 0, [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[1, 1, 0, [1, 1, 1, 0], [1, 1, 1, 1], [0.33, 0.33, 0.33, 0], [0.59, 0.64, 0, 0, 0, 0, 4]]
] call _fnc_createEffect;
} else {
GVAR(ppPain) = [

View File

@ -1,21 +1,16 @@
// CBA Settings [ADDON: ace_medical_feedback]:
private _categoryArray = [LELSTRING(medical,Category), LLSTRING(subCategory)];
[
QGVAR(painEffectType),
"LIST",
[localize LSTRING(painEffectType), "Selects the used pain effect type"], //@todo
_categoryArray,
[
[0, 1],
[LLSTRING(painEffectType_whiteFlashing), LLSTRING(painEffectType_pulsingBlur)],
0
],
[LSTRING(PainEffectType_DisplayName), LSTRING(PainEffectType_Description)],
[ELSTRING(medical,Category), LSTRING(SubCategory)],
[[0, 1], [LSTRING(PainEffectType_WhiteFlashing), LSTRING(PainEffectType_PulsingBlur)], 0],
false,
{
if (isNil QGVAR(ppPain)) exitWith {TRACE_1("Before Post-Init",_this)};
TRACE_1("reseting ppEffect type",_this);
if (isNil QGVAR(ppPain)) exitWith {
TRACE_1("painEffectType setting - before postInit",_this);
};
TRACE_1("painEffectType setting - resetting effect",_this);
[true] call FUNC(initEffects);
}
] call CBA_Settings_fnc_init;

View File

@ -34,5 +34,6 @@
#define SND_HEARBEAT_FAST (selectRandom ["ACE_heartbeat_fast_1", "ACE_heartbeat_fast_2", "ACE_heartbeat_fast_3"])
#define SND_HEARBEAT_NORMAL (selectRandom ["ACE_heartbeat_norm_1", "ACE_heartbeat_norm_2"])
#define SND_HEARBEAT_SLOW (selectRandom ["ACE_heartbeat_slow_1", "ACE_heartbeat_slow_2"])
#define SND_FRACTURE (selectRandom ["ACE_fracture_1", "ACE_fracture_2", "ACE_fracture_3", "ACE_fracture_4"])
#define VOL_UNCONSCIOUS 0.25

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,12 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<Project name="ACE">
<Package name="Medical_Feedback">
<Key ID="STR_ACE_Medical_Feedback_SubCategory">
<English>Feedback</English>
<German>Feedback</German>
<Japanese>フィードバック</Japanese>
<Russian>Реакция на ранения</Russian>
</Key>
<Key ID="STR_ACE_Medical_Feedback_PainEffectType_DisplayName">
<English>Pain Effect Type</English>
<German>Schmerzeffekt-Typ</German>
<Polish>Rodzaj efektu bólu</Polish>
<Russian>Визуальный эффект боли</Russian>
<Italian>Pain Effect Type</Italian>
<Spanish>Tipo de efecto de dolor</Spanish>
<French>Type d'effet de douleur</French>
<Hungarian>Fájdalom-effekt típusa</Hungarian>
<Portuguese>Tipo do efeito de dor</Portuguese>
<Czech>Typ bolesti - efekt</Czech>
<Japanese>痛み効果の種類</Japanese>
<Korean>고통 효과 종류</Korean>
</Key>
<Key ID="STR_ACE_Medical_Feedback_PainEffectType_Description">
<English>Selects the used pain effect type.</English>
<Japanese>痛みの効果の種類を選択できます。</Japanese>
</Key>
<Key ID="STR_ACE_Medical_Feedback_PainEffectType_WhiteFlashing">
<English>White Flashing</English>
<German>Weißes blinken</German>
<Japanese>白く点滅</Japanese>
<Russian>Белые вспышки</Russian>
</Key>
<Key ID="STR_ACE_Medical_Feedback_PainEffectType_PulsingBlur">
<English>Pulsing Blur</English>
<German>Wiederkehrende Unschärfe</German>
<Japanese>ボケの強弱</Japanese>
<Russian>Пульсирующее размытие</Russian>
</Key>
<Container name="Settings">
<Key ID="STR_ACE_Medical_feedback_subCategory">
<English>Feedback</English>
<Japanese>フィードバック</Japanese>
<Russian>Реакция на ранения</Russian>
</Key>
<Key ID="STR_ACE_Medical_feedback_enableScreams_DisplayName">
<English>Enable Screams</English>
<Russian>Включить крики</Russian>
@ -34,35 +65,11 @@
<French>Active les hurlements d'unités blessées</French>
<Hungarian>Engedélyezi a sérült egységek kiáltásait</Hungarian>
<Italian>Abilita Grida da parte delle unità ferite</Italian>
<Japanese>負傷したユニットが叫びだします。</Japanese>
<Japanese>負傷したユニットを叫ぶようにします。</Japanese>
<Korean>부상당한 인원이 소리지르는것을 활성화합니다</Korean>
<Chinesesimp>启用伤者的尖叫声</Chinesesimp>
<Chinese>啟用傷者的尖叫聲</Chinese>
</Key>
</Container>
<Key ID="STR_ACE_Medical_feedback_painEffectType">
<English>Pain Effect Type</English>
<German>Schmerzeffekt-Typ</German>
<Polish>Rodzaj efektu bólu</Polish>
<Russian>Визуальный эффект боли</Russian>
<Italian>Pain Effect Type</Italian>
<Spanish>Tipo de efecto de dolor</Spanish>
<French>Type d'effet de douleur</French>
<Hungarian>Fájdalom-effekt típusa</Hungarian>
<Portuguese>Tipo do efeito de dor</Portuguese>
<Czech>Typ bolesti - efekt</Czech>
<Japanese>痛み効果の種類</Japanese>
<Korean>고통 효과 종류</Korean>
</Key>
<Key ID="STR_ACE_Medical_feedback_painEffectType_whiteFlashing">
<English>White flashing</English>
<Japanese>白く点滅</Japanese>
<Russian>Белые вспышки</Russian>
</Key>
<Key ID="STR_ACE_Medical_feedback_painEffectType_pulsingBlur">
<English>Pulsing blur</English>
<Japanese>ボケの強弱</Japanese>
<Russian>Пульсирующее размытие</Russian>
</Key>
</Package>
</Project>

View File

@ -19,7 +19,7 @@
if !([ACE_player, GVAR(target), ["isNotInside", "isNotSwimming"]] call EFUNC(common,canInteractWith) && {[ACE_player, GVAR(target)] call FUNC(canOpenMenu)}) then {
closeDialog 0;
// Show hint if distance condition failed
if (ACE_player distance GVAR(target) > GVAR(maxDistance)) then {
if ((ACE_player distance GVAR(target) > GVAR(maxDistance)) && {vehicle ACE_player != vehicle GVAR(target)}) then {
[[ELSTRING(medical,DistanceToFar), GVAR(target) call EFUNC(common,getName)], 2] call EFUNC(common,displayTextStructured);
};
};

View File

@ -30,7 +30,7 @@ private _bloodLossOnBodyPart = 0;
if (_bodyPartN == _partIndex) then {
_bloodLossOnBodyPart = _bloodLossOnBodyPart + (_amountOf * _bleeding);
};
} forEach (_target getvariable [QEGVAR(medical,openWounds), []]);
} forEach GET_OPEN_WOUNDS(_target);
private _frBL = 0 max (_bloodLossOnBodyPart / BLOOD_LOSS_RED_THRESHOLD) min 1;
private _colorInt = ceil (_frBL * (BLOOD_LOSS_TOTAL_COLORS - 1)); // ceil because any bleeding more than zero shouldn't be white

View File

@ -18,5 +18,6 @@
if (EGVAR(interact_menu,menuBackground) == 1) then {[QGVAR(id), false] call EFUNC(common,blurScreen)};
if (EGVAR(interact_menu,menuBackground) == 2) then {(uiNamespace getVariable [QEGVAR(interact_menu,menuBackground), displayNull]) closeDisplay 0};
GVAR(pendingReopen) = false;
GVAR(menuPFH) call CBA_fnc_removePerFrameHandler;
GVAR(menuPFH) = -1;

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