diff --git a/addons/chemical/ACE_Medical_Injuries.hpp b/addons/chemical/ACE_Medical_Injuries.hpp index 819c5d5e2..11864e2bb 100644 --- a/addons/chemical/ACE_Medical_Injuries.hpp +++ b/addons/chemical/ACE_Medical_Injuries.hpp @@ -12,6 +12,13 @@ class ACE_Medical_Injuries { pain = 0.6; minDamage = 0; }; + // Beta / local high-dose radiation burn. Like a chemical burn but + // weeps less and hurts more (deep tissue damage, slow to heal). + class KAT_RadiationBurn { + bleeding = 0.003; + pain = 0.7; + minDamage = 0; + }; }; class damageTypes { @@ -22,5 +29,12 @@ class ACE_Medical_Injuries { weighting[] = {{0, 1}}; }; }; + class KAT_radiationBurn { + thresholds[] = {{0, 1}}; + selectionSpecific = 0; + class KAT_RadiationBurn { + weighting[] = {{0, 1}}; + }; + }; }; }; diff --git a/addons/chemical/ACE_Medical_Treatment_Actions.hpp b/addons/chemical/ACE_Medical_Treatment_Actions.hpp index 654ac5c30..50aec3824 100644 --- a/addons/chemical/ACE_Medical_Treatment_Actions.hpp +++ b/addons/chemical/ACE_Medical_Treatment_Actions.hpp @@ -17,7 +17,95 @@ class ACE_Medical_Treatment_Actions { items[] = {"kat_decon_kit"}; treatmentTime = 8; callbackSuccess = QFUNC(clearContamination); - condition = QUOTE((_patient getVariable [ARR_2(QQGVAR(chemicalContamination),'')]) != ''); + condition = QUOTE(((_patient getVariable [ARR_2(QQGVAR(chemicalContamination),'')]) != '') || {(_patient getVariable [ARR_2(QQGVAR(radExternalContam),0)]) > 0}); + icon = QPATHTOF(ui\icon_deconkit.paa); + }; + class KAT_TakeKI: Diagnose { + displayName = CSTRING(TakeKI); + displayNameProgress = CSTRING(TakeKI_Progress); + allowedSelections[] = {"Head"}; + allowSelfTreatment = 1; + items[] = {"kat_potassiumIodide"}; + treatmentTime = 4; + callbackSuccess = QUOTE([ARR_2(_patient,'ki')] call FUNC(treatmentAdvanced_AntiRadLocal)); + condition = "true"; + icon = QPATHTOF(ui\icon_deconkit.paa); + }; + class KAT_TakePrussianBlue: Diagnose { + displayName = CSTRING(TakePrussianBlue); + displayNameProgress = CSTRING(TakePrussianBlue_Progress); + allowedSelections[] = {"Head"}; + allowSelfTreatment = 1; + items[] = {"kat_prussianBlue"}; + treatmentTime = 4; + callbackSuccess = QUOTE([ARR_2(_patient,'prussian')] call FUNC(treatmentAdvanced_AntiRadLocal)); + condition = "true"; + icon = QPATHTOF(ui\icon_deconkit.paa); + }; + class KAT_GiveAntibiotics: Diagnose { + displayName = CSTRING(GiveAntibiotics); + displayNameProgress = CSTRING(GiveAntibiotics_Progress); + allowedSelections[] = {"LeftArm", "RightArm"}; + allowSelfTreatment = 1; + items[] = {"kat_antibiotics"}; + treatmentTime = 5; + callbackSuccess = QUOTE([ARR_2(_patient,'antibiotics')] call FUNC(treatmentAdvanced_AntiRadLocal)); + condition = "true"; + icon = QPATHTOF(ui\icon_deconkit.paa); + }; + class KAT_GiveFilgrastim: Diagnose { + displayName = CSTRING(GiveFilgrastim); + displayNameProgress = CSTRING(GiveFilgrastim_Progress); + allowedSelections[] = {"LeftArm", "RightArm"}; + allowSelfTreatment = 1; + items[] = {"kat_filgrastim"}; + treatmentTime = 5; + callbackSuccess = QUOTE([ARR_2(_patient,'filgrastim')] call FUNC(treatmentAdvanced_AntiRadLocal)); + condition = "true"; + icon = QPATHTOF(ui\icon_deconkit.paa); + }; + class KAT_TakeAntiemetic: Diagnose { + displayName = CSTRING(TakeAntiemetic); + displayNameProgress = CSTRING(TakeAntiemetic_Progress); + allowedSelections[] = {"Head"}; + allowSelfTreatment = 1; + items[] = {"kat_antiemetic"}; + treatmentTime = 4; + callbackSuccess = QUOTE([ARR_2(_patient,'antiemetic')] call FUNC(treatmentAdvanced_AntiRadLocal)); + condition = "true"; + icon = QPATHTOF(ui\icon_deconkit.paa); + }; + class KAT_EstimateDose: Diagnose { + displayName = CSTRING(EstimateDose); + displayNameProgress = CSTRING(EstimateDose_Progress); + allowedSelections[] = {"Head"}; + allowSelfTreatment = 1; + treatmentTime = 5; + callbackSuccess = QUOTE([ARR_2(_medic,_patient)] call FUNC(estimateRadDose)); + condition = "true"; + icon = QPATHTOF(ui\icon_deconkit.paa); + }; + class KAT_RadSurvey: Diagnose { + displayName = CSTRING(RadSurvey); + displayNameProgress = CSTRING(RadSurvey_Progress); + allowedSelections[] = {"Body"}; + allowSelfTreatment = 1; + items[] = {"KAT_Dosimeter"}; + treatmentTime = 3; + callbackSuccess = QUOTE([ARR_2(_medic,_patient)] call FUNC(radSurvey)); + condition = "true"; + icon = QPATHTOF(UI\kat_chemicalDet_icon.paa); + }; + class KAT_GiveStemCells: Diagnose { + displayName = CSTRING(GiveStemCells); + displayNameProgress = CSTRING(GiveStemCells_Progress); + allowedSelections[] = {"LeftArm", "RightArm"}; + allowSelfTreatment = 1; + medicRequired = QGVAR(rad_stemCellsMedLvl); + items[] = {"kat_stemCells"}; + treatmentTime = 20; + callbackSuccess = QUOTE([ARR_2(_patient,'stemcells')] call FUNC(treatmentAdvanced_AntiRadLocal)); + condition = QUOTE(_patient getVariable [ARR_2(QQGVAR(radCritical),false)]); icon = QPATHTOF(ui\icon_deconkit.paa); }; }; diff --git a/addons/chemical/CfgEventHandlers.hpp b/addons/chemical/CfgEventHandlers.hpp index e5090d55b..d6d2ac2cd 100644 --- a/addons/chemical/CfgEventHandlers.hpp +++ b/addons/chemical/CfgEventHandlers.hpp @@ -11,6 +11,11 @@ class Extended_Init_EventHandlers { init = QUOTE([ARR_2((_this select 0),false)] call FUNC(init)); }; }; + class kat_radSource { + class ADDON { + init = QUOTE([_this select 0] call FUNC(initRadSourceObject)); + }; + }; }; class Extended_PostInit_EventHandlers { diff --git a/addons/chemical/CfgSounds.hpp b/addons/chemical/CfgSounds.hpp index b450407cc..a14b80bf6 100644 --- a/addons/chemical/CfgSounds.hpp +++ b/addons/chemical/CfgSounds.hpp @@ -157,4 +157,30 @@ class CfgSounds { }; titles[] = {}; }; + + class GVAR(geiger_base) { + name = QGVAR(geiger_base); + sound[] = {QPATHTOF(audio\baseChime.ogg), 1.5, 1.0, 8}; + titles[] = {}; + }; + class GVAR(geiger_slow) { + name = QGVAR(geiger_slow); + sound[] = {QPATHTOF(audio\slowChime.ogg), 1.5, 1.0, 8}; + titles[] = {}; + }; + class GVAR(geiger_normal) { + name = QGVAR(geiger_normal); + sound[] = {QPATHTOF(audio\normalChime.ogg), 1.5, 1.0, 8}; + titles[] = {}; + }; + class GVAR(geiger_fast) { + name = QGVAR(geiger_fast); + sound[] = {QPATHTOF(audio\fastChime.ogg), 1.5, 1.0, 8}; + titles[] = {}; + }; + class GVAR(geiger_rapid) { + name = QGVAR(geiger_rapid); + sound[] = {QPATHTOF(audio\rapidChime.ogg), 1.5, 1.0, 8}; + titles[] = {}; + }; }; diff --git a/addons/chemical/CfgVehicles.hpp b/addons/chemical/CfgVehicles.hpp index c1078f471..665067de5 100644 --- a/addons/chemical/CfgVehicles.hpp +++ b/addons/chemical/CfgVehicles.hpp @@ -47,13 +47,22 @@ class CfgVehicles { class KAT_UseDecon { displayName = CSTRING(UseDecon); - condition = QUOTE('kat_decon_kit' in (items _player) && {(_player getVariable [ARR_2(QQGVAR(chemicalContamination),'')]) != ''}); + condition = QUOTE('kat_decon_kit' in (items _player) && {((_player getVariable [ARR_2(QQGVAR(chemicalContamination),'')]) != '') || {(_player getVariable [ARR_2(QQGVAR(radExternalContam),0)]) > 0}}); exceptions[] = {"isNotSwimming", "isNotInside"}; statement = QUOTE([ARR_2(_player,_player)] call FUNC(decontaminate)); showDisabled = 0; icon = QPATHTOF(ui\icon_deconkit.paa); }; + class KAT_DropRadSource { + displayName = CSTRING(DropRadSource); + condition = QUOTE(!isNull (_player getVariable [ARR_2(QQGVAR(carriedRadSource),objNull)])); + exceptions[] = {"isNotSwimming"}; + statement = QUOTE([_player] call FUNC(dropRadSource)); + showDisabled = 0; + icon = QPATHTOF(ui\icon_deconkit.paa); + }; + class KAT_ChemicalDetector { displayName = CSTRING(ChemicalDetector_Menu); icon = QPATHTOF(ui\kat_chemicalDet_icon.paa); @@ -84,6 +93,45 @@ class CfgVehicles { icon = QPATHTOF(ui\kat_chemicalDet_icon.paa); }; }; + + class KAT_Dosimeter { + displayName = CSTRING(Dosimeter_Menu); + icon = QPATHTOF(ui\kat_chemicalDet_icon.paa); + exceptions[] = {"isNotSwimming"}; + + class KAT_Dosimeter_Enable { + displayName = CSTRING(EnableDosimeter); + condition = QUOTE(([_player] call FUNC(hasDosimeter)) && !(_player getVariable [ARR_2(QQGVAR(dosimeterEnabled),false)])); + exceptions[] = {"isNotSwimming"}; + statement = QUOTE([_player] call FUNC(enableDosimeter)); + showDisabled = 0; + icon = QPATHTOF(ui\kat_chemicalDet_icon.paa); + }; + class KAT_Dosimeter_Disable { + displayName = CSTRING(DisableDosimeter); + condition = QUOTE(([_player] call FUNC(hasDosimeter)) && (_player getVariable [ARR_2(QQGVAR(dosimeterEnabled),false)])); + exceptions[] = {"isNotSwimming"}; + statement = QUOTE(_player setVariable [ARR_3(QQGVAR(dosimeterEnabled),false,true)]); + showDisabled = 0; + icon = QPATHTOF(ui\kat_chemicalDet_icon.paa); + }; + class KAT_Dosimeter_SoundOn { + displayName = CSTRING(EnableDosimeterSound); + condition = QUOTE(!(_player getVariable [ARR_2(QQGVAR(dosimeterSound),false)]) && ([_player] call FUNC(hasDosimeter))); + exceptions[] = {"isNotSwimming"}; + statement = QUOTE(_player setVariable [ARR_3(QQGVAR(dosimeterSound),true,true)]); + showDisabled = 0; + icon = QPATHTOF(ui\kat_chemicalDet_icon.paa); + }; + class KAT_Dosimeter_SoundOff { + displayName = CSTRING(DisableDosimeterSound); + condition = QUOTE((_player getVariable [ARR_2(QQGVAR(dosimeterSound),false)]) && ([_player] call FUNC(hasDosimeter))); + exceptions[] = {"isNotSwimming"}; + statement = QUOTE(_player setVariable [ARR_3(QQGVAR(dosimeterSound),false,true)]); + showDisabled = 0; + icon = QPATHTOF(ui\kat_chemicalDet_icon.paa); + }; + }; }; }; }; @@ -154,6 +202,127 @@ class CfgVehicles { }; }; + class kat_potassiumIodide_Item: Item_Base_F { + scope = 2; + scopeCurator = 2; + displayName = CSTRING(potassiumIodideItem); + author = "DiGii"; + vehicleClass = "Items"; + editorCategory = "EdCat_Equipment"; + editorSubcategory = "EdSubcat_InventoryItems"; + class TransportItems { + class _xx_kat_potassiumIodide { + name = "kat_potassiumIodide"; + count = 1; + }; + }; + }; + + class kat_prussianBlue_Item: Item_Base_F { + scope = 2; + scopeCurator = 2; + displayName = CSTRING(prussianBlueItem); + author = "DiGii"; + vehicleClass = "Items"; + editorCategory = "EdCat_Equipment"; + editorSubcategory = "EdSubcat_InventoryItems"; + class TransportItems { + class _xx_kat_prussianBlue { + name = "kat_prussianBlue"; + count = 1; + }; + }; + }; + + class kat_antibiotics_Item: Item_Base_F { + scope = 2; + scopeCurator = 2; + displayName = CSTRING(antibioticsItem); + author = "DiGii"; + vehicleClass = "Items"; + editorCategory = "EdCat_Equipment"; + editorSubcategory = "EdSubcat_InventoryItems"; + class TransportItems { + class _xx_kat_antibiotics { + name = "kat_antibiotics"; + count = 1; + }; + }; + }; + + class kat_filgrastim_Item: Item_Base_F { + scope = 2; + scopeCurator = 2; + displayName = CSTRING(filgrastimItem); + author = "DiGii"; + vehicleClass = "Items"; + editorCategory = "EdCat_Equipment"; + editorSubcategory = "EdSubcat_InventoryItems"; + class TransportItems { + class _xx_kat_filgrastim { + name = "kat_filgrastim"; + count = 1; + }; + }; + }; + + class kat_antiemetic_Item: Item_Base_F { + scope = 2; + scopeCurator = 2; + displayName = CSTRING(antiemeticItem); + author = "DiGii"; + vehicleClass = "Items"; + editorCategory = "EdCat_Equipment"; + editorSubcategory = "EdSubcat_InventoryItems"; + class TransportItems { + class _xx_kat_antiemetic { + name = "kat_antiemetic"; + count = 1; + }; + }; + }; + + class kat_stemCells_Item: Item_Base_F { + scope = 2; + scopeCurator = 2; + displayName = CSTRING(stemCellsItem); + author = "DiGii"; + vehicleClass = "Items"; + editorCategory = "EdCat_Equipment"; + editorSubcategory = "EdSubcat_InventoryItems"; + class TransportItems { + class _xx_kat_stemCells { + name = "kat_stemCells"; + count = 1; + }; + }; + }; + + class Land_CanisterFuel_F; + class kat_radSource: Land_CanisterFuel_F { + scope = 2; + scopeCurator = 2; + displayName = CSTRING(radSourceObject); + author = "DiGii"; + editorCategory = "EdCat_Equipment"; + editorSubcategory = "EdSubcat_InventoryItems"; + class ACE_Actions { + class ACE_MainActions { + displayName = CSTRING(radSourceObject); + selection = ""; + distance = 4; + condition = "true"; + class KAT_PickupRadSource { + displayName = CSTRING(PickupRadSource); + distance = 4; + condition = QUOTE(isNull (_player getVariable [ARR_2(QQGVAR(carriedRadSource),objNull)])); + statement = QUOTE([ARR_2(_player,_target)] call FUNC(pickupRadSource)); + icon = QPATHTOF(ui\icon_deconkit.paa); + }; + }; + }; + }; + class Logic; class Module_F: Logic { @@ -250,6 +419,106 @@ class CfgVehicles { isGlobal = 0; }; + class kat_module_radiation: Module_F + { + scope = 2; + side = 7; + displayName = CSTRING(RadModule_Displayname); + category = QEGVAR(zeus,KAM); + function = QFUNC(radmodule); + isTriggerActivated = 0; + functionPriority = 1; + isGlobal = 0; + + class Arguments: AttributesBase + { + class Radius + { + displayName = CSTRING(UI_max_range); + tooltip = CSTRING(RadModule_max_radius_dcs); + typeName = "NUMBER"; + defaultValue = 20; + }; + class Preset + { + displayName = CSTRING(RadModule_preset); + tooltip = CSTRING(RadModule_preset_dcs); + typeName = "NUMBER"; + class values + { + class custom { name = CSTRING(RadPreset_custom); value = 0; default = 1; }; + class cobalt { name = CSTRING(RadPreset_Cobalt60); value = 1; }; + class reactor { name = CSTRING(RadPreset_Reactor); value = 2; }; + class fallout { name = CSTRING(RadPreset_Fallout); value = 3; }; + class alpha { name = CSTRING(RadPreset_AlphaEmitter); value = 4; }; + class dirty { name = CSTRING(RadPreset_DirtyBomb); value = 5; }; + }; + }; + class Alpha + { + displayName = CSTRING(RadModule_alpha); + tooltip = CSTRING(RadModule_strength_dcs); + typeName = "NUMBER"; + defaultValue = 0; + }; + class Beta + { + displayName = CSTRING(RadModule_beta); + tooltip = CSTRING(RadModule_strength_dcs); + typeName = "NUMBER"; + defaultValue = 0; + }; + class Gamma + { + displayName = CSTRING(RadModule_gamma); + tooltip = CSTRING(RadModule_strength_dcs); + typeName = "NUMBER"; + defaultValue = 50; + }; + class Neutron + { + displayName = CSTRING(RadModule_neutron); + tooltip = CSTRING(RadModule_strength_dcs); + typeName = "NUMBER"; + defaultValue = 0; + }; + class PointSource + { + displayName = CSTRING(RadModule_pointSource); + tooltip = CSTRING(RadModule_pointSource_dcs); + typeName = "BOOL"; + defaultValue = 0; + }; + }; + + class ModuleDescription: ModuleDescription { + description = CSTRING(RadModule_description); + sync[] = {"LocationArea_F"}; + + class LocationArea_F { + position = 0; + optional = 1; + duplicate = 1; + synced[] = {"Anything"}; + }; + }; + }; + + class kat_module_zeus_radiation: Module_F + { + scope = 1; + scopeCurator = 2; + side = 7; + curatorCanAttach = 1; + displayName = CSTRING(RadModule_Displayname); + category = QEGVAR(zeus,KAM); + function = QACEFUNC(common,dummy); + curatorInfoType = QGVAR(kat_RscRadModul); + isTriggerActivated = 0; + functionPriority = 1; + isGlobal = 0; + }; + class LandVehicle; class StaticWeapon: LandVehicle { diff --git a/addons/chemical/CfgWeapons.hpp b/addons/chemical/CfgWeapons.hpp index 8d8dde89b..ee3b5b579 100644 --- a/addons/chemical/CfgWeapons.hpp +++ b/addons/chemical/CfgWeapons.hpp @@ -54,16 +54,103 @@ class CfgWeapons { }; }; + class kat_potassiumIodide : ACE_ItemCore { + scope = 2; + author = "DiGii"; + displayName = CSTRING(potassiumIodideItem); + model = "\A3\weapons_F\ammo\mag_univ.p3d"; + picture = QPATHTOF(ui\kat_potassiumIodide.paa); + descriptionShort = CSTRING(potassiumIodideItem_desc); + descriptionUse = CSTRING(potassiumIodideItem_desc); + class ItemInfo: CBA_MiscItem_ItemInfo { + mass = 1; + }; + }; + + class kat_prussianBlue : ACE_ItemCore { + scope = 2; + author = "DiGii"; + displayName = CSTRING(prussianBlueItem); + model = "\A3\weapons_F\ammo\mag_univ.p3d"; + picture = QPATHTOF(ui\kat_prussianBlue.paa); + descriptionShort = CSTRING(prussianBlueItem_desc); + descriptionUse = CSTRING(prussianBlueItem_desc); + class ItemInfo: CBA_MiscItem_ItemInfo { + mass = 1; + }; + }; + + class kat_antibiotics : ACE_ItemCore { + scope = 2; + author = "DiGii"; + displayName = CSTRING(antibioticsItem); + model = "\A3\weapons_F\ammo\mag_univ.p3d"; + picture = QPATHTOF(ui\icon_deconkit.paa); + descriptionShort = CSTRING(antibioticsItem_desc); + descriptionUse = CSTRING(antibioticsItem_desc); + class ItemInfo: CBA_MiscItem_ItemInfo { + mass = 1; + }; + }; + + class kat_filgrastim : ACE_ItemCore { + scope = 2; + author = "DiGii"; + displayName = CSTRING(filgrastimItem); + model = "\A3\weapons_F\ammo\mag_univ.p3d"; + picture = QPATHTOF(ui\icon_deconkit.paa); + descriptionShort = CSTRING(filgrastimItem_desc); + descriptionUse = CSTRING(filgrastimItem_desc); + class ItemInfo: CBA_MiscItem_ItemInfo { + mass = 1; + }; + }; + + class kat_antiemetic : ACE_ItemCore { + scope = 2; + author = "DiGii"; + displayName = CSTRING(antiemeticItem); + model = "\A3\weapons_F\ammo\mag_univ.p3d"; + picture = QPATHTOF(ui\icon_deconkit.paa); + descriptionShort = CSTRING(antiemeticItem_desc); + descriptionUse = CSTRING(antiemeticItem_desc); + class ItemInfo: CBA_MiscItem_ItemInfo { + mass = 1; + }; + }; + + class kat_stemCells : ACE_ItemCore { + scope = 2; + author = "DiGii"; + displayName = CSTRING(stemCellsItem); + model = "\A3\weapons_F\ammo\mag_univ.p3d"; + picture = QPATHTOF(ui\icon_deconkit.paa); + descriptionShort = CSTRING(stemCellsItem_desc); + descriptionUse = CSTRING(stemCellsItem_desc); + class ItemInfo: CBA_MiscItem_ItemInfo { + mass = 2; + }; + }; + class ItemWatch; class KAT_ChemicalDetector: ItemWatch { ACE_hideItemType = "Watch"; - author = "Mazinski"; + author = "Mazinski"; descriptionShort = CSTRING(ChemicalDetectorDescription); displayName = CSTRING(ChemicalDetectorDisplayName); picture = QPATHTOF(UI\kat_chemicalDet_icon.paa); model = "\a3\Weapons_F_Enoch\Items\ChemicalDetector_01_F.p3d"; }; + class KAT_Dosimeter: ItemWatch { + ACE_hideItemType = "Watch"; + author = "DiGii"; + descriptionShort = CSTRING(DosimeterDescription); + displayName = CSTRING(DosimeterDisplayName); + picture = QPATHTOF(UI\kat_chemicalDet_icon.paa); + model = "\a3\Weapons_F_Enoch\Items\ChemicalDetector_01_F.p3d"; + }; + class CannonCore; class mortar_82mm: CannonCore { // AI-driven mortars get only choking agents (chlorine, phosgene, CS). diff --git a/addons/chemical/RscTitles.hpp b/addons/chemical/RscTitles.hpp index 2d8197edc..0217b621c 100644 --- a/addons/chemical/RscTitles.hpp +++ b/addons/chemical/RscTitles.hpp @@ -238,4 +238,66 @@ class RscTitles }; }; }; + + class KAT_Dosimeter + { + idd = 18836; + enableSimulation = 1; + movingEnable = 0; + fadeIn = 0; + fadeOut = 1; + duration = 10e10; + onLoad = "uiNamespace setVariable ['KAT_Dosimeter', _this select 0];"; + class controls + { + // "DOSIMETER" header, bottom-right corner stack. + class KatDosiHeader: RscText + { + idc = 18813; + style = ST_RIGHT; + shadow = 1; + font = "PuristaBold"; + text = "$STR_KAT_Chemical_Dosimeter_Header"; + x = QUOTE(SAFEZONE_X_RIGHTEDGE - FRAME_W(22)); + y = QUOTE(SAFEZONE_Y_LOWEDGE - FRAME_H(11)); + w = QUOTE(FRAME_W(20)); + h = QUOTE(FRAME_H(3)); + colorBackground[] = {0,0,0,0}; + colorText[] = {0.55,0.85,0.35,0.9}; + sizeEx = QUOTE(FRAME_H(2)); + }; + // Current dose-rate (Gy/h). + class KatDosiRate: RscText + { + idc = 18814; + style = ST_RIGHT; + shadow = 1; + font = "PuristaMedium"; + text = "0.000 Gy/h"; + x = QUOTE(SAFEZONE_X_RIGHTEDGE - FRAME_W(22)); + y = QUOTE(SAFEZONE_Y_LOWEDGE - FRAME_H(8)); + w = QUOTE(FRAME_W(20)); + h = QUOTE(FRAME_H(3)); + colorBackground[] = {0,0,0,0}; + colorText[] = {0.3,0.3,0.3,0.9}; + sizeEx = QUOTE(FRAME_H(2.2)); + }; + // Accumulated whole-body dose (Gy). + class KatDosiDose: RscText + { + idc = 18815; + style = ST_RIGHT; + shadow = 1; + font = "PuristaMedium"; + text = "0.000 Gy"; + x = QUOTE(SAFEZONE_X_RIGHTEDGE - FRAME_W(22)); + y = QUOTE(SAFEZONE_Y_LOWEDGE - FRAME_H(5)); + w = QUOTE(FRAME_W(20)); + h = QUOTE(FRAME_H(3)); + colorBackground[] = {0,0,0,0}; + colorText[] = {0.3,0.3,0.3,0.9}; + sizeEx = QUOTE(FRAME_H(2.2)); + }; + }; + }; }; diff --git a/addons/chemical/XEH_PREP.hpp b/addons/chemical/XEH_PREP.hpp index 099930f0c..9ac1b9f77 100644 --- a/addons/chemical/XEH_PREP.hpp +++ b/addons/chemical/XEH_PREP.hpp @@ -2,6 +2,7 @@ PREP(addToExposureWatcher); PREP(applyDelayedEffect); PREP(applyMustardDamage); PREP(AttributeRadius); +PREP(AttributeRadModule); PREP(breathing); PREP(canPutGasMask); PREP(canPutOnGasMask); @@ -16,6 +17,7 @@ PREP(createSealAction); PREP(csGrenade); PREP(decontaminate); PREP(displayGasMaskDur); +PREP(dropRadSource); PREP(effect_chlorine); PREP(effect_cs); PREP(effect_mustard); @@ -24,6 +26,9 @@ PREP(effect_sarin); PREP(effect_vx); PREP(emitSmellHint); PREP(enableChemDetector); +PREP(enableDosimeter); +PREP(estimateRadDose); +PREP(evaluateRadDose); PREP(exposureWatcherPFH); PREP(fullHealLocal); PREP(gasManagerPFH); @@ -38,22 +43,43 @@ PREP(handleGasMaskDur); PREP(handleRespawn); PREP(hasCBRNProtection); PREP(hasDetector); +PREP(hasDosimeter); PREP(hasGasmask); PREP(hasGasMaskON); PREP(hideChemDetector); +PREP(hideDosimeter); PREP(init); PREP(initGasRegistry); PREP(initModule); +PREP(initRadProfiles); +PREP(initRadSourceObject); +PREP(irradiate); +PREP(pickupRadSource); PREP(poison); PREP(putOnGasMask); +PREP(radContaminationTickPFH); +PREP(radInternalTickPFH); +PREP(radManagerPFH); +PREP(radmodule); +PREP(radPhysiologyPFH); +PREP(radProtection); +PREP(radSurvey); +PREP(registerContaminatedSource); PREP(scheduleAirPoisoningOnset); PREP(scheduleNerveSymptomChain); +PREP(scheduleRadSicknessChain); PREP(showChemDetector); +PREP(showDosimeter); PREP(spawnSmoke); PREP(startContaminationTick); +PREP(startRadContaminationTick); +PREP(startRadInternalTick); +PREP(startRadPhysiologyTick); PREP(takeOffGasMask); PREP(throwGrenade); +PREP(treatmentAdvanced_AntiRadLocal); PREP(treatmentAdvanced_AtnaaLocal); PREP(treatmentAdvanced_AtropineLocal); PREP(ui_gasModule); +PREP(ui_radModule); PREP(useM8Paper); diff --git a/addons/chemical/XEH_postInit.sqf b/addons/chemical/XEH_postInit.sqf index b363f365c..f87efa428 100644 --- a/addons/chemical/XEH_postInit.sqf +++ b/addons/chemical/XEH_postInit.sqf @@ -5,6 +5,23 @@ //Events ["ace_glassesChanged", LINKFUNC(breathing)] call CBA_fnc_addEventHandler; [QGVAR(poison), LINKFUNC(poison)] call CBA_fnc_addEventHandler; +[QGVAR(irradiate), LINKFUNC(irradiate)] call CBA_fnc_addEventHandler; + +[QGVAR(attachRadSource), { + params ["_source", "_player"]; + if (isNull _source || {isNull _player}) exitWith {}; + detach _source; + _source attachTo [_player, [0, 0.1, 0.1]]; +}] call CBA_fnc_addEventHandler; + +[QGVAR(detachRadSource), { + params ["_source", "_player"]; + if (isNull _source) exitWith {}; + detach _source; + if (isServer && {!isNull _player}) then { + _source setPosATL (_player modelToWorld [0, 1, 0]); + }; +}] call CBA_fnc_addEventHandler; [QGVAR(handleGasMaskDur), LINKFUNC(handleGasMaskDur)] call CBA_fnc_addEventHandler; [QGVAR(addSealAction), LINKFUNC(createSealAction)] call CBA_fnc_addEventHandler; @@ -52,6 +69,18 @@ missionNamespace setVariable [QGVAR(availGasmaskList), _array, true]; true }, { false }, [24, [false, false, false]], false] call CBA_fnc_addKeybind; +[CBA_SETTINGS_CAT, QGVAR(showDosimeter), LLSTRING(ShowDosimeter), { + if (!([ACE_player, objNull, ["isNotEscorting", "isNotInside"]] call ACEFUNC(common,canInteractWith)) || {!('KAT_Dosimeter' in assignedItems ACE_player)}) exitWith { false }; + + if !(GETMVAR(GVAR(DosimeterActive),false)) then { + [ACE_player] call FUNC(showDosimeter); + } else { + call FUNC(hideDosimeter); + }; + + true +}, { false }, [25, [false, false, false]], false] call CBA_fnc_addKeybind; + // Client-side particle tracking (all machines) GVAR(clientParticles) = createHashMap; @@ -150,6 +179,75 @@ if (!isServer) exitWith {}; GVAR(gasSources) = createHashMap; GVAR(exposureWatcherUnits) = createHashMap; +GVAR(radSources) = createHashMap; +GVAR(radExposedUnits) = []; + +[QGVAR(addRadSource), { + params [ + ["_source", objNull, [objNull, []]], + ["_radius", 0, [0]], + ["_strengths", [], [[]]], + ["_falloff", "linear", [""]], + ["_key", ""], + ["_condition", {true}, [{}]], + ["_conditionArgs", []] + ]; + + private _isObject = _source isEqualType objNull; + + if !(_isObject || {_source isEqualTypeParams [0, 0, 0]}) exitWith {}; + if (_isObject && {isNull _source}) exitWith {}; + if (_radius == 0) exitWith {}; + if (count _strengths != 4) exitWith {}; + if ((_strengths findIf {_x > 0}) == -1) exitWith {}; + if (_key isEqualTo "") exitWith {}; + + private _hashedKey = hashValue _key; + if (isNil "_hashedKey") exitWith { + ERROR_2("Unsupported key type used: %1 - %2",_key,typeName _key); + }; + + private _sourcePos = if (_isObject) then { + getPosATL _source + } else { + ASLToATL _source + }; + + private _radLogic = createVehicle [QGVAR(logic), _sourcePos, [], 0, "CAN_COLLIDE"]; + + if (_isObject) then { + _radLogic attachTo [_source]; + } else { + _radLogic setPosATL [_sourcePos select 0, _sourcePos select 1, 0]; + }; + + if (_hashedKey in GVAR(radSources)) then { + [QGVAR(removeRadSource), _key] call CBA_fnc_localEvent; + }; + + GVAR(radSources) set [_hashedKey, [_radLogic, _radius, _strengths, _falloff, _condition, _conditionArgs]]; +}] call CBA_fnc_addEventHandler; + +[QGVAR(removeRadSource), { + params ["_key"]; + private _hashedKey = hashValue _key; + + if (isNil "_hashedKey") exitWith { + ERROR_2("Unsupported key type used: %1 - %2",_key,typeName _key); + }; + + (GVAR(radSources) deleteAt _hashedKey) params [["_radLogic", objNull]]; + + detach _radLogic; + deleteVehicle _radLogic; +}] call CBA_fnc_addEventHandler; + +[QGVAR(serverRegisterContamSource), LINKFUNC(registerContaminatedSource)] call CBA_fnc_addEventHandler; + +[QGVAR(serverRemoveContamSource), { + params ["_unit"]; + [QGVAR(removeRadSource), _unit] call CBA_fnc_localEvent; +}] call CBA_fnc_addEventHandler; // Server-side: register a unit with the exposure watcher PFH (idempotent). // Triggered by FUNC(addToExposureWatcher) on the unit's owner. @@ -257,4 +355,5 @@ GVAR(exposureWatcherUnits) = createHashMap; }] call CBA_fnc_addEventHandler; [LINKFUNC(gasManagerPFH), GAS_MANAGER_PFH_DELAY, []] call CBA_fnc_addPerFrameHandler; +[LINKFUNC(radManagerPFH), RAD_MANAGER_PFH_DELAY, []] call CBA_fnc_addPerFrameHandler; diff --git a/addons/chemical/XEH_preInit.sqf b/addons/chemical/XEH_preInit.sqf index 22a34bd93..a6eea849c 100644 --- a/addons/chemical/XEH_preInit.sqf +++ b/addons/chemical/XEH_preInit.sqf @@ -10,5 +10,6 @@ PREP_RECOMPILE_END; #include "initSettings.inc.sqf" call FUNC(initGasRegistry); +call FUNC(initRadProfiles); ADDON = true; diff --git a/addons/chemical/config.cpp b/addons/chemical/config.cpp index dba5e8394..d5421bd8a 100644 --- a/addons/chemical/config.cpp +++ b/addons/chemical/config.cpp @@ -8,10 +8,19 @@ class CfgPatches { "kat_sealant_Item", "kat_module_gas", "kat_module_zeus_gas", + "kat_module_radiation", + "kat_module_zeus_radiation", "KAT_Gas_TripWireMine", "kat_gasmaskFilter_Item", "kat_m8paper_Item", - "kat_decon_kit_Item" + "kat_decon_kit_Item", + "kat_potassiumIodide_Item", + "kat_prussianBlue_Item", + "kat_antibiotics_Item", + "kat_filgrastim_Item", + "kat_antiemetic_Item", + "kat_stemCells_Item", + "kat_radSource" }; weapons[] = { "kat_sealant", @@ -19,8 +28,15 @@ class CfgPatches { "KAT_CAS_M43_Bomb", "KAT_CAS_R_80mm_GAS_POD", "KAT_ChemicalDetector", + "KAT_Dosimeter", "kat_m8paper", - "kat_decon_kit" + "kat_decon_kit", + "kat_potassiumIodide", + "kat_prussianBlue", + "kat_antibiotics", + "kat_filgrastim", + "kat_antiemetic", + "kat_stemCells" }; ammo[] = { "KAT_Gas_TripWireMine_Ammo", diff --git a/addons/chemical/functions/fnc_AttributeRadModule.sqf b/addons/chemical/functions/fnc_AttributeRadModule.sqf new file mode 100644 index 000000000..c1cc9f7b0 --- /dev/null +++ b/addons/chemical/functions/fnc_AttributeRadModule.sqf @@ -0,0 +1,76 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Wires the radiation Zeus module attribute inputs (radius, preset, per-type + * strengths, point source). Selecting a preset fills the four strength edits. + * Writes ui_radius / ui_radStrengths / ui_radPointSource onto the display for + * fnc_ui_radModule to read on confirm. + * + * Arguments: + * 0: Control + * + * Return Value: + * None + * + * Example: + * [_control] call kat_chemical_fnc_AttributeRadModule; + * + * Public: No + */ + +params ["_control"]; + +private _display = ctrlParent _control; +_control ctrlRemoveAllEventHandlers "SetFocus"; + +private _presetCombo = _display displayCtrl 1624; + +(_display displayCtrl 1621) ctrlSetText "20"; +(_display displayCtrl 1625) ctrlSetText "0"; +(_display displayCtrl 1626) ctrlSetText "0"; +(_display displayCtrl 1627) ctrlSetText "50"; +(_display displayCtrl 1628) ctrlSetText "0"; + +private _presetNames = ["custom", "Cobalt60", "Reactor", "Fallout", "AlphaEmitter", "DirtyBomb"]; +private _presetLabels = [LLSTRING(RadPreset_custom), LLSTRING(RadPreset_Cobalt60), LLSTRING(RadPreset_Reactor), LLSTRING(RadPreset_Fallout), LLSTRING(RadPreset_AlphaEmitter), LLSTRING(RadPreset_DirtyBomb)]; +lbClear _presetCombo; +{ _presetCombo lbAdd _x } forEach _presetLabels; +_presetCombo lbSetCurSel 0; + +_display setVariable [QGVAR(ui_presetNames), _presetNames]; +_display setVariable [QGVAR(ui_radius), 20]; +_display setVariable [QGVAR(ui_radStrengths), [0, 0, 50, 0]]; +_display setVariable [QGVAR(ui_radPointSource), false]; + +private _fnc_onKeyUp = { + params ["_display"]; + _display setVariable [QGVAR(ui_radius), parseNumber (ctrlText (_display displayCtrl 1621))]; + _display setVariable [QGVAR(ui_radStrengths), [ + parseNumber (ctrlText (_display displayCtrl 1625)), + parseNumber (ctrlText (_display displayCtrl 1626)), + parseNumber (ctrlText (_display displayCtrl 1627)), + parseNumber (ctrlText (_display displayCtrl 1628)) + ]]; +}; + +private _fnc_onPreset = { + params ["_combo"]; + private _display = ctrlParent _combo; + private _name = (_display getVariable [QGVAR(ui_presetNames), ["custom"]]) param [lbCurSel _combo, "custom"]; + if (_name isEqualTo "custom") exitWith {}; + private _s = +(GVAR(radPresets) getOrDefault [_name, [0, 0, 0, 0]]); + (_display displayCtrl 1625) ctrlSetText str (_s select 0); + (_display displayCtrl 1626) ctrlSetText str (_s select 1); + (_display displayCtrl 1627) ctrlSetText str (_s select 2); + (_display displayCtrl 1628) ctrlSetText str (_s select 3); + _display setVariable [QGVAR(ui_radStrengths), _s]; +}; + +private _fnc_onCheck = { + params ["_check"]; + (ctrlParent _check) setVariable [QGVAR(ui_radPointSource), cbChecked _check]; +}; + +_display displayAddEventHandler ["KeyUp", _fnc_onKeyUp]; +_presetCombo ctrlAddEventHandler ["LBSelChanged", _fnc_onPreset]; +(_display displayCtrl 1623) ctrlAddEventHandler ["CheckedChanged", _fnc_onCheck]; diff --git a/addons/chemical/functions/fnc_applyDelayedEffect.sqf b/addons/chemical/functions/fnc_applyDelayedEffect.sqf index 90c9fb103..1c0d302ad 100644 --- a/addons/chemical/functions/fnc_applyDelayedEffect.sqf +++ b/addons/chemical/functions/fnc_applyDelayedEffect.sqf @@ -59,4 +59,58 @@ switch (_effect) do { case "cardiac": { [QACEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent; }; + + case "radProdromal": { + if ((_unit getVariable [QGVAR(radTimeToVomit), -1]) < 0) then { + _unit setVariable [QGVAR(radTimeToVomit), CBA_missionTime, true]; + }; + + private _sounds = [ + QPATHTOEF_SOUND(airway,sounds\puking1.wav), + QPATHTOEF_SOUND(airway,sounds\puking2.wav), + QPATHTOEF_SOUND(airway,sounds\puking1.wav) + ]; + if (CBA_missionTime >= (_unit getVariable [QGVAR(radAntiemeticWindow), 0])) then { + playSound3D [selectRandom _sounds, _unit, false, getPosASL _unit, 8, 1, 15]; + }; + + private _pain = _unit getVariable [VAR_PAIN, 0]; + _unit setVariable [VAR_PAIN, (_pain + 0.1) min 1, true]; + + if (GVAR(rad_showSickness) && {_unit == ACE_player}) then { + [LLSTRING(radHint_nausea), 1.5, _unit] call ACEFUNC(common,displayTextStructured); + }; + }; + case "radHema": { + private _pain = _unit getVariable [VAR_PAIN, 0]; + _unit setVariable [VAR_PAIN, (_pain + 0.15) min 1, true]; + + if (GVAR(rad_showSickness) && {_unit == ACE_player}) then { + [LLSTRING(radHint_weak), 1.5, _unit] call ACEFUNC(common,displayTextStructured); + }; + }; + case "radGI": { + private _sounds = [ + QPATHTOEF_SOUND(airway,sounds\puking1.wav), + QPATHTOEF_SOUND(airway,sounds\puking2.wav) + ]; + if (CBA_missionTime >= (_unit getVariable [QGVAR(radAntiemeticWindow), 0])) then { + playSound3D [selectRandom _sounds, _unit, false, getPosASL _unit, 8, 1, 15]; + }; + + private _pain = _unit getVariable [VAR_PAIN, 0]; + _unit setVariable [VAR_PAIN, (_pain + 0.25) min 1, true]; + + if (GVAR(rad_showSickness) && {_unit == ACE_player}) then { + [LLSTRING(radHint_gi), 1.5, _unit] call ACEFUNC(common,displayTextStructured); + }; + }; + case "radCNS": { + [_unit, true] call ACEFUNC(medical,setUnconscious); + }; + case "radCardiac": { + if (!GVAR(rad_lethalCurable)) then { + [QACEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent; + }; + }; }; diff --git a/addons/chemical/functions/fnc_clearContamination.sqf b/addons/chemical/functions/fnc_clearContamination.sqf index b7fdbf7aa..8f89b66b8 100644 --- a/addons/chemical/functions/fnc_clearContamination.sqf +++ b/addons/chemical/functions/fnc_clearContamination.sqf @@ -23,3 +23,6 @@ _patient setVariable [QGVAR(chemicalContamination), "", true]; _patient setVariable [QGVAR(mustardDeadline_eye), 0, true]; _patient setVariable [QGVAR(mustardDeadline_burn), 0, true]; _patient setVariable [QGVAR(mustardBurnActive), false, true]; + +_patient setVariable [QGVAR(radExternalContam), 0, true]; +[QGVAR(serverRemoveContamSource), [_patient]] call CBA_fnc_serverEvent; diff --git a/addons/chemical/functions/fnc_decontaminate.sqf b/addons/chemical/functions/fnc_decontaminate.sqf index 439a4a5f8..d8f0d6baa 100644 --- a/addons/chemical/functions/fnc_decontaminate.sqf +++ b/addons/chemical/functions/fnc_decontaminate.sqf @@ -47,7 +47,7 @@ private _duration = missionNamespace getVariable [QGVAR(deconActionTime), 8]; params ["_args"]; _args params ["_player", "_target"]; ([_player, _player, ["kat_decon_kit"]] call ACEFUNC(medical_treatment,hasItem)) && - {(_target getVariable [QGVAR(chemicalContamination), ""]) != ""} + {((_target getVariable [QGVAR(chemicalContamination), ""]) != "") || {(_target getVariable [QGVAR(radExternalContam), 0]) > 0}} }, ["isNotInside"] ] call ACEFUNC(common,progressBar); diff --git a/addons/chemical/functions/fnc_dropRadSource.sqf b/addons/chemical/functions/fnc_dropRadSource.sqf new file mode 100644 index 000000000..7695eb90a --- /dev/null +++ b/addons/chemical/functions/fnc_dropRadSource.sqf @@ -0,0 +1,21 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Drops the radioactive source the player is carrying back onto the ground. + * + * Arguments: + * 0: Player + * + * Return Value: + * None + * + * Public: No + */ + +params ["_player"]; + +private _source = _player getVariable [QGVAR(carriedRadSource), objNull]; +if (isNull _source) exitWith {}; + +_player setVariable [QGVAR(carriedRadSource), objNull, true]; +[QGVAR(detachRadSource), [_source, _player]] call CBA_fnc_globalEvent; diff --git a/addons/chemical/functions/fnc_enableDosimeter.sqf b/addons/chemical/functions/fnc_enableDosimeter.sqf new file mode 100644 index 000000000..c9d5c2189 --- /dev/null +++ b/addons/chemical/functions/fnc_enableDosimeter.sqf @@ -0,0 +1,51 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Starts the dosimeter audio loop. While the dosimeter sound is enabled it + * emits geiger clicks whose tier scales with the current dose-rate, and only + * while the unit is actually being irradiated. Single-instance; self-terminates + * when the dosimeter is disabled, the unit dies, or the item is removed. + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Example: + * [player] call kat_chemical_fnc_enableDosimeter + * + * Public: No + */ + +params ["_unit"]; + +_unit setVariable [QGVAR(dosimeterEnabled), true, true]; + +if (_unit getVariable [QGVAR(dosimeterAudioActive), false]) exitWith {}; +_unit setVariable [QGVAR(dosimeterAudioActive), true, true]; + +[{ + params ["_args", "_idPFH"]; + _args params ["_unit"]; + + if (!alive _unit || {!("KAT_Dosimeter" in assignedItems _unit)} || {!(_unit getVariable [QGVAR(dosimeterEnabled), false])}) exitWith { + _unit setVariable [QGVAR(dosimeterEnabled), false, true]; + _unit setVariable [QGVAR(dosimeterAudioActive), false, true]; + _idPFH call CBA_fnc_removePerFrameHandler; + }; + + if !(_unit getVariable [QGVAR(dosimeterSound), false]) exitWith {}; + + private _rate = _unit getVariable [QGVAR(radDoseRate), 0]; + if (_rate < 0.01) exitWith {}; + + private _tone = switch (true) do { + case (_rate > 10): { QGVAR(geiger_rapid) }; + case (_rate > 1): { QGVAR(geiger_fast) }; + case (_rate > 0.1): { QGVAR(geiger_normal) }; + default { QGVAR(geiger_slow) }; + }; + + [QGVAR(playTone), [_unit, _tone], _unit] call CBA_fnc_targetEvent; +}, 5, [_unit]] call CBA_fnc_addPerFrameHandler; diff --git a/addons/chemical/functions/fnc_estimateRadDose.sqf b/addons/chemical/functions/fnc_estimateRadDose.sqf new file mode 100644 index 000000000..a83e83758 --- /dev/null +++ b/addons/chemical/functions/fnc_estimateRadDose.sqf @@ -0,0 +1,46 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Triage diagnostic: estimates a patient's accumulated radiation dose and + * prognosis from their absorbed dose and the time-to-emesis biomarker, shown + * to the examining medic. Reports the exact accumulated dose (Gy). + * + * Runs on the medic's machine (treatment callbackSuccess). + * + * Arguments: + * 0: Medic + * 1: Patient + * + * Return Value: + * None + * + * Public: No + */ + +params ["_medic", "_patient"]; + +private _dose = _patient getVariable [QGVAR(radDoseWB), 0]; + +private _prognosis = switch (true) do { + case (_dose >= GVAR(rad_doseThreshold_lethal)): { LLSTRING(radPrognosis_lethal) }; + case (_dose >= GVAR(rad_doseThreshold_severe)): { LLSTRING(radPrognosis_severe) }; + case (_dose >= GVAR(rad_doseThreshold_moderate)): { LLSTRING(radPrognosis_moderate) }; + case (_dose >= GVAR(rad_doseThreshold_mild)): { LLSTRING(radPrognosis_mild) }; + default { LLSTRING(radPrognosis_none) }; +}; + +private _vomitTime = _patient getVariable [QGVAR(radTimeToVomit), -1]; +private _emesis = if (_vomitTime < 0) then { + LLSTRING(radEmesis_none) +} else { + format [LLSTRING(radEmesis_since), round ((CBA_missionTime - _vomitTime) / 60)] +}; + +private _text = format [ + "%1
%2
%3", + format [LLSTRING(radEstimate_dose), _dose toFixed 2], + _prognosis, + _emesis +]; + +[_text, 2, _medic] call ACEFUNC(common,displayTextStructured); diff --git a/addons/chemical/functions/fnc_evaluateRadDose.sqf b/addons/chemical/functions/fnc_evaluateRadDose.sqf new file mode 100644 index 000000000..32d1daa09 --- /dev/null +++ b/addons/chemical/functions/fnc_evaluateRadDose.sqf @@ -0,0 +1,51 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Maps a unit's accumulated whole-body dose to an Acute Radiation Syndrome + * (ARS) severity tier, sets the marrow/immune suppression factors for that + * tier, and (when the tier rises) schedules the staged sickness chain. + * + * Tiers: 0 none, 1 mild, 2 moderate (hematopoietic), 3 severe (GI), + * 4 lethal (neurovascular/CNS). + * + * Idempotent per tier: a chain is only (re)scheduled when the tier increases, + * so this is safe to call every exposure tick. + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Public: No + */ + +params ["_unit"]; + +private _severity = _unit getVariable [QGVAR(radSeverity), 0]; + +private _tier = switch (true) do { + case (_severity >= GVAR(rad_doseThreshold_lethal)): {4}; + case (_severity >= GVAR(rad_doseThreshold_severe)): {3}; + case (_severity >= GVAR(rad_doseThreshold_moderate)): {2}; + case (_severity >= GVAR(rad_doseThreshold_mild)): {1}; + default {0}; +}; + +private _currentTier = _unit getVariable [QGVAR(radSicknessTier), 0]; + +private _suppression = [1, 0.85, 0.6, 0.35, 0.1] select _tier; +_unit setVariable [QGVAR(radMarrowFactor), _suppression, true]; +_unit setVariable [QGVAR(radImmuneFactor), _suppression, true]; + +_unit setVariable [QGVAR(radSicknessTier), _tier, true]; + +if (_tier >= 1) then { + [_unit] call FUNC(startRadPhysiologyTick); +}; + +if (_tier <= _currentTier) exitWith {}; + +private _scale = [1, 1, 0.7, 0.45, 0.2] select _tier; + +[_unit, _tier, _scale] call FUNC(scheduleRadSicknessChain); diff --git a/addons/chemical/functions/fnc_exposureWatcherPFH.sqf b/addons/chemical/functions/fnc_exposureWatcherPFH.sqf index e953f8eab..63337d8b7 100644 --- a/addons/chemical/functions/fnc_exposureWatcherPFH.sqf +++ b/addons/chemical/functions/fnc_exposureWatcherPFH.sqf @@ -105,6 +105,29 @@ private _toRemove = []; }; }; + private _radTier = _unit getVariable [QGVAR(radSicknessTier), 0]; + + { + _x params ["_var", "_effect", "_minTier"]; + private _deadline = _unit getVariable [_var, 0]; + if (_deadline > 0) then { + if (_now >= _deadline) then { + if (_radTier >= _minTier) then { + [QGVAR(applyDelayedEffect), [_unit, _effect], _unit] call CBA_fnc_targetEvent; + }; + _unit setVariable [_var, -1, true]; + } else { + _hasPending = true; + }; + }; + } forEach [ + [QGVAR(radDeadline_prodromal), "radProdromal", 1], + [QGVAR(radDeadline_hema), "radHema", 2], + [QGVAR(radDeadline_gi), "radGI", 3], + [QGVAR(radDeadline_cns), "radCNS", 4], + [QGVAR(radDeadline_cardiac), "radCardiac", 4] + ]; + if (!_hasPending) then { _toRemove pushBack _netId; }; diff --git a/addons/chemical/functions/fnc_fullHealLocal.sqf b/addons/chemical/functions/fnc_fullHealLocal.sqf index 9a006faaf..77cdd5494 100644 --- a/addons/chemical/functions/fnc_fullHealLocal.sqf +++ b/addons/chemical/functions/fnc_fullHealLocal.sqf @@ -39,3 +39,39 @@ _patient setVariable [QGVAR(mustardBurnActive), false, true]; _patient setVariable [QGVAR(nerveDeadline_vomit), 0, true]; _patient setVariable [QGVAR(nerveDeadline_unconscious), 0, true]; _patient setVariable [QGVAR(nerveDeadline_cardiac), 0, true]; + +_patient setVariable [QGVAR(radDoseWB), 0, true]; +_patient setVariable [QGVAR(radSeverity), 0, true]; +_patient setVariable [QGVAR(radDoseLimb), [0, 0, 0, 0, 0, 0], true]; +_patient setVariable [QGVAR(radInternalBurden), 0, true]; +_patient setVariable [QGVAR(radExternalContam), 0, true]; +_patient setVariable [QGVAR(radDoseRate), 0, true]; +_patient setVariable [QGVAR(radSicknessTier), 0, true]; +_patient setVariable [QGVAR(radMarrowFactor), 1, true]; +_patient setVariable [QGVAR(radImmuneFactor), 1, true]; +_patient setVariable [QGVAR(radInfection), false, true]; +_patient setVariable [QGVAR(radInfectionLevel), 0, true]; +_patient setVariable [QGVAR(radCritical), false, true]; +_patient setVariable [QGVAR(radCollapseTimer), -1, true]; +_patient setVariable [QGVAR(radMarrowRescueWindow), 0, true]; +_patient setVariable [QGVAR(radProtectiveWindow), 0, true]; +_patient setVariable [QGVAR(radChelationWindow), 0, true]; +_patient setVariable [QGVAR(radAntibioticWindow), 0, true]; +_patient setVariable [QGVAR(radAntiemeticWindow), 0, true]; +_patient setVariable [QGVAR(radFilgrastimWindow), 0, true]; +_patient setVariable [QGVAR(radDominantType), "", true]; +_patient setVariable [QGVAR(radInternalPFHActive), false, true]; +_patient setVariable [QGVAR(radContamPFHActive), false, true]; +_patient setVariable [QGVAR(radPhysiologyPFHActive), false, true]; +_patient setVariable [QGVAR(radFever), 0, true]; +_patient setVariable [QGVAR(radBPDrop), 0, true]; +_patient setVariable [QGVAR(radTimeToVomit), -1, true]; + +if (_patient == ACE_player) then { + [false, 0] call EFUNC(feedback,effectRadiation); +}; +_patient setVariable [QGVAR(radDeadline_prodromal), 0, true]; +_patient setVariable [QGVAR(radDeadline_hema), 0, true]; +_patient setVariable [QGVAR(radDeadline_gi), 0, true]; +_patient setVariable [QGVAR(radDeadline_cns), 0, true]; +_patient setVariable [QGVAR(radDeadline_cardiac), 0, true]; diff --git a/addons/chemical/functions/fnc_gui_updateInjuryListGeneral.sqf b/addons/chemical/functions/fnc_gui_updateInjuryListGeneral.sqf index 90803609a..0034d00d0 100644 --- a/addons/chemical/functions/fnc_gui_updateInjuryListGeneral.sqf +++ b/addons/chemical/functions/fnc_gui_updateInjuryListGeneral.sqf @@ -20,6 +20,29 @@ params ["_ctrl", "_target", "_selectionN", "_entries"]; +if (GVAR(rad_icReadout) && {_target getVariable [QGVAR(radCritical), false]}) then { + private _severity = _target getVariable [QGVAR(radSeverity), 0]; + private _fragility = (((_severity - GVAR(rad_doseThreshold_moderate)) / ((GVAR(rad_doseThreshold_lethal) - GVAR(rad_doseThreshold_moderate)) max 0.1)) max 0) min 1; + private _progress = round ((1 - _fragility) * 100); + + _entries pushBack [LLSTRING(radCriticalStatus), [0.85, 0.20, 0.20, 1]]; + _entries pushBack [format [LLSTRING(radICProgress), _progress], [0.90, 0.55, 0.10, 1]]; + + private _missing = []; + private _support = (count (_target getVariable [QACEGVAR(medical,ivBags), []]) > 0) + || {(([_target, "Epinephrine", false] call ACEFUNC(medical_status,getMedicationCount)) select 1) > 0} + || {(([_target, "Norepinephrine", false] call ACEFUNC(medical_status,getMedicationCount)) select 1) > 0}; + if (!_support) then { _missing pushBack LLSTRING(radIC_support); }; + if (CBA_missionTime >= (_target getVariable [QGVAR(radFilgrastimWindow), 0])) then { _missing pushBack LLSTRING(radIC_filgrastim); }; + if (CBA_missionTime >= (_target getVariable [QGVAR(radAntibioticWindow), 0])) then { _missing pushBack LLSTRING(radIC_antibiotics); }; + if (CBA_missionTime >= (_target getVariable [QGVAR(radMarrowRescueWindow), 0])) then { _missing pushBack LLSTRING(radIC_stemcells); }; + if (((_target getVariable [QGVAR(radDoseRate), 0]) >= 0.01) || {(_target getVariable [QGVAR(radInternalBurden), 0]) >= 0.001}) then { _missing pushBack LLSTRING(radIC_source); }; + + if (_missing isNotEqualTo []) then { + _entries pushBack [format [LLSTRING(radICMissing), _missing joinString ", "], [0.90, 0.70, 0.20, 1]]; + }; +}; + if !(missionNamespace getVariable [QGVAR(showPoisoning), true]) exitWith {}; private _poisontype = _target getVariable [QGVAR(poisonType),""]; diff --git a/addons/chemical/functions/fnc_handleRespawn.sqf b/addons/chemical/functions/fnc_handleRespawn.sqf index 2f60a8c9b..bce845c15 100644 --- a/addons/chemical/functions/fnc_handleRespawn.sqf +++ b/addons/chemical/functions/fnc_handleRespawn.sqf @@ -26,3 +26,5 @@ params ["_unit"]; [_unit] call FUNC(fullHealLocal); _unit setVariable [QGVAR(detectorSound), false, true]; +_unit setVariable [QGVAR(dosimeterEnabled), false, true]; +_unit setVariable [QGVAR(dosimeterSound), false, true]; diff --git a/addons/chemical/functions/fnc_hasDosimeter.sqf b/addons/chemical/functions/fnc_hasDosimeter.sqf new file mode 100644 index 000000000..c99703484 --- /dev/null +++ b/addons/chemical/functions/fnc_hasDosimeter.sqf @@ -0,0 +1,20 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Whether the unit has a dosimeter assigned (in the watch slot). + * + * Arguments: + * 0: Unit + * + * Return Value: + * Bool + * + * Example: + * [player] call kat_chemical_fnc_hasDosimeter; + * + * Public: No + */ + +params ["_unit"]; + +"KAT_Dosimeter" in assignedItems _unit diff --git a/addons/chemical/functions/fnc_hideDosimeter.sqf b/addons/chemical/functions/fnc_hideDosimeter.sqf new file mode 100644 index 000000000..945a61b54 --- /dev/null +++ b/addons/chemical/functions/fnc_hideDosimeter.sqf @@ -0,0 +1,19 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Removes the dosimeter HUD from the screen. + * + * Arguments: + * None + * + * Return Value: + * None + * + * Example: + * call kat_chemical_fnc_hideDosimeter + * + * Public: No + */ + +GVAR(DosimeterActive) = false; +"KAT_Dosimeter" cutText ["", "PLAIN", 0, true]; diff --git a/addons/chemical/functions/fnc_initRadProfiles.sqf b/addons/chemical/functions/fnc_initRadProfiles.sqf new file mode 100644 index 000000000..54fa4b04b --- /dev/null +++ b/addons/chemical/functions/fnc_initRadProfiles.sqf @@ -0,0 +1,38 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Builds the radiation type-profile and source-preset registries. + * + * GVAR(radProfiles): type-id -> [wbWeight, skinWeight, inhaleWeight, qualityFactor, [maskF, cbrnF, radGearF, vehicleF]] + * wbWeight - fraction of shielded external rate that becomes whole-body dose + * skinWeight - fraction that becomes local skin/limb dose (beta burns) + * inhaleWeight - fraction of raw rate that becomes internal burden when unmasked + * qualityFactor - biological weighting on whole-body dose (neutron/alpha high) + * [..F] - per-gear external absorbed-dose multipliers (0 = blocks fully) + * + * GVAR(radPresets): preset-id -> [alpha, beta, gamma, neutron] dose-rate (Gy/h) + * + * Arguments: + * None + * + * Return Value: + * None + * + * Public: No + */ + +GVAR(radProfiles) = createHashMapFromArray [ + ["alpha", [0, 0.05, 1.0, 20, [0, 0, 0, 0 ]]], + ["beta", [0.1, 1.0, 0.3, 1, [0.7, 0.1, 0.1, 0.2 ]]], + ["gamma", [1.0, 0.05, 0.05, 1, [0.97, 0.9, 0.4, 0.5 ]]], + ["neutron", [1.2, 0, 0, 10, [1, 0.97, 0.7, 0.7 ]]] +]; + +GVAR(radPresets) = createHashMapFromArray [ + ["custom", [0, 0, 0, 0 ]], + ["Cobalt60", [0, 0, 100, 0 ]], + ["Reactor", [0, 0, 50, 25]], + ["Fallout", [0, 400, 20, 0 ]], + ["AlphaEmitter", [150, 10, 0, 0 ]], + ["DirtyBomb", [40, 250, 50, 0 ]] +]; diff --git a/addons/chemical/functions/fnc_initRadSourceObject.sqf b/addons/chemical/functions/fnc_initRadSourceObject.sqf new file mode 100644 index 000000000..86af250d3 --- /dev/null +++ b/addons/chemical/functions/fnc_initRadSourceObject.sqf @@ -0,0 +1,27 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Registers a placed radioactive-source object as an inverse-square point + * source. Uses a hot beta+gamma profile (a "lost industrial-radiography + * source") so handling it point-blank burns the hands/arms and is rapidly + * lethal whole-body. Runs once per object on the server. + * + * Arguments: + * 0: Source object + * + * Return Value: + * None + * + * Public: No + */ + +params ["_obj"]; + +if (!isServer || {isNull _obj}) exitWith {}; + +private _strengths = [0, 500, 100, 0]; + +[QGVAR(addRadSource), [_obj, 15, _strengths, "inverseSquare", _obj, { + params ["_obj"]; + !isNull _obj +}, [_obj]]] call CBA_fnc_localEvent; diff --git a/addons/chemical/functions/fnc_irradiate.sqf b/addons/chemical/functions/fnc_irradiate.sqf new file mode 100644 index 000000000..aff023f46 --- /dev/null +++ b/addons/chemical/functions/fnc_irradiate.sqf @@ -0,0 +1,111 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Per-unit radiation exposure handler. Routes each radiation type's incident + * dose-rate (after type-specific shielding) into whole-body absorbed dose, + * local skin/limb dose (beta burns), inhaled internal burden, and surface + * contamination, then re-evaluates radiation sickness. + * + * Runs local to the unit's owner (fired via QGVAR(irradiate) target event). + * The geiger reading (radDoseRate) is owned by fnc_radManagerPFH, not here. + * + * Arguments: + * 0: Unit + * 1: Incident dose-rates by type [alpha,beta,gamma,neutron] (Gy/h) + * 2: Source logic + * + * Return Value: + * None + * + * Public: No + */ + +params ["_unit", "_ratesByType", "_radLogic"]; + +if (!GVAR(rad_enable)) exitWith {}; + +if (!local _unit) exitWith { + TRACE_1("rad unit not local",_unit); +}; + +if (getNumber (configOf _unit >> "isPlayableLogic") == 1 || {!(_unit isKindOf "CAManBase")}) exitWith { + TRACE_1("rad unit is virtual or not a man",_unit); +}; + +if !(isDamageAllowed _unit && {_unit getVariable [QACEGVAR(medical,allowDamage), true]}) exitWith { + TRACE_1("rad unit is invulnerable",_unit); +}; + +private _hours = RAD_MANAGER_PFH_DELAY / 3600; +private _hasMask = [_unit] call FUNC(hasGasMaskON); +private _kiActive = CBA_missionTime < (_unit getVariable [QGVAR(radProtectiveWindow), 0]); +private _veryClose = (_radLogic distance _unit) < GVAR(rad_localProximity); +private _selfContamSource = (_radLogic getVariable [QGVAR(contamSourceOwner), objNull]) isEqualTo _unit; + +private _wbAdd = 0; +private _internalAdd = 0; +private _contamAdd = 0; +private _skinByPart = [0, 0, 0, 0, 0, 0]; + +{ + private _type = _x; + private _rate = _ratesByType select _forEachIndex; + if (_rate <= 0) then { continue }; + + (GVAR(radProfiles) get _type) params ["_wbW", "_skinW", "_inhaleW", "_qf"]; + private _ext = _rate * ([_unit, _type] call FUNC(radProtection)); + + _wbAdd = _wbAdd + (_ext * _wbW * _qf); + + private _skin = _ext * _skinW; + if (_skin > 0) then { + if (_veryClose) then { + _skinByPart set [2, (_skinByPart select 2) + (_skin * 0.5)]; + _skinByPart set [3, (_skinByPart select 3) + (_skin * 0.5)]; + } else { + _skinByPart = _skinByPart apply { _x + (_skin / 6) }; + }; + }; + + if (!_hasMask && {_inhaleW > 0}) then { + private _inhale = _rate * _inhaleW * GVAR(rad_inhalationFactor); + if (_kiActive) then { _inhale = _inhale * GVAR(rad_kiFactor); }; + _internalAdd = _internalAdd + _inhale; + }; + + if (_type != "neutron" && {!_selfContamSource}) then { + _contamAdd = _contamAdd + _rate; + }; +} forEach RAD_TYPES; + +if (_wbAdd > 0) then { + private _add = _wbAdd * _hours; + _unit setVariable [QGVAR(radDoseWB), (_unit getVariable [QGVAR(radDoseWB), 0]) + _add, true]; + _unit setVariable [QGVAR(radSeverity), (_unit getVariable [QGVAR(radSeverity), 0]) + _add, true]; +}; + +private _limb = _unit getVariable [QGVAR(radDoseLimb), [0, 0, 0, 0, 0, 0]]; +private _thr = GVAR(rad_skinBurnThreshold); +private _parts = RAD_BODY_PARTS; +{ + private _new = (_limb select _forEachIndex) + ((_skinByPart select _forEachIndex) * _hours); + if (_new >= _thr) then { + [_unit, 0.1 + random 0.3, _parts select _forEachIndex, "KAT_radiationBurn", _unit] call ACEFUNC(medical,addDamageToUnit); + _new = _new - _thr; + }; + _limb set [_forEachIndex, _new]; +} forEach _limb; +_unit setVariable [QGVAR(radDoseLimb), _limb, true]; + +if (_internalAdd > 0) then { + _unit setVariable [QGVAR(radInternalBurden), (_unit getVariable [QGVAR(radInternalBurden), 0]) + (_internalAdd * _hours), true]; + [_unit] call FUNC(startRadInternalTick); +}; + +if (_contamAdd > 0) then { + private _contam = ((_unit getVariable [QGVAR(radExternalContam), 0]) + (_contamAdd * GVAR(rad_contaminationDeposition) * _hours)) min 1; + _unit setVariable [QGVAR(radExternalContam), _contam, true]; + [_unit] call FUNC(startRadContaminationTick); +}; + +[_unit] call FUNC(evaluateRadDose); diff --git a/addons/chemical/functions/fnc_pickupRadSource.sqf b/addons/chemical/functions/fnc_pickupRadSource.sqf new file mode 100644 index 000000000..dd6417a05 --- /dev/null +++ b/addons/chemical/functions/fnc_pickupRadSource.sqf @@ -0,0 +1,25 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Picks up a radioactive-source object: attaches it to the player (globally, so + * the server-side source follows them and doses point-blank). The attached + * source keeps its registration; local skin/limb dose comes from the proximity + * branch in fnc_irradiate. + * + * Arguments: + * 0: Player + * 1: Source object + * + * Return Value: + * None + * + * Public: No + */ + +params ["_player", "_source"]; + +if (isNull _source) exitWith {}; +if !(isNull (_player getVariable [QGVAR(carriedRadSource), objNull])) exitWith {}; + +_player setVariable [QGVAR(carriedRadSource), _source, true]; +[QGVAR(attachRadSource), [_source, _player]] call CBA_fnc_globalEvent; diff --git a/addons/chemical/functions/fnc_radContaminationTickPFH.sqf b/addons/chemical/functions/fnc_radContaminationTickPFH.sqf new file mode 100644 index 000000000..e04f538c0 --- /dev/null +++ b/addons/chemical/functions/fnc_radContaminationTickPFH.sqf @@ -0,0 +1,36 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Owner-local per-unit tick for external (surface) radioactive contamination. + * Decays contamination by weathering and keeps the server-side + * cross-contamination source in sync (so the unit doses itself and nearby + * people and reads on geigers). Self-terminates and removes the source when + * contamination is cleared (decon or full decay) or the unit dies. + * + * Arguments: + * 0: [_unit] + * 1: PFH handle + * + * Return Value: + * None + * + * Public: No + */ + +params ["_args", "_pfhHandle"]; +_args params ["_unit"]; + +if (isNull _unit || {!alive _unit} || {(_unit getVariable [QGVAR(radExternalContam), 0]) <= 0.01}) exitWith { + if (!isNull _unit) then { + _unit setVariable [QGVAR(radExternalContam), 0, true]; + _unit setVariable [QGVAR(radContamPFHActive), false, true]; + [QGVAR(serverRemoveContamSource), [_unit]] call CBA_fnc_serverEvent; + }; + _pfhHandle call CBA_fnc_removePerFrameHandler; +}; + +private _interval = 5; +private _contam = (_unit getVariable [QGVAR(radExternalContam), 0]) * (0 max (1 - (GVAR(rad_contaminationDecay) * _interval))); +_unit setVariable [QGVAR(radExternalContam), _contam, true]; + +[QGVAR(serverRegisterContamSource), [_unit, _contam]] call CBA_fnc_serverEvent; diff --git a/addons/chemical/functions/fnc_radInternalTickPFH.sqf b/addons/chemical/functions/fnc_radInternalTickPFH.sqf new file mode 100644 index 000000000..77d5a048b --- /dev/null +++ b/addons/chemical/functions/fnc_radInternalTickPFH.sqf @@ -0,0 +1,47 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Owner-local per-unit tick that turns internal radionuclide burden into + * committed whole-body dose and decays the burden (biological elimination, + * accelerated while a chelation window is active). Self-terminates when the + * burden is cleared or the unit dies. + * + * Arguments: + * 0: [_unit] + * 1: PFH handle + * + * Return Value: + * None + * + * Public: No + */ + +params ["_args", "_pfhHandle"]; +_args params ["_unit"]; + +if (isNull _unit || {!alive _unit}) exitWith { + if (!isNull _unit) then { _unit setVariable [QGVAR(radInternalPFHActive), false, true]; }; + _pfhHandle call CBA_fnc_removePerFrameHandler; +}; + +private _burden = _unit getVariable [QGVAR(radInternalBurden), 0]; + +if (_burden < 0.001) exitWith { + _unit setVariable [QGVAR(radInternalBurden), 0, true]; + _unit setVariable [QGVAR(radInternalPFHActive), false, true]; + _pfhHandle call CBA_fnc_removePerFrameHandler; +}; + +private _interval = 5; + +private _add = _burden * GVAR(rad_internalConversionRate) * _interval; +_unit setVariable [QGVAR(radDoseWB), (_unit getVariable [QGVAR(radDoseWB), 0]) + _add, true]; +_unit setVariable [QGVAR(radSeverity), (_unit getVariable [QGVAR(radSeverity), 0]) + _add, true]; + +private _decay = GVAR(rad_internalDecayRate); +if (CBA_missionTime < (_unit getVariable [QGVAR(radChelationWindow), 0])) then { + _decay = _decay * GVAR(rad_chelationFactor); +}; +_unit setVariable [QGVAR(radInternalBurden), _burden * (0 max (1 - (_decay * _interval))), true]; + +[_unit] call FUNC(evaluateRadDose); diff --git a/addons/chemical/functions/fnc_radManagerPFH.sqf b/addons/chemical/functions/fnc_radManagerPFH.sqf new file mode 100644 index 000000000..5db12c33a --- /dev/null +++ b/addons/chemical/functions/fnc_radManagerPFH.sqf @@ -0,0 +1,98 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Radiation analogue of fnc_gasManagerPFH. Walks the registered radiation + * sources, removes any whose anchor or condition is gone, and for every unit + * in range computes the per-type incident dose-rate (by geometry) and fires + * the QGVAR(irradiate) target event on the unit's owner. + * + * Owns the geiger reading: radDoseRate (total incident, summed across sources) + * and radDominantType, reset to 0/"" for units no longer in any field. + * + * Source tuple: [_logic, _radius, _strengths(=[a,b,g,n]), _falloff, _condition, _conditionArgs] + * + * Arguments: + * None + * + * Return Value: + * None + * + * Example: + * kat_chemical_fnc_radManagerPFH call CBA_fnc_addPerFrameHandler + * + * Public: No + */ + +private _exposedNow = []; +private _accum = createHashMap; +private _types = RAD_TYPES; + +{ + _y params ["_radLogic", "_radius", "_strengths", ["_falloff", "linear"], ["_condition", {true}], ["_conditionArgs", []]]; + + if (isNull _radLogic) then { + GVAR(radSources) deleteAt _x; + continue; + }; + + if !(_conditionArgs call _condition) then { + TRACE_2("rad condition no longer valid, deleting",_x,_y); + detach _radLogic; + deleteVehicle _radLogic; + GVAR(radSources) deleteAt _x; + continue; + }; + + { + private _unit = _x; + private _distance = (_unit distance _radLogic) min _radius; + + private _falloffFactor = switch (_falloff) do { + case "inverseSquare": { + private _d = _distance max 1; + 1 / (_d * _d) + }; + default { + 1 - (_distance / _radius) + }; + }; + + if (_falloffFactor <= 0) then { continue }; + + private _ratesByType = _strengths apply { _x * _falloffFactor }; + private _total = 0; + { _total = _total + _x } forEach _ratesByType; + if (_total <= 0) then { continue }; + + _exposedNow pushBackUnique _unit; + + private _nid = netId _unit; + private _entry = _accum getOrDefault [_nid, [_unit, 0, "", -1]]; + _entry set [1, (_entry select 1) + _total]; + + private _maxRate = selectMax _ratesByType; + if (_maxRate > (_entry select 3)) then { + _entry set [2, _types select (_ratesByType find _maxRate)]; + _entry set [3, _maxRate]; + }; + _accum set [_nid, _entry]; + + [QGVAR(irradiate), [_unit, _ratesByType, _radLogic], _unit] call CBA_fnc_targetEvent; + } forEach nearestObjects [_radLogic, ["CAManBase"], _radius]; +} forEach GVAR(radSources); + +{ + _y params ["_unit", "_rate", "_domType"]; + if (isNull _unit) then { continue }; + _unit setVariable [QGVAR(radDoseRate), _rate, true]; + _unit setVariable [QGVAR(radDominantType), _domType, true]; +} forEach _accum; + +{ + if (!isNull _x && {!(_x in _exposedNow)}) then { + _x setVariable [QGVAR(radDoseRate), 0, true]; + _x setVariable [QGVAR(radDominantType), "", true]; + }; +} forEach GVAR(radExposedUnits); + +GVAR(radExposedUnits) = _exposedNow; diff --git a/addons/chemical/functions/fnc_radPhysiologyPFH.sqf b/addons/chemical/functions/fnc_radPhysiologyPFH.sqf new file mode 100644 index 000000000..10a6872c9 --- /dev/null +++ b/addons/chemical/functions/fnc_radPhysiologyPFH.sqf @@ -0,0 +1,217 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Owner-local per-unit radiation-physiology tick. Drives the dose-dependent + * sub-syndromes by current sickness tier (hematopoietic anemia, GI dehydration + * and acidosis, neurovascular hypotension and seizures, systemic fever and the + * visual feedback), runs the immune/infection model (sepsis-capable), and + * handles slow spontaneous recovery below the lethal tier. + * + * Each layer is gated on its host KAT subsystem's enable setting so radiation + * never depends on a disabled system; the cross-addon read hooks default to a + * no-op value, so this is inert when the layer is off. + * + * Arguments: + * 0: [_unit] + * 1: PFH handle + * + * Return Value: + * None + * + * Public: No + */ + +params ["_args", "_pfhHandle"]; +_args params ["_unit"]; + +if (isNull _unit || {!alive _unit}) exitWith { + if (!isNull _unit) then { + _unit setVariable [QGVAR(radPhysiologyPFHActive), false, true]; + _unit setVariable [QGVAR(radFever), 0, true]; + _unit setVariable [QGVAR(radBPDrop), 0, true]; + if (_unit == ACE_player) then { [false, 0] call EFUNC(feedback,effectRadiation); }; + }; + _pfhHandle call CBA_fnc_removePerFrameHandler; +}; + +private _interval = 5; +private _tier = _unit getVariable [QGVAR(radSicknessTier), 0]; +private _marrow = _unit getVariable [QGVAR(radMarrowFactor), 1]; + +if (_tier >= 2) then { + private _vol = (1 - _marrow) * GVAR(rad_marrowAnemiaRate) * _interval; + if (_vol > 0) then { REDUCE_TOTAL_BLOOD_VOLUME(_unit,_vol); }; +}; + +if (_tier >= 3) then { + REDUCE_TOTAL_BLOOD_VOLUME(_unit,GVAR(rad_giFluidLossRate) * _interval); + + if (missionNamespace getVariable [QEGVAR(breathing,enable), false]) then { + private _bloodGas = GET_BLOOD_GAS(_unit); + private _drop = GVAR(rad_giAcidosisRate) * _interval; + _bloodGas set [3, ((_bloodGas select 3) - _drop) max 0]; + _bloodGas set [4, ((_bloodGas select 4) - (_drop * 0.02)) max 6.8]; + _unit setVariable [VAR_BLOOD_GAS, _bloodGas, true]; + }; + + if (random 1 < 0.4 && {CBA_missionTime >= (_unit getVariable [QGVAR(radAntiemeticWindow), 0])}) then { + playSound3D [QPATHTOEF_SOUND(airway,sounds\puking1.wav), _unit, false, getPosASL _unit, 5, 1, 15]; + _unit setVariable [VAR_PAIN, ((_unit getVariable [VAR_PAIN, 0]) + 0.05) min 1, true]; + }; +}; + +private _curable = GVAR(rad_lethalCurable); +private _severity = _unit getVariable [QGVAR(radSeverity), 0]; +private _critical = _unit getVariable [QGVAR(radCritical), false]; + +if (_curable) then { + if (_tier >= 4 && {!_critical}) then { + _critical = true; + _unit setVariable [QGVAR(radCritical), true, true]; + _unit setVariable [QGVAR(radCollapseTimer), GVAR(rad_lethalCollapseTime), true]; + }; + if (_critical && {_severity < GVAR(rad_doseThreshold_moderate)}) then { + _critical = false; + _unit setVariable [QGVAR(radCritical), false, true]; + _unit setVariable [QGVAR(radCollapseTimer), -1, true]; + }; +}; + +if (!_curable && {_tier >= 4}) then { + if (missionNamespace getVariable [QEGVAR(circulation,enable), false]) then { + private _bp = (_unit getVariable [QGVAR(radBPDrop), 0]) + (GVAR(rad_cnsHypotension) * 0.1 * _interval); + _unit setVariable [QGVAR(radBPDrop), _bp min GVAR(rad_cnsHypotension), true]; + }; + _unit setVariable [VAR_PAIN, ((_unit getVariable [VAR_PAIN, 0]) + 0.1) min 1, true]; + if (_unit == ACE_player && {random 1 < 0.3}) then { addCamShake [6, 2, 15]; }; +}; + +if (_critical) then { + private _inArrest = _unit getVariable [QACEGVAR(medical,inCardiacArrest), false]; + private _fragility = (((_severity - GVAR(rad_doseThreshold_moderate)) / ((GVAR(rad_doseThreshold_lethal) - GVAR(rad_doseThreshold_moderate)) max 0.1)) max 0) min 1; + private _support = (count (_unit getVariable [QACEGVAR(medical,ivBags), []]) > 0) + || {(([_unit, "Epinephrine", false] call ACEFUNC(medical_status,getMedicationCount)) select 1) > 0} + || {(([_unit, "Norepinephrine", false] call ACEFUNC(medical_status,getMedicationCount)) select 1) > 0}; + + if (_inArrest) then { + _unit setVariable [QGVAR(radCollapseTimer), GVAR(rad_lethalCollapseTime), true]; + } else { + if (missionNamespace getVariable [QEGVAR(circulation,enable), false]) then { + private _bp = _unit getVariable [QGVAR(radBPDrop), 0]; + if (_support) then { + _bp = (_bp - (GVAR(rad_cnsHypotension) * 0.15 * _interval)) max 0; + } else { + _bp = (_bp + (GVAR(rad_cnsHypotension) * 0.1 * _interval)) min GVAR(rad_cnsHypotension); + }; + _unit setVariable [QGVAR(radBPDrop), _bp, true]; + }; + + if (_tier >= 4) then { + _unit setVariable [VAR_PAIN, ((_unit getVariable [VAR_PAIN, 0]) + 0.1) min 1, true]; + if (_unit == ACE_player && {random 1 < 0.3}) then { addCamShake [6, 2, 15]; }; + }; + + private _timer = _unit getVariable [QGVAR(radCollapseTimer), GVAR(rad_lethalCollapseTime)]; + if (_support) then { + _timer = (_timer + _interval) min GVAR(rad_lethalCollapseTime); + } else { + _timer = _timer - _interval; + }; + _unit setVariable [QGVAR(radCollapseTimer), _timer, true]; + + private _triggerArrest = (_timer <= 0); + if (!_triggerArrest) then { + private _chance = GVAR(rad_recrashChance) * _fragility; + if (_support) then { _chance = _chance * 0.5; }; + if (random 1 < _chance) then { _triggerArrest = true; }; + }; + + if (_triggerArrest) then { + _unit setVariable [QGVAR(radCollapseTimer), GVAR(rad_lethalCollapseTime), true]; + [QACEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent; + if ((missionNamespace getVariable [QEGVAR(circulation,AdvRhythm), false]) && {random 1 < (GVAR(rad_shockableChance) * _fragility)}) then { + [{ + params ["_unit"]; + if (_unit getVariable [QACEGVAR(medical,inCardiacArrest), false]) then { + _unit setVariable [QEGVAR(circulation,cardiacArrestType), selectRandom [3, 4], true]; + }; + }, [_unit], 0.5] call CBA_fnc_waitAndExecute; + }; + } else { + private _stem = CBA_missionTime < (_unit getVariable [QGVAR(radMarrowRescueWindow), 0]); + private _filg = CBA_missionTime < (_unit getVariable [QGVAR(radFilgrastimWindow), 0]); + private _abx = CBA_missionTime < (_unit getVariable [QGVAR(radAntibioticWindow), 0]); + private _sourceGone = ((_unit getVariable [QGVAR(radDoseRate), 0]) < 0.01) && {(_unit getVariable [QGVAR(radInternalBurden), 0]) < 0.001}; + if (_support && _stem && _filg && _abx && _sourceGone) then { + private _newSev = ((_unit getVariable [QGVAR(radSeverity), 0]) - (GVAR(rad_criticalRecoveryRate) * _interval)) max 0; + _unit setVariable [QGVAR(radSeverity), _newSev, true]; + }; + }; + }; +}; + +private _infLevel = _unit getVariable [QGVAR(radInfectionLevel), 0]; +if (GVAR(rad_infectionEnable)) then { + private _immune = _unit getVariable [QGVAR(radImmuneFactor), 1]; + private _antibiotic = CBA_missionTime < (_unit getVariable [QGVAR(radAntibioticWindow), 0]); + + if (_infLevel <= 0) then { + private _hasWounds = ((count (_unit getVariable [VAR_OPEN_WOUNDS, []])) + (count (_unit getVariable [VAR_BANDAGED_WOUNDS, []]))) > 0; + if (_immune < 0.9 && {_hasWounds} && {!_antibiotic} && {random 1 < ((1 - _immune) * GVAR(rad_infectionChance) * _interval)}) then { + _infLevel = 0.05; + _unit setVariable [QGVAR(radInfection), true, true]; + }; + } else { + if (_antibiotic || {_immune > 0.95}) then { + _infLevel = (_infLevel - (0.05 * _interval)) max 0; + } else { + _infLevel = (_infLevel + ((1 - _immune) * GVAR(rad_infectionSeverityRate) * _interval)) min 1; + }; + + _unit setVariable [VAR_PAIN, ((_unit getVariable [VAR_PAIN, 0]) + (0.05 * _infLevel)) min 1, true]; + REDUCE_TOTAL_BLOOD_VOLUME(_unit,(_infLevel * _infLevel) * GVAR(rad_infectionDamageRate) * _interval); + + if (_infLevel <= 0) then { _unit setVariable [QGVAR(radInfection), false, true]; }; + }; + + _unit setVariable [QGVAR(radInfectionLevel), _infLevel, true]; +}; + +if (missionNamespace getVariable [QEGVAR(hypothermia,hypothermiaActive), false]) then { + private _tierFever = ([0, 0.5, 1, 1.5, 2] select _tier) min GVAR(rad_feverMax); + private _targetFever = _tierFever max (_infLevel * GVAR(rad_feverMax)); + private _cur = _unit getVariable [QGVAR(radFever), 0]; + _unit setVariable [QGVAR(radFever), (_cur + ((_targetFever - _cur) * 0.4)), true]; +}; + +if (_unit == ACE_player) then { + if (GVAR(rad_visualEffect)) then { + private _doseRate = _unit getVariable [QGVAR(radDoseRate), 0]; + private _intensity = ((_tier / 4) max ((_doseRate / 50) min 1)) min 1; + [true, _intensity] call EFUNC(feedback,effectRadiation); + } else { + [false, 0] call EFUNC(feedback,effectRadiation); + }; +}; + +private _doseRate = _unit getVariable [QGVAR(radDoseRate), 0]; +private _burden = _unit getVariable [QGVAR(radInternalBurden), 0]; +if (!_critical && {_tier < 4} && {_doseRate < 0.01} && {_burden < 0.001}) then { + private _recovery = GVAR(rad_recoveryRate); + if (CBA_missionTime < (_unit getVariable [QGVAR(radFilgrastimWindow), 0])) then { + _recovery = _recovery * GVAR(rad_filgrastimFactor); + }; + private _severity = (_unit getVariable [QGVAR(radSeverity), 0]) - (_recovery * _interval); + _unit setVariable [QGVAR(radSeverity), _severity max 0, true]; + _unit setVariable [QGVAR(radBPDrop), ((_unit getVariable [QGVAR(radBPDrop), 0]) - (2 * _interval)) max 0, true]; +}; + +[_unit] call FUNC(evaluateRadDose); + +_tier = _unit getVariable [QGVAR(radSicknessTier), 0]; +if (_tier == 0 && {!(_unit getVariable [QGVAR(radCritical), false])} && {(_unit getVariable [QGVAR(radFever), 0]) <= 0.05} && {(_unit getVariable [QGVAR(radBPDrop), 0]) <= 0} && {!(_unit getVariable [QGVAR(radInfection), false])}) exitWith { + _unit setVariable [QGVAR(radFever), 0, true]; + _unit setVariable [QGVAR(radPhysiologyPFHActive), false, true]; + if (_unit == ACE_player) then { [false, 0] call EFUNC(feedback,effectRadiation); }; + _pfhHandle call CBA_fnc_removePerFrameHandler; +}; diff --git a/addons/chemical/functions/fnc_radProtection.sqf b/addons/chemical/functions/fnc_radProtection.sqf new file mode 100644 index 000000000..94e42e1cf --- /dev/null +++ b/addons/chemical/functions/fnc_radProtection.sqf @@ -0,0 +1,51 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Returns a unit's external shielding multiplier (0..1, 1 = unshielded) for a + * given radiation type. Each type's per-gear coefficients come from its profile + * in GVAR(radProfiles); the rad_protectionFactor* settings are per-gear + * effectiveness knobs (0 = gear does nothing, 1 = full profile protection). + * + * Arguments: + * 0: Unit + * 1: Radiation type id + * + * Return Value: + * Absorbed-dose multiplier + * + * Example: + * [player, "gamma"] call kat_chemical_fnc_radProtection; + * + * Public: No + */ + +params ["_unit", "_type"]; + +private _profile = GVAR(radProfiles) getOrDefault [_type, [0, 0, 0, 1, [1, 1, 1, 1]]]; +(_profile param [4, [1, 1, 1, 1]]) params ["_maskF", "_cbrnF", "_radF", "_vehF"]; + +private _factor = 1; + +private _fnc_apply = { + params ["_gearFactor", "_eff"]; + _factor = _factor * (1 - ((1 - _gearFactor) * _eff)); +}; + +if ([_unit] call FUNC(hasGasMaskON)) then { + [_maskF, GVAR(rad_protectionFactorMask)] call _fnc_apply; +}; + +if ([_unit] call FUNC(hasCBRNProtection)) then { + [_cbrnF, GVAR(rad_protectionFactorCBRN)] call _fnc_apply; +}; + +private _radList = missionNamespace getVariable [QGVAR(availRadProtectionList), []]; +if ((_radList isNotEqualTo []) && {uniform _unit != ""} && {(uniform _unit) in _radList}) then { + [_radF, GVAR(rad_protectionFactorRadGear)] call _fnc_apply; +}; + +if (!isNull objectParent _unit) then { + [_vehF, GVAR(rad_protectionFactorVehicle)] call _fnc_apply; +}; + +_factor diff --git a/addons/chemical/functions/fnc_radSurvey.sqf b/addons/chemical/functions/fnc_radSurvey.sqf new file mode 100644 index 000000000..362521189 --- /dev/null +++ b/addons/chemical/functions/fnc_radSurvey.sqf @@ -0,0 +1,35 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Radiation survey diagnostic: reads a patient's external (surface) + * contamination level, dominant radiation type, and ambient dose-rate from the + * dosimeter and reports them to the examining medic. + * + * Runs on the medic's machine (treatment callbackSuccess). + * + * Arguments: + * 0: Medic + * 1: Patient + * + * Return Value: + * None + * + * Public: No + */ + +params ["_medic", "_patient"]; + +private _contam = _patient getVariable [QGVAR(radExternalContam), 0]; +private _type = _patient getVariable [QGVAR(radDominantType), ""]; +private _rate = _patient getVariable [QGVAR(radDoseRate), 0]; + +private _typeText = if (_type isEqualTo "") then { LLSTRING(radSurvey_none) } else { _type }; + +private _text = format [ + "%1
%2
%3", + format [LLSTRING(radSurvey_contam), round (_contam * 100)], + format [LLSTRING(radSurvey_rate), _rate toFixed 3], + format [LLSTRING(radSurvey_type), _typeText] +]; + +[_text, 2, _medic] call ACEFUNC(common,displayTextStructured); diff --git a/addons/chemical/functions/fnc_radmodule.sqf b/addons/chemical/functions/fnc_radmodule.sqf new file mode 100644 index 000000000..59ac31691 --- /dev/null +++ b/addons/chemical/functions/fnc_radmodule.sqf @@ -0,0 +1,55 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Eden module that spawns a radiation source. Resolves a preset (or the + * per-type Custom fields) into a [alpha,beta,gamma,neutron] strength array and + * registers the source. Cannot be called manually. + * + * Arguments: + * 0: Logic + * 1: Affected Units (unused) + * 2: Activated + * + * Return Value: + * None + * + * Public: No + */ + +params ["_logic", "_units", "_activated"]; + +private _radius = _logic getVariable ["Radius", 20]; +private _pointSource = _logic getVariable ["PointSource", false]; +private _presetName = ["custom", "Cobalt60", "Reactor", "Fallout", "AlphaEmitter", "DirtyBomb"] param [_logic getVariable ["Preset", 0], "custom"]; + +private _strengths = if (_presetName isEqualTo "custom") then { + [_logic getVariable ["Alpha", 0], _logic getVariable ["Beta", 0], _logic getVariable ["Gamma", 0], _logic getVariable ["Neutron", 0]] +} else { + +(GVAR(radPresets) getOrDefault [_presetName, [0, 0, 0, 0]]) +}; + +if (count _units == 0) then {_units pushBack _logic;}; + +if (!_activated) exitWith {}; + +if (isServer) then { + [{ + params ["_logic", "_radius", "_strengths", "_pointSource", "_units"]; + + private _falloff = ["linear", "inverseSquare"] select _pointSource; + + { + [QGVAR(addRadSource), [_x, _radius, _strengths, _falloff, _x, { + params ["_endTime", "_logic"]; + + if (isNull _logic) exitWith { + false + }; + + CBA_missionTime < _endTime + }, [CBA_missionTime + 1e10, _logic]]] call CBA_fnc_serverEvent; + + } forEach _units; + + }, [_logic, _radius, _strengths, _pointSource, _units], 1] call CBA_fnc_waitAndExecute; +}; diff --git a/addons/chemical/functions/fnc_registerContaminatedSource.sqf b/addons/chemical/functions/fnc_registerContaminatedSource.sqf new file mode 100644 index 000000000..ad2e96679 --- /dev/null +++ b/addons/chemical/functions/fnc_registerContaminatedSource.sqf @@ -0,0 +1,35 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Server-side: (re)registers a contaminated unit as a weak beta/gamma point + * source so it doses itself and anyone nearby and shows on geigers. Tagged with + * contamSourceOwner so the unit's own exposure handler doesn't re-deposit + * contamination from it (no feedback loop). The source self-removes via its + * condition once the unit's contamination clears. + * + * Arguments: + * 0: Unit + * 1: Contamination level (0..1) + * + * Return Value: + * None + * + * Public: No + */ + +params ["_unit", "_contam"]; + +if (isNull _unit) exitWith {}; + +private _gamma = _contam * GVAR(rad_crossContamStrength); +private _strengths = [0, _gamma * 0.5, _gamma, 0]; + +[QGVAR(addRadSource), [_unit, 4, _strengths, "linear", _unit, { + params ["_unit"]; + !isNull _unit && {alive _unit} && {(_unit getVariable [QGVAR(radExternalContam), 0]) > 0.01} +}, [_unit]]] call CBA_fnc_localEvent; + +private _entry = GVAR(radSources) getOrDefault [hashValue _unit, []]; +if (_entry isNotEqualTo []) then { + (_entry select 0) setVariable [QGVAR(contamSourceOwner), _unit, true]; +}; diff --git a/addons/chemical/functions/fnc_scheduleRadSicknessChain.sqf b/addons/chemical/functions/fnc_scheduleRadSicknessChain.sqf new file mode 100644 index 000000000..65762bd6a --- /dev/null +++ b/addons/chemical/functions/fnc_scheduleRadSicknessChain.sqf @@ -0,0 +1,51 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Schedules the staged radiation-sickness chain by writing deadline variables, + * which the exposure watcher PFH consumes. Mirrors fnc_scheduleNerveSymptomChain + * but unlocks stages by ARS tier and compresses delays at higher tiers. + * + * Per-stage deadline convention: + * 0 = never scheduled (eligible) + * >0 = pending (fires when CBA_missionTime reaches it) + * -1 = already fired (set by the watcher; not rescheduled) + * + * Arguments: + * 0: Unit + * 1: ARS tier (1..4) + * 2: Delay scale (shorter at higher tiers) + * + * Return Value: + * None + * + * Public: No + */ + +params ["_unit", "_tier", "_scale"]; + +private _now = CBA_missionTime; + +private _fnc_sched = { + params ["_var", "_delay"]; + if ((_unit getVariable [_var, 0]) == 0) then { + _unit setVariable [_var, _now + (_delay * _scale), true]; + }; +}; + +if (_tier >= 1) then { + [QGVAR(radDeadline_prodromal), GVAR(rad_prodromalDelay)] call _fnc_sched; +}; +if (_tier >= 2) then { + [QGVAR(radDeadline_hema), GVAR(rad_hemaDelay)] call _fnc_sched; +}; +if (_tier >= 3) then { + [QGVAR(radDeadline_gi), GVAR(rad_giDelay)] call _fnc_sched; +}; +if (_tier >= 4) then { + [QGVAR(radDeadline_cns), GVAR(rad_cnsDelay)] call _fnc_sched; + if (!GVAR(rad_lethalCurable)) then { + [QGVAR(radDeadline_cardiac), GVAR(rad_cardiacDelay)] call _fnc_sched; + }; +}; + +[_unit] call FUNC(addToExposureWatcher); diff --git a/addons/chemical/functions/fnc_showDosimeter.sqf b/addons/chemical/functions/fnc_showDosimeter.sqf new file mode 100644 index 000000000..bbb580b78 --- /dev/null +++ b/addons/chemical/functions/fnc_showDosimeter.sqf @@ -0,0 +1,63 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Displays the dosimeter HUD and runs a per-frame handler that refreshes the + * accumulated whole-body dose (Gy) and, while the dosimeter is enabled, the + * current dose-rate (Gy/h). The rate reads "--" when the dosimeter is off and + * 0 once the unit leaves a field. + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Example: + * [player] call kat_chemical_fnc_showDosimeter + * + * Public: Yes + */ + +params ["_unit"]; + +"KAT_Dosimeter" cutRsc ["KAT_Dosimeter", "PLAIN", 0, true]; + +if (isNull (uiNamespace getVariable ["KAT_Dosimeter", displayNull])) exitWith {}; + +GVAR(DosimeterActive) = true; + +private _display = uiNamespace getVariable ["KAT_Dosimeter", displayNull]; +private _rate = _display displayCtrl 18814; +private _dose = _display displayCtrl 18815; + +[{ + _this params ["_args", "_pfhID"]; + _args params ["_unit", "_rate", "_dose"]; + + if !(GVAR(DosimeterActive)) exitWith { + _pfhID call CBA_fnc_removePerFrameHandler; + }; + + if !(alive _unit) exitWith { + call FUNC(hideDosimeter); + _pfhID call CBA_fnc_removePerFrameHandler; + }; + + if !("KAT_Dosimeter" in assignedItems _unit) exitWith { + call FUNC(hideDosimeter); + _pfhID call CBA_fnc_removePerFrameHandler; + }; + + private _doseTotal = _unit getVariable [QGVAR(radDoseWB), 0]; + _dose ctrlSetText (format ["%1 Gy", _doseTotal toFixed 3]); + + if (_unit getVariable [QGVAR(dosimeterEnabled), false]) then { + _rate ctrlSetText (format ["%1 Gy/h", (_unit getVariable [QGVAR(radDoseRate), 0]) toFixed 3]); + } else { + _rate ctrlSetText "--"; + }; +}, 1, [ + _unit, + _rate, + _dose +]] call CBA_fnc_addPerFrameHandler; diff --git a/addons/chemical/functions/fnc_startRadContaminationTick.sqf b/addons/chemical/functions/fnc_startRadContaminationTick.sqf new file mode 100644 index 000000000..ccf17a0dd --- /dev/null +++ b/addons/chemical/functions/fnc_startRadContaminationTick.sqf @@ -0,0 +1,23 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Starts the owner-local external-contamination tick for a unit if not already + * running. Decays surface contamination over time and keeps the unit's + * cross-contamination source (server-side) in sync. Idempotent. + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Public: No + */ + +params ["_unit"]; + +if (isNull _unit) exitWith {}; +if (_unit getVariable [QGVAR(radContamPFHActive), false]) exitWith {}; +_unit setVariable [QGVAR(radContamPFHActive), true, true]; + +[LINKFUNC(radContaminationTickPFH), 5, [_unit]] call CBA_fnc_addPerFrameHandler; diff --git a/addons/chemical/functions/fnc_startRadInternalTick.sqf b/addons/chemical/functions/fnc_startRadInternalTick.sqf new file mode 100644 index 000000000..e861aed84 --- /dev/null +++ b/addons/chemical/functions/fnc_startRadInternalTick.sqf @@ -0,0 +1,24 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Starts the owner-local internal-burden tick for a unit if not already + * running. Converts internalised radionuclides into committed whole-body dose + * over time and decays the burden (faster while a chelation window is active). + * Idempotent. + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Public: No + */ + +params ["_unit"]; + +if (isNull _unit) exitWith {}; +if (_unit getVariable [QGVAR(radInternalPFHActive), false]) exitWith {}; +_unit setVariable [QGVAR(radInternalPFHActive), true, true]; + +[LINKFUNC(radInternalTickPFH), 5, [_unit]] call CBA_fnc_addPerFrameHandler; diff --git a/addons/chemical/functions/fnc_startRadPhysiologyTick.sqf b/addons/chemical/functions/fnc_startRadPhysiologyTick.sqf new file mode 100644 index 000000000..f94cf418e --- /dev/null +++ b/addons/chemical/functions/fnc_startRadPhysiologyTick.sqf @@ -0,0 +1,24 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Starts the owner-local radiation-physiology tick for a unit if not already + * running. Drives the ongoing dose-dependent sub-syndromes (anemia, GI, + * hypotension, fever, visual feedback) and handles spontaneous recovery. + * Idempotent. + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Public: No + */ + +params ["_unit"]; + +if (isNull _unit) exitWith {}; +if (_unit getVariable [QGVAR(radPhysiologyPFHActive), false]) exitWith {}; +_unit setVariable [QGVAR(radPhysiologyPFHActive), true, true]; + +[LINKFUNC(radPhysiologyPFH), 5, [_unit]] call CBA_fnc_addPerFrameHandler; diff --git a/addons/chemical/functions/fnc_treatmentAdvanced_AntiRadLocal.sqf b/addons/chemical/functions/fnc_treatmentAdvanced_AntiRadLocal.sqf new file mode 100644 index 000000000..cdf98cbeb --- /dev/null +++ b/addons/chemical/functions/fnc_treatmentAdvanced_AntiRadLocal.sqf @@ -0,0 +1,58 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Applies an anti-radiation drug to a patient. Both effects are timestamp + * windows read elsewhere, so they are locality-safe to set from any machine: + * "ki" - potassium iodide: opens a prophylactic uptake-reduction window + * (read in fnc_irradiate via rad_kiFactor). + * "prussian" - Prussian blue: opens a chelation window that accelerates + * internal-burden elimination (read in fnc_radInternalTickPFH). + * + * Arguments: + * 0: Patient + * 1: Mode + * + * Modes: + * "ki" - potassium iodide: prophylactic uptake-reduction window. + * "prussian" - Prussian blue: chelation window (faster internal clearance). + * "antibiotics"- opens an infection-suppression window and cuts current infection. + * "filgrastim" - opens a window that accelerates marrow/sickness recovery. + * "antiemetic" - opens a window that suppresses radiation vomiting. + * "stemcells" - opens the marrow-rescue window that lets a lethal-tier + * casualty's sickness decay under full intensive care. + * + * Return Value: + * None + * + * Public: No + */ + +params ["_patient", "_mode"]; + +switch (_mode) do { + case "ki": { + _patient setVariable [QGVAR(radProtectiveWindow), CBA_missionTime + GVAR(rad_kiDuration), true]; + [_patient, LLSTRING(potassiumIodideItem)] call ACEFUNC(medical_treatment,addToTriageCard); + }; + case "prussian": { + _patient setVariable [QGVAR(radChelationWindow), CBA_missionTime + GVAR(rad_chelationDuration), true]; + [_patient, LLSTRING(prussianBlueItem)] call ACEFUNC(medical_treatment,addToTriageCard); + }; + case "antibiotics": { + _patient setVariable [QGVAR(radAntibioticWindow), CBA_missionTime + GVAR(rad_antibioticDuration), true]; + _patient setVariable [QGVAR(radInfectionLevel), (_patient getVariable [QGVAR(radInfectionLevel), 0]) * 0.5, true]; + [_patient, LLSTRING(antibioticsItem)] call ACEFUNC(medical_treatment,addToTriageCard); + }; + case "filgrastim": { + _patient setVariable [QGVAR(radFilgrastimWindow), CBA_missionTime + GVAR(rad_filgrastimDuration), true]; + [_patient, LLSTRING(filgrastimItem)] call ACEFUNC(medical_treatment,addToTriageCard); + }; + case "antiemetic": { + _patient setVariable [QGVAR(radAntiemeticWindow), CBA_missionTime + GVAR(rad_antiemeticDuration), true]; + [_patient, LLSTRING(antiemeticItem)] call ACEFUNC(medical_treatment,addToTriageCard); + }; + case "stemcells": { + _patient setVariable [QGVAR(radMarrowRescueWindow), CBA_missionTime + GVAR(rad_marrowRescueDuration), true]; + [_patient, LLSTRING(stemCellsItem)] call ACEFUNC(medical_treatment,addToTriageCard); + }; +}; diff --git a/addons/chemical/functions/fnc_ui_radModule.sqf b/addons/chemical/functions/fnc_ui_radModule.sqf new file mode 100644 index 000000000..fbd16ce30 --- /dev/null +++ b/addons/chemical/functions/fnc_ui_radModule.sqf @@ -0,0 +1,70 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Confirm/cancel handler for the radiation Zeus module attributes dialog. + * On confirm reads the radius/strength/point-source inputs and registers a + * radiation source; on cancel deletes the placed logic. Mirrors fnc_ui_gasModule. + * + * Arguments: + * 0: Control + * + * Return Value: + * None + * + * Example: + * [_control] call kat_chemical_fnc_ui_radModule; + * + * Public: No + */ + +params ["_control"]; + +private _display = ctrlParent _control; +private _ctrlButtonOK = _display displayCtrl 1; +private _logic = GETMVAR(BIS_fnc_initCuratorAttributes_target,objNull); + +_control ctrlRemoveAllEventHandlers "SetFocus"; + +private _fnc_onUnload = { + params ["_display"]; + private _logic = GETMVAR(BIS_fnc_initCuratorAttributes_target,objNull); + if (isNull _logic) exitWith {}; + if !(_display getVariable [QGVAR(Confirmed), false]) then { + deleteVehicle _logic; + }; +}; + +private _fnc_onConfirm = { + params [["_ctrlButtonOK", controlNull, [controlNull]]]; + + private _display = ctrlParent _ctrlButtonOK; + if (isNull _display) exitWith {}; + + private _logic = GETMVAR(BIS_fnc_initCuratorAttributes_target,objNull); + if (isNull _logic) exitWith {}; + + private _radius = _display getVariable [QGVAR(ui_radius), 20]; + private _strengths = _display getVariable [QGVAR(ui_radStrengths), [0, 0, 50, 0]]; + private _pointSource = _display getVariable [QGVAR(ui_radPointSource), false]; + private _falloff = ["linear", "inverseSquare"] select _pointSource; + + private _center = _logic; + if !(isNull attachedTo _logic) then { + _center = attachedTo _logic; + }; + + [QGVAR(addRadSource), [_center, _radius, _strengths, _falloff, _logic, { + params ["_endTime", "_logic"]; + + if (isNull _logic) exitWith { + false + }; + + CBA_missionTime < _endTime + }, [CBA_missionTime + 1e10, _logic]]] call CBA_fnc_serverEvent; + + _display setVariable [QGVAR(Confirmed), true]; +}; + +_display displayAddEventHandler ["Unload", _fnc_onUnload]; +_ctrlButtonOK ctrlAddEventHandler ["ButtonClick", _fnc_onConfirm]; diff --git a/addons/chemical/initSettings.inc.sqf b/addons/chemical/initSettings.inc.sqf index 4fe01e504..2c7457b3d 100644 --- a/addons/chemical/initSettings.inc.sqf +++ b/addons/chemical/initSettings.inc.sqf @@ -273,3 +273,468 @@ [1, 600, 8], true ] call CBA_fnc_addSetting; + +// =============== Radiation =============== +[ + QGVAR(rad_enable), + "CHECKBOX", + [LLSTRING(SETTING_rad_enable), LLSTRING(SETTING_rad_enable_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [true], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_showSickness), + "CHECKBOX", + [LLSTRING(SETTING_rad_showSickness), LLSTRING(SETTING_rad_showSickness_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [true], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_doseThreshold_mild), + "SLIDER", + [LLSTRING(SETTING_rad_doseThreshold_mild), LLSTRING(SETTING_rad_doseThreshold_mild_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 30, 1, 2], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_doseThreshold_moderate), + "SLIDER", + [LLSTRING(SETTING_rad_doseThreshold_moderate), LLSTRING(SETTING_rad_doseThreshold_moderate_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 30, 2, 2], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_doseThreshold_severe), + "SLIDER", + [LLSTRING(SETTING_rad_doseThreshold_severe), LLSTRING(SETTING_rad_doseThreshold_severe_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 30, 4, 2], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_doseThreshold_lethal), + "SLIDER", + [LLSTRING(SETTING_rad_doseThreshold_lethal), LLSTRING(SETTING_rad_doseThreshold_lethal_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 30, 6, 2], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_prodromalDelay), + "TIME", + [LLSTRING(SETTING_rad_prodromalDelay), LLSTRING(SETTING_rad_prodromalDelay_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 3600, 120], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_hemaDelay), + "TIME", + [LLSTRING(SETTING_rad_hemaDelay), LLSTRING(SETTING_rad_hemaDelay_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 7200, 600], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_giDelay), + "TIME", + [LLSTRING(SETTING_rad_giDelay), LLSTRING(SETTING_rad_giDelay_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 7200, 480], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_cnsDelay), + "TIME", + [LLSTRING(SETTING_rad_cnsDelay), LLSTRING(SETTING_rad_cnsDelay_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 3600, 180], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_cardiacDelay), + "TIME", + [LLSTRING(SETTING_rad_cardiacDelay), LLSTRING(SETTING_rad_cardiacDelay_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 3600, 300], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_protectionFactorMask), + "SLIDER", + [LLSTRING(SETTING_rad_protectionFactorMask), LLSTRING(SETTING_rad_protectionFactorMask_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 1, 1, 2], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_protectionFactorCBRN), + "SLIDER", + [LLSTRING(SETTING_rad_protectionFactorCBRN), LLSTRING(SETTING_rad_protectionFactorCBRN_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 1, 1, 2], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_protectionFactorRadGear), + "SLIDER", + [LLSTRING(SETTING_rad_protectionFactorRadGear), LLSTRING(SETTING_rad_protectionFactorRadGear_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 1, 1, 2], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_protectionFactorVehicle), + "SLIDER", + [LLSTRING(SETTING_rad_protectionFactorVehicle), LLSTRING(SETTING_rad_protectionFactorVehicle_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 1, 1, 2], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(availRadProtection), + "EDITBOX", + [LLSTRING(SETTING_availRadProtection), LLSTRING(SETTING_availRadProtection_DISC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + "", + 1, + { + private _array = [_this, "CfgWeapons"] call FUNC(getList); + missionNamespace setVariable [QGVAR(availRadProtectionList), _array, true]; + }, + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_kiFactor), + "SLIDER", + [LLSTRING(SETTING_rad_kiFactor), LLSTRING(SETTING_rad_kiFactor_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 1, 0.5, 2], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_kiDuration), + "TIME", + [LLSTRING(SETTING_rad_kiDuration), LLSTRING(SETTING_rad_kiDuration_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 14400, 3600], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_inhalationFactor), + "SLIDER", + [LLSTRING(SETTING_rad_inhalationFactor), LLSTRING(SETTING_rad_inhalationFactor_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 2, 0.1, 2], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_internalConversionRate), + "SLIDER", + [LLSTRING(SETTING_rad_internalConversionRate), LLSTRING(SETTING_rad_internalConversionRate_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 1, 0.001, 4], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_internalDecayRate), + "SLIDER", + [LLSTRING(SETTING_rad_internalDecayRate), LLSTRING(SETTING_rad_internalDecayRate_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 1, 0.0005, 4], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_chelationDuration), + "TIME", + [LLSTRING(SETTING_rad_chelationDuration), LLSTRING(SETTING_rad_chelationDuration_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 14400, 600], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_chelationFactor), + "SLIDER", + [LLSTRING(SETTING_rad_chelationFactor), LLSTRING(SETTING_rad_chelationFactor_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [1, 50, 5, 1], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_contaminationDeposition), + "SLIDER", + [LLSTRING(SETTING_rad_contaminationDeposition), LLSTRING(SETTING_rad_contaminationDeposition_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 1, 0.02, 3], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_contaminationDecay), + "SLIDER", + [LLSTRING(SETTING_rad_contaminationDecay), LLSTRING(SETTING_rad_contaminationDecay_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 1, 0.002, 4], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_crossContamStrength), + "SLIDER", + [LLSTRING(SETTING_rad_crossContamStrength), LLSTRING(SETTING_rad_crossContamStrength_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 50, 5, 1], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_localProximity), + "SLIDER", + [LLSTRING(SETTING_rad_localProximity), LLSTRING(SETTING_rad_localProximity_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 5, 1.5, 1], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_skinBurnThreshold), + "SLIDER", + [LLSTRING(SETTING_rad_skinBurnThreshold), LLSTRING(SETTING_rad_skinBurnThreshold_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [1, 50, 5, 1], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_marrowAnemiaRate), + "SLIDER", + [LLSTRING(SETTING_rad_marrowAnemiaRate), LLSTRING(SETTING_rad_marrowAnemiaRate_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 20, 2, 1], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_giFluidLossRate), + "SLIDER", + [LLSTRING(SETTING_rad_giFluidLossRate), LLSTRING(SETTING_rad_giFluidLossRate_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 30, 3, 1], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_giAcidosisRate), + "SLIDER", + [LLSTRING(SETTING_rad_giAcidosisRate), LLSTRING(SETTING_rad_giAcidosisRate_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 1, 0.05, 3], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_cnsHypotension), + "SLIDER", + [LLSTRING(SETTING_rad_cnsHypotension), LLSTRING(SETTING_rad_cnsHypotension_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 100, 40, 0], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_feverMax), + "SLIDER", + [LLSTRING(SETTING_rad_feverMax), LLSTRING(SETTING_rad_feverMax_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 5, 2, 1], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_recoveryRate), + "SLIDER", + [LLSTRING(SETTING_rad_recoveryRate), LLSTRING(SETTING_rad_recoveryRate_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 0.5, 0.01, 3], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_visualEffect), + "CHECKBOX", + [LLSTRING(SETTING_rad_visualEffect), LLSTRING(SETTING_rad_visualEffect_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [true], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_infectionEnable), + "CHECKBOX", + [LLSTRING(SETTING_rad_infectionEnable), LLSTRING(SETTING_rad_infectionEnable_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [true], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_infectionChance), + "SLIDER", + [LLSTRING(SETTING_rad_infectionChance), LLSTRING(SETTING_rad_infectionChance_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 1, 0.05, 3], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_infectionSeverityRate), + "SLIDER", + [LLSTRING(SETTING_rad_infectionSeverityRate), LLSTRING(SETTING_rad_infectionSeverityRate_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 0.5, 0.02, 3], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_infectionDamageRate), + "SLIDER", + [LLSTRING(SETTING_rad_infectionDamageRate), LLSTRING(SETTING_rad_infectionDamageRate_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 50, 15, 0], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_antibioticDuration), + "TIME", + [LLSTRING(SETTING_rad_antibioticDuration), LLSTRING(SETTING_rad_antibioticDuration_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 14400, 600], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_antiemeticDuration), + "TIME", + [LLSTRING(SETTING_rad_antiemeticDuration), LLSTRING(SETTING_rad_antiemeticDuration_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 14400, 900], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_filgrastimDuration), + "TIME", + [LLSTRING(SETTING_rad_filgrastimDuration), LLSTRING(SETTING_rad_filgrastimDuration_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 14400, 1800], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_filgrastimFactor), + "SLIDER", + [LLSTRING(SETTING_rad_filgrastimFactor), LLSTRING(SETTING_rad_filgrastimFactor_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [1, 10, 3, 1], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_lethalCurable), + "CHECKBOX", + [LLSTRING(SETTING_rad_lethalCurable), LLSTRING(SETTING_rad_lethalCurable_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [true], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_lethalCollapseTime), + "TIME", + [LLSTRING(SETTING_rad_lethalCollapseTime), LLSTRING(SETTING_rad_lethalCollapseTime_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 600, 150], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_criticalRecoveryRate), + "SLIDER", + [LLSTRING(SETTING_rad_criticalRecoveryRate), LLSTRING(SETTING_rad_criticalRecoveryRate_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 0.1, 0.006, 4], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_marrowRescueDuration), + "TIME", + [LLSTRING(SETTING_rad_marrowRescueDuration), LLSTRING(SETTING_rad_marrowRescueDuration_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 3600, 300], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_recrashChance), + "SLIDER", + [LLSTRING(SETTING_rad_recrashChance), LLSTRING(SETTING_rad_recrashChance_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 1, 0.05, 3], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_shockableChance), + "SLIDER", + [LLSTRING(SETTING_rad_shockableChance), LLSTRING(SETTING_rad_shockableChance_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [0, 1, 0.7, 2], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_stemCellsMedLvl), + "LIST", + [LLSTRING(SETTING_rad_stemCellsMedLvl)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [[0, 1, 2], [ACELSTRING(medical_treatment,Anyone), ACELSTRING(medical_treatment,Medics), ACELSTRING(medical_treatment,Doctors)], 1], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(rad_icReadout), + "CHECKBOX", + [LLSTRING(SETTING_rad_icReadout), LLSTRING(SETTING_rad_icReadout_DESC)], + [CBA_SETTINGS_CAT, LSTRING(SubCategory_Radiation)], + [false], + true +] call CBA_fnc_addSetting; diff --git a/addons/chemical/script_component.hpp b/addons/chemical/script_component.hpp index 93a09c3cc..d76c526cb 100644 --- a/addons/chemical/script_component.hpp +++ b/addons/chemical/script_component.hpp @@ -26,3 +26,10 @@ #define Y_PART(num) (H_PART(num) + (safeZoneY + (safeZoneH - SIZEY) / 2)) #define GAS_MANAGER_PFH_DELAY 1 +#define RAD_MANAGER_PFH_DELAY 1 + +// Radiation body parts (matches ALL_BODY_PARTS index order used for per-limb dose) +#define RAD_BODY_PARTS ["Head", "Body", "LeftArm", "RightArm", "LeftLeg", "RightLeg"] + +// Radiation types (canonical index order for per-type strength/rate arrays) +#define RAD_TYPES ["alpha", "beta", "gamma", "neutron"] diff --git a/addons/chemical/stringtable.xml b/addons/chemical/stringtable.xml index 602fae72a..33a506760 100644 --- a/addons/chemical/stringtable.xml +++ b/addons/chemical/stringtable.xml @@ -589,40 +589,772 @@ Gaz maskesini tak - 1. Protection & Gear - 1. Schutz & Ausrüstung + 01. Protection & Gear + 01. Schutz & Ausrüstung - 2. CS Gas (Level 0) - 2. CS-Gas (Level 0) + 02. CS Gas (Level 0) + 02. CS-Gas (Level 0) - 3. Chlorine (Level 1) - 3. Chlor (Level 1) + 03. Chlorine (Level 1) + 03. Chlor (Level 1) - 4. Phosgene (Level 1) - 4. Phosgen (Level 1) + 04. Phosgene (Level 1) + 04. Phosgen (Level 1) - 5. Mustard Gas (Level 2) - 5. Senfgas (Level 2) + 05. Mustard Gas (Level 2) + 05. Senfgas (Level 2) - 6. Sarin (Level 2) - 6. Sarin (Level 2) + 06. Sarin (Level 2) + 06. Sarin (Level 2) - 7. VX (Level 2) - 7. VX (Level 2) + 07. VX (Level 2) + 07. VX (Level 2) - 8. Contamination & Decontamination - 8. Kontamination & Dekontamination + 08. Contamination & Decontamination + 08. Kontamination & Dekontamination - 9. Identification (Detector & M8 Paper) - 9. dentifikation (Detektor & M8-Papier) + 09. Identification (Detector & M8 Paper) + 09. dentifikation (Detektor & M8-Papier) + + + 10. Radiation + 10. Strahlung + + + Enable radiation + Strahlung aktivieren + + + Master switch for the radiation system (sources, dose, sickness). + Hauptschalter für das Strahlungssystem (Quellen, Dosis, Krankheit). + + + Show radiation sickness hints + Hinweise zur Strahlenkrankheit anzeigen + + + Show on-screen hints (nausea, weakness, etc.) to the affected player. + Bildschirmhinweise (Übelkeit, Schwäche usw.) für den betroffenen Spieler anzeigen. + + + Dose threshold: mild (Gy) + Dosisschwelle: leicht (Gy) + + + Accumulated whole-body dose (Gray) at which mild radiation sickness begins. + Akkumulierte Ganzkörperdosis (Gray), ab der eine leichte Strahlenkrankheit beginnt. + + + Dose threshold: moderate (Gy) + Dosisschwelle: mäßig (Gy) + + + Dose at which the hematopoietic (bone-marrow) syndrome sets in. + Dosis, ab der das hämatopoetische (Knochenmark-) Syndrom einsetzt. + + + Dose threshold: severe (Gy) + Dosisschwelle: schwer (Gy) + + + Dose at which the gastrointestinal syndrome sets in. + Dosis, ab der das gastrointestinale Syndrom einsetzt. + + + Dose threshold: lethal (Gy) + Dosisschwelle: tödlich (Gy) + + + Dose at which the neurovascular/CNS syndrome and cardiac arrest occur. + Dosis, ab der das neurovaskuläre/ZNS-Syndrom und Herzstillstand auftreten. + + + Prodromal onset (s) + Prodromalbeginn (s) + + + Base delay before the prodromal phase (nausea/vomiting). Shorter at higher doses. + Basisverzögerung bis zur Prodromalphase (Übelkeit/Erbrechen). Kürzer bei höheren Dosen. + + + Hematopoietic onset (s) + Hämatopoetischer Beginn (s) + + + Base delay before hematopoietic syndrome onset (marrow suppression). + Basisverzögerung bis zum Beginn des hämatopoetischen Syndroms (Knochenmarksuppression). + + + Gastrointestinal onset (s) + Gastrointestinaler Beginn (s) + + + Base delay before gastrointestinal syndrome onset. + Basisverzögerung bis zum Beginn des gastrointestinalen Syndroms. + + + CNS collapse onset (s) + ZNS-Kollaps-Beginn (s) + + + Base delay before neurovascular/CNS collapse at lethal doses. + Basisverzögerung bis zum neurovaskulären/ZNS-Kollaps bei tödlichen Dosen. + + + Cardiac arrest onset (s) + Herzstillstand-Beginn (s) + + + Base delay before cardiac arrest at lethal doses. + Basisverzögerung bis zum Herzstillstand bei tödlichen Dosen. + + + Shielding: gas mask + Abschirmung: Gasmaske + + + Gas-mask shielding effectiveness (0 = no protection, 1 = full per-type protection). + Wirksamkeit der Gasmasken-Abschirmung (0 = kein Schutz, 1 = voller typabhängiger Schutz). + + + Shielding: CBRN suit + Abschirmung: CBRN-Anzug + + + CBRN-suit shielding effectiveness (0 = no protection, 1 = full per-type protection). + Wirksamkeit der CBRN-Anzug-Abschirmung (0 = kein Schutz, 1 = voller typabhängiger Schutz). + + + Shielding: radiation gear + Abschirmung: Strahlenschutzausrüstung + + + Radiation-gear shielding effectiveness (0 = no protection, 1 = full per-type protection). + Wirksamkeit der Strahlenschutzausrüstung (0 = kein Schutz, 1 = voller typabhängiger Schutz). + + + Shielding: vehicle + Abschirmung: Fahrzeug + + + Vehicle shielding effectiveness (0 = no protection, 1 = full per-type protection). + Wirksamkeit der Fahrzeug-Abschirmung (0 = kein Schutz, 1 = voller typabhängiger Schutz). + + + Radiation-protective uniforms + Strahlenschutz-Uniformen + + + Comma-separated uniform classnames that count as dedicated radiation protection. + Kommagetrennte Uniform-Klassennamen, die als spezieller Strahlenschutz gelten. + + + Potassium iodide protection factor + Kaliumiodid-Schutzfaktor + + + Absorbed-dose multiplier during the potassium-iodide protective window. + Dosismultiplikator während des Kaliumiodid-Schutzfensters. + + + Dosimeter + Dosimeter + + + Personal radiation dosimeter. Worn in the watch slot; shows dose-rate and accumulated dose. + Persönliches Strahlungsdosimeter. Im Uhrenslot getragen; zeigt Dosisleistung und akkumulierte Dosis. + + + DOSIMETER + DOSIMETER + + + Dosimeter + Dosimeter + + + Show Dosimeter + Dosimeter anzeigen + + + Enable Dosimeter + Dosimeter aktivieren + + + Disable Dosimeter + Dosimeter deaktivieren + + + Enable dosimeter sound + Dosimeter-Ton aktivieren + + + Disable dosimeter sound + Dosimeter-Ton deaktivieren + + + Radiation Source + Strahlungsquelle + + + Radius of the radiation field in meters. + Radius des Strahlungsfeldes in Metern. + + + Dose-rate in Gray per hour at the reference point (centre for zones, 1 m for point sources). + Dosisleistung in Gray pro Stunde am Referenzpunkt (Zentrum bei Zonen, 1 m bei Punktquellen). + + + Point source + Punktquelle + + + If enabled, dose falls off with the inverse-square law (a hot point) instead of linearly (an area). + Wenn aktiviert, fällt die Dosis nach dem Abstandsquadratgesetz ab (heißer Punkt) statt linear (Fläche). + + + Creates a radiation source. Sync a LocationArea for a zone, or enable Point source for a hot spot. + Erzeugt eine Strahlungsquelle. Synchronisiere ein LocationArea für eine Zone oder aktiviere Punktquelle für einen Hotspot. + + + You feel nauseous and start to vomit. + Dir ist übel und du beginnst zu erbrechen. + + + You feel weak and feverish. + Du fühlst dich schwach und fiebrig. + + + Severe cramps and vomiting wrack your body. + Schwere Krämpfe und Erbrechen schütteln deinen Körper. + + + Potassium Iodide (KI) + Kaliumiodid (KI) + + + Prophylactic anti-radiation tablets. Taken before/early exposure to reduce radionuclide uptake. + Prophylaktische Anti-Strahlungs-Tabletten. Vor/früh bei Exposition eingenommen, um die Aufnahme von Radionukliden zu verringern. + + + Prussian Blue + Berliner Blau + + + Chelation agent. Speeds elimination of internalised radionuclides (internal burden). + Chelatbildner. Beschleunigt die Ausscheidung internalisierter Radionuklide (innere Belastung). + + + Radioactive Source + Radioaktive Quelle + + + Pick up radioactive source + Radioaktive Quelle aufnehmen + + + Drop radioactive source + Radioaktive Quelle ablegen + + + Take Potassium Iodide + Kaliumiodid einnehmen + + + Taking Potassium Iodide... + Nehme Kaliumiodid ein... + + + Administer Prussian Blue + Berliner Blau verabreichen + + + Administering Prussian Blue... + Verabreiche Berliner Blau... + + + Antibiotics + Antibiotika + + + Broad-spectrum antibiotics. Fights radiation-induced wound infection while the immune system is suppressed. + Breitbandantibiotika. Bekämpfen strahlenbedingte Wundinfektionen, solange das Immunsystem unterdrückt ist. + + + Filgrastim (G-CSF) + Filgrastim (G-CSF) + + + Granulocyte colony-stimulating factor. Speeds bone-marrow recovery after radiation exposure. + Granulozyten-Kolonie-stimulierender Faktor. Beschleunigt die Knochenmarkserholung nach Strahlenexposition. + + + Antiemetic + Antiemetikum + + + Anti-nausea medication. Suppresses radiation-sickness vomiting for a time. + Mittel gegen Übelkeit. Unterdrückt das Erbrechen bei Strahlenkrankheit für eine Weile. + + + Administer Antibiotics + Antibiotika verabreichen + + + Administering Antibiotics... + Verabreiche Antibiotika... + + + Administer Filgrastim + Filgrastim verabreichen + + + Administering Filgrastim... + Verabreiche Filgrastim... + + + Administer Antiemetic + Antiemetikum verabreichen + + + Administering Antiemetic... + Verabreiche Antiemetikum... + + + Estimate Radiation Dose + Strahlendosis abschätzen + + + Assessing radiation exposure... + Beurteile Strahlenexposition... + + + Radiation Survey + Strahlungsmessung + + + Surveying for radiation... + Messe Strahlung... + + + Estimated absorbed dose: %1 Gy + Geschätzte absorbierte Dosis: %1 Gy + + + Prognosis: no acute radiation syndrome expected. + Prognose: keine akute Strahlenkrankheit zu erwarten. + + + Prognosis: mild ARS - good with supportive care. + Prognose: leichte Strahlenkrankheit - gut mit unterstützender Behandlung. + + + Prognosis: moderate ARS (hematopoietic) - survivable with care. + Prognose: mittelschwere Strahlenkrankheit (hämatopoetisch) - mit Behandlung überlebbar. + + + Prognosis: severe ARS - guarded; intensive care required. + Prognose: schwere Strahlenkrankheit - ernst; Intensivbehandlung erforderlich. + + + Prognosis: likely lethal without intensive treatment. + Prognose: ohne Intensivbehandlung wahrscheinlich tödlich. + + + No emesis recorded. + Kein Erbrechen verzeichnet. + + + Emesis recorded ~%1 min ago. + Erbrechen vor ~%1 Min. verzeichnet. + + + Surface contamination: %1% + Oberflächenkontamination: %1% + + + Ambient dose rate: %1 Gy/h + Umgebungsdosisleistung: %1 Gy/h + + + Dominant type: %1 + Dominanter Typ: %1 + + + none + keiner + + + Stem-Cell / Marrow Rescue + Stammzellen / Knochenmark-Rettung + + + Haematopoietic stem-cell transplant. The pivotal treatment that lets a lethally-irradiated casualty's marrow recover during sustained intensive care. + Hämatopoetische Stammzelltransplantation. Die entscheidende Behandlung, die das Knochenmark eines tödlich bestrahlten Patienten unter anhaltender Intensivpflege erholen lässt. + + + Administer Stem-Cell Rescue + Stammzell-Rettung verabreichen + + + Administering stem-cell transplant... + Verabreiche Stammzelltransplantation... + + + Preset + Vorlage + + + Source profile. Non-Custom presets fill the per-type strengths; Custom uses the four fields below. + Quellenprofil. Nicht-benutzerdefinierte Vorlagen füllen die typabhängigen Stärken; Benutzerdefiniert nutzt die vier Felder unten. + + + Alpha (Gy/h) + Alpha (Gy/h) + + + Beta (Gy/h) + Beta (Gy/h) + + + Gamma (Gy/h) + Gamma (Gy/h) + + + Neutron (Gy/h) + Neutron (Gy/h) + + + Custom + Benutzerdefiniert + + + Cobalt-60 (gamma) + Cobalt-60 (Gamma) + + + Reactor (gamma + neutron) + Reaktor (Gamma + Neutron) + + + Fallout (beta + gamma) + Fallout (Beta + Gamma) + + + Alpha emitter + Alpha-Strahler + + + Dirty bomb (alpha + beta + gamma) + Schmutzige Bombe (Alpha + Beta + Gamma) + + + Potassium iodide duration (s) + Kaliumiodid-Dauer (s) + + + How long the potassium-iodide uptake-reduction window lasts. + Wie lange das Kaliumiodid-Aufnahmereduktionsfenster anhält. + + + Inhalation factor + Inhalationsfaktor + + + Scales how much airborne radioactivity becomes internal burden when no gas mask is worn. + Skaliert, wie viel luftgetragene Radioaktivität ohne Gasmaske zur inneren Belastung wird. + + + Internal dose conversion rate + Interne Dosis-Umwandlungsrate + + + Fraction of internal burden delivered as committed whole-body dose each second. + Anteil der inneren Belastung, der pro Sekunde als festgelegte Ganzkörperdosis abgegeben wird. + + + Internal burden elimination rate + Ausscheidungsrate der inneren Belastung + + + Biological elimination of internal burden per second (chelation multiplies this). + Biologische Ausscheidung der inneren Belastung pro Sekunde (Chelattherapie vervielfacht dies). + + + Chelation duration (s) + Chelat-Dauer (s) + + + How long a Prussian blue chelation window accelerates internal-burden elimination. + Wie lange ein Berliner-Blau-Chelatfenster die Ausscheidung der inneren Belastung beschleunigt. + + + Chelation speed multiplier + Chelat-Geschwindigkeitsmultiplikator + + + How much faster internal burden is eliminated while a chelation window is active. + Wie viel schneller die innere Belastung während eines Chelatfensters ausgeschieden wird. + + + Contamination deposition rate + Kontaminations-Ablagerungsrate + + + How quickly surface contamination builds up while exposed to particulate radiation. + Wie schnell sich Oberflächenkontamination bei Exposition gegenüber Partikelstrahlung aufbaut. + + + Contamination weathering rate + Kontaminations-Verwitterungsrate + + + How quickly surface contamination weathers away on its own per second. + Wie schnell Oberflächenkontamination pro Sekunde von selbst verwittert. + + + Cross-contamination strength (Gy/h) + Kreuzkontaminations-Stärke (Gy/h) + + + Dose-rate emitted by a fully contaminated person (doses themselves and nearby people). + Dosisleistung einer vollständig kontaminierten Person (bestrahlt sich selbst und Personen in der Nähe). + + + Local exposure distance (m) + Lokale Expositionsdistanz (m) + + + Within this distance of a point source, skin dose concentrates on the arms/hands (handling burns). + Innerhalb dieser Distanz zu einer Punktquelle konzentriert sich die Hautdosis auf Arme/Hände (Handhabungsverbrennungen). + + + Skin burn threshold (Gy) + Hautverbrennungsschwelle (Gy) + + + Local skin dose per radiation burn wound applied to a body part. + Lokale Hautdosis pro Strahlenverbrennungswunde, die auf ein Körperteil angewendet wird. + + + Anemia rate (ml/s) + Anämie-Rate (ml/s) + + + Blood-volume loss per second from marrow suppression, scaled by sickness severity. Models progressive anemia at moderate+ tiers. + Blutvolumenverlust pro Sekunde durch Knochenmarkssuppression, skaliert mit der Schwere der Krankheit. Modelliert fortschreitende Anämie ab mittlerer Stufe. + + + GI fluid loss (ml/s) + GI-Flüssigkeitsverlust (ml/s) + + + Blood-volume loss per second from gastrointestinal syndrome (dehydration) at severe+ tiers. + Blutvolumenverlust pro Sekunde durch das gastrointestinale Syndrom (Dehydrierung) ab schwerer Stufe. + + + GI acidosis rate + GI-Azidose-Rate + + + Per-second drop in blood-gas bicarbonate/pH (metabolic acidosis) at severe+ tiers. Requires the Breathing system enabled. + Sekündlicher Abfall von Bikarbonat/pH im Blutgas (metabolische Azidose) ab schwerer Stufe. Erfordert aktiviertes Atmungssystem. + + + CNS hypotension (mmHg) + ZNS-Hypotonie (mmHg) + + + Maximum blood-pressure drop at the lethal/neurovascular tier. Requires the Circulation system enabled. + Maximaler Blutdruckabfall in der tödlichen/neurovaskulären Stufe. Erfordert aktiviertes Kreislaufsystem. + + + Maximum fever (°C) + Maximales Fieber (°C) + + + Maximum body-temperature rise from radiation sickness. Requires the Hypothermia system enabled. + Maximaler Anstieg der Körpertemperatur durch Strahlenkrankheit. Erfordert aktiviertes Hypothermie-System. + + + Recovery rate (Gy/s) + Erholungsrate (Gy/s) + + + How fast sickness severity heals per second once out of radiation (below the lethal tier). The lethal tier does not self-recover. + Wie schnell die Krankheitsschwere pro Sekunde abheilt, sobald keine Strahlung mehr wirkt (unterhalb der tödlichen Stufe). Die tödliche Stufe erholt sich nicht von selbst. + + + Radiation visual effect + Strahlungs-Bildschirmeffekt + + + Show a desaturated screen effect while irradiated/sick (client-side). + Zeigt einen entsättigten Bildschirmeffekt während Bestrahlung/Krankheit (clientseitig). + + + Enable wound infection + Wundinfektion aktivieren + + + Immunosuppressed casualties with open/bandaged wounds can develop infection that can progress to lethal sepsis. Treated with antibiotics. + Immungeschwächte Verwundete mit offenen/verbundenen Wunden können eine Infektion entwickeln, die zur tödlichen Sepsis fortschreiten kann. Behandlung mit Antibiotika. + + + Infection chance + Infektionswahrscheinlichkeit + + + Per-second base chance of a wound becoming infected, scaled by how suppressed the immune system is. + Sekündliche Grundwahrscheinlichkeit, dass sich eine Wunde infiziert, skaliert mit dem Grad der Immunsuppression. + + + Infection progression rate + Infektions-Fortschrittsrate + + + How fast an untreated infection worsens per second while the immune system is suppressed. + Wie schnell sich eine unbehandelte Infektion pro Sekunde verschlimmert, solange das Immunsystem unterdrückt ist. + + + Sepsis blood loss (ml/s) + Sepsis-Blutverlust (ml/s) + + + Blood-volume loss per second at full infection (scales with infection severity squared). Drives lethal septic shock if untreated. + Blutvolumenverlust pro Sekunde bei voller Infektion (skaliert quadratisch mit der Infektionsschwere). Führt unbehandelt zum tödlichen septischen Schock. + + + Antibiotic duration + Antibiotika-Wirkdauer + + + How long a dose of antibiotics suppresses infection. + Wie lange eine Dosis Antibiotika eine Infektion unterdrückt. + + + Antiemetic duration + Antiemetikum-Wirkdauer + + + How long an antiemetic dose suppresses radiation-sickness vomiting. + Wie lange eine Antiemetikum-Dosis das Erbrechen bei Strahlenkrankheit unterdrückt. + + + Filgrastim duration + Filgrastim-Wirkdauer + + + How long filgrastim accelerates sickness recovery. + Wie lange Filgrastim die Genesung von der Krankheit beschleunigt. + + + Filgrastim recovery multiplier + Filgrastim-Genesungsmultiplikator + + + How much faster sickness severity recovers while filgrastim is active. + Wie viel schneller sich die Krankheitsschwere erholt, solange Filgrastim wirkt. + + + Lethal dose curable + Tödliche Dosis heilbar + + + If enabled, a lethal-tier casualty can be saved through sustained intensive care (life support + stem-cell rescue + the full drug stack over ~15 min). If disabled, the lethal tier is terminal. + Wenn aktiviert, kann ein Patient der tödlichen Stufe durch anhaltende Intensivpflege gerettet werden (Lebenserhaltung + Stammzell-Rettung + voller Medikamenten-Stack über ~15 Min). Wenn deaktiviert, ist die tödliche Stufe terminal. + + + Collapse time (unsupported) + Kollapszeit (ohne Unterstützung) + + + How long a critical casualty survives without circulatory support (IV or vasopressor) before dropping into cardiac arrest. + Wie lange ein kritischer Patient ohne Kreislaufunterstützung (IV oder Vasopressor) überlebt, bevor er in den Herzstillstand fällt. + + + Intensive-care recovery rate (Gy/s) + Intensivpflege-Erholungsrate (Gy/s) + + + How fast a lethal casualty's sickness clears while the full intensive-care stack is sustained. Lower = longer, harder recovery. + Wie schnell die Krankheit eines tödlich Verletzten abklingt, solange der volle Intensivpflege-Stack aufrechterhalten wird. Niedriger = längere, schwerere Genesung. + + + Stem-cell rescue duration + Stammzell-Rettung Wirkdauer + + + How long one stem-cell dose enables intensive-care recovery before it must be re-administered. + Wie lange eine Stammzelldosis die Intensivpflege-Genesung ermöglicht, bevor sie erneut verabreicht werden muss. + + + Re-crash chance + Rückfall-Wahrscheinlichkeit + + + Per-tick chance (at full severity) that an undertreated critical casualty spontaneously crashes back into cardiac arrest. Tapers as the cure progresses; halved while on life support. + Wahrscheinlichkeit pro Tick (bei voller Schwere), dass ein unterversorgter kritischer Patient spontan in den Herzstillstand zurückfällt. Nimmt mit dem Behandlungsfortschritt ab; halbiert unter Lebenserhaltung. + + + Shockable rhythm bias + Schockbare-Rhythmus-Neigung + + + Chance (at full severity, with Advanced Rhythm on) that a radiation-driven cardiac arrest is VF/VT rather than asystole/PEA. Tapers as the casualty recovers. + Wahrscheinlichkeit (bei voller Schwere, mit aktiviertem erweitertem Rhythmus), dass ein strahlenbedingter Herzstillstand Kammerflimmern/-tachykardie statt Asystolie/PEA ist. Nimmt mit der Genesung ab. + + + Stem-cell rescue required trait + Stammzell-Rettung benötigte Qualifikation + + + Intensive-care readout + Intensivpflege-Anzeige + + + Show a radiation intensive-care status line in the medical menu for a critical casualty (cure progress + which supports are missing). Does not show the time-to-arrest. + Zeigt im Sanitätsmenü eine Statuszeile zur Strahlungs-Intensivpflege für einen kritischen Patienten (Behandlungsfortschritt + fehlende Unterstützung). Zeigt nicht die Zeit bis zum Herzstillstand. + + + Acute radiation - CRITICAL + Akute Strahlung - KRITISCH + + + Intensive care: %1% + Intensivpflege: %1% + + + Needs: %1 + Benötigt: %1 + + + circulatory support + Kreislaufunterstützung + + + filgrastim + Filgrastim + + + antibiotics + Antibiotika + + + stem-cell rescue + Stammzell-Rettung + + + decontamination + Dekontamination Accepted gas masks @@ -1371,5 +2103,21 @@ Major Chemical Burn Schwere chemische Verätzung + + Radiation Burn + Strahlenverbrennung + + + Minor Radiation Burn + Leichte Strahlenverbrennung + + + Medium Radiation Burn + Mittlere Strahlenverbrennung + + + Major Radiation Burn + Schwere Strahlenverbrennung + diff --git a/addons/chemical/ui/RscAttributes.hpp b/addons/chemical/ui/RscAttributes.hpp index 65478c0cd..efcb1ff43 100644 --- a/addons/chemical/ui/RscAttributes.hpp +++ b/addons/chemical/ui/RscAttributes.hpp @@ -125,3 +125,129 @@ class GVAR(kat_RscGasModul): RscDisplayAttributes { class ButtonCancel: ButtonCancel {}; }; }; + +class GVAR(kat_RscAttributeRadModule): RscControlsGroupNoScrollbars { + onSetFocus = QUOTE(_this call FUNC(AttributeRadModule)); + idc = 26423; + x = 0; + y = 0; + w = QUOTE(W_PART(26)); + h = QUOTE(H_PART(8)); + class controls { + class Title1: RscText { + idc = 16110; + text = CSTRING(UI_max_range); + toolTip = CSTRING(RadModule_max_radius_dcs); + x = 0; + y = 0; + w = QUOTE(W_PART(10)); + h = QUOTE(H_PART(1)); + colorBackground[] = {0,0,0,0.5}; + }; + class radius_max: RscEdit { + idc = 1621; + x = QUOTE(W_PART(10.1)); + y = 0; + w = QUOTE(W_PART(15.9)); + h = QUOTE(H_PART(1)); + }; + class Title2: Title1 { + idc = -1; + text = CSTRING(RadModule_preset); + toolTip = CSTRING(RadModule_preset_dcs); + y = QUOTE(H_PART(1.1)); + }; + class preset_combo: RscCombo { + idc = 1624; + x = QUOTE(W_PART(10.1)); + y = QUOTE(H_PART(1.1)); + w = QUOTE(W_PART(15.9)); + h = QUOTE(H_PART(1)); + colorBackground[] = {0, 0, 0, 0.7}; + }; + class Title3: Title1 { + idc = -1; + text = CSTRING(RadModule_alpha); + toolTip = CSTRING(RadModule_strength_dcs); + y = QUOTE(H_PART(2.2)); + }; + class alpha_edit: RscEdit { + idc = 1625; + x = QUOTE(W_PART(10.1)); + y = QUOTE(H_PART(2.2)); + w = QUOTE(W_PART(15.9)); + h = QUOTE(H_PART(1)); + }; + class Title4: Title1 { + idc = -1; + text = CSTRING(RadModule_beta); + toolTip = CSTRING(RadModule_strength_dcs); + y = QUOTE(H_PART(3.3)); + }; + class beta_edit: RscEdit { + idc = 1626; + x = QUOTE(W_PART(10.1)); + y = QUOTE(H_PART(3.3)); + w = QUOTE(W_PART(15.9)); + h = QUOTE(H_PART(1)); + }; + class Title5: Title1 { + idc = -1; + text = CSTRING(RadModule_gamma); + toolTip = CSTRING(RadModule_strength_dcs); + y = QUOTE(H_PART(4.4)); + }; + class gamma_edit: RscEdit { + idc = 1627; + x = QUOTE(W_PART(10.1)); + y = QUOTE(H_PART(4.4)); + w = QUOTE(W_PART(15.9)); + h = QUOTE(H_PART(1)); + }; + class Title6: Title1 { + idc = -1; + text = CSTRING(RadModule_neutron); + toolTip = CSTRING(RadModule_strength_dcs); + y = QUOTE(H_PART(5.5)); + }; + class neutron_edit: RscEdit { + idc = 1628; + x = QUOTE(W_PART(10.1)); + y = QUOTE(H_PART(5.5)); + w = QUOTE(W_PART(15.9)); + h = QUOTE(H_PART(1)); + }; + class Title7: Title1 { + idc = -1; + text = CSTRING(RadModule_pointSource); + toolTip = CSTRING(RadModule_pointSource_dcs); + y = QUOTE(H_PART(6.6)); + }; + class pointSource_check: RscCheckBox { + idc = 1623; + x = QUOTE(W_PART(10.1)); + y = QUOTE(H_PART(6.6)); + w = QUOTE(W_PART(1)); + h = QUOTE(H_PART(1)); + }; + }; +}; + +class GVAR(kat_RscRadModul): RscDisplayAttributes { + onLoad = QUOTE([ARR_3('onLoad',_this,QQGVAR(kat_RscRadModul))] call EFUNC(zeus,zeusAttributes)); + onUnload = QUOTE([ARR_3('onUnload',_this,QQGVAR(kat_RscRadModul))] call EFUNC(zeus,zeusAttributes)); + + class Controls: Controls { + class Background: Background {}; + class Title: Title {}; + class Content: Content { + class Controls { + class radius: GVAR(kat_RscAttributeRadModule) {}; + }; + }; + class ButtonOK: ButtonOK { + onSetFocus = QUOTE(_this call FUNC(ui_radModule)); + }; + class ButtonCancel: ButtonCancel {}; + }; +}; diff --git a/addons/chemical/ui/kat_potassiumIodide.paa b/addons/chemical/ui/kat_potassiumIodide.paa new file mode 100644 index 000000000..d54f3fb40 Binary files /dev/null and b/addons/chemical/ui/kat_potassiumIodide.paa differ diff --git a/addons/chemical/ui/kat_prussianBlue.paa b/addons/chemical/ui/kat_prussianBlue.paa new file mode 100644 index 000000000..e3a26adaa Binary files /dev/null and b/addons/chemical/ui/kat_prussianBlue.paa differ diff --git a/addons/circulation/functions/fnc_getBloodPressure.sqf b/addons/circulation/functions/fnc_getBloodPressure.sqf index 6b651ffdb..9bbf082bd 100644 --- a/addons/circulation/functions/fnc_getBloodPressure.sqf +++ b/addons/circulation/functions/fnc_getBloodPressure.sqf @@ -44,4 +44,6 @@ if (count _BPChange > 0) then { private _systolic = _bloodPressure * MODIFIER_BP_LOW; private _diastolic = _bloodPressure * MODIFIER_BP_HIGH; -[(round(_systolic + _changeSystolic * (_systolic / 80)) max 0), (round(_diastolic + _changeDiastolic * (_diastolic / 120)) max 0)] +private _radBPDrop = _unit getVariable [QEGVAR(chemical,radBPDrop), 0]; + +[((round(_systolic + _changeSystolic * (_systolic / 80)) - _radBPDrop) max 0), ((round(_diastolic + _changeDiastolic * (_diastolic / 120)) - _radBPDrop) max 0)] diff --git a/addons/feedback/XEH_PREP.hpp b/addons/feedback/XEH_PREP.hpp index 8a4998531..8e97ab59e 100644 --- a/addons/feedback/XEH_PREP.hpp +++ b/addons/feedback/XEH_PREP.hpp @@ -5,6 +5,7 @@ PREP(effectEyeInjury); PREP(effectHurtEye); PREP(effectLowSpO2); PREP(effectOpioid); +PREP(effectRadiation); PREP(effectTearHaze); PREP(handleEffects); PREP(initEffects); diff --git a/addons/feedback/functions/fnc_effectRadiation.sqf b/addons/feedback/functions/fnc_effectRadiation.sqf new file mode 100644 index 000000000..fb4be871b --- /dev/null +++ b/addons/feedback/functions/fnc_effectRadiation.sqf @@ -0,0 +1,33 @@ +#include "..\script_component.hpp" +/* + * Author: DiGii + * Triggers the radiation-sickness visual effect: a desaturated, sickly grade + * that deepens with intensity. Driven by the radiation physiology tick from the + * unit's sickness tier / dose-rate. Client-local. + * + * Arguments: + * 0: Enable + * 1: Intensity (0..1) + * + * Return Value: + * None + * + * Example: + * [true, 0.5] call kat_feedback_fnc_effectRadiation; + * + * Public: No + */ + +params ["_enable", "_intensity"]; + +if ((!_enable) || {_intensity <= 0}) exitWith { + if (GVAR(radiationEffect) != -1) then { GVAR(radiationEffect) ppEffectEnable false; }; +}; + +if (GVAR(radiationEffect) != -1) then { GVAR(radiationEffect) ppEffectEnable true; }; + +private _sat = 1 - (0.55 * _intensity); +private _tint = 0.4 * _intensity; + +GVAR(radiationEffect) ppEffectAdjust [1, 1, _sat, [0.25, 0.4, 0.15, _tint], [0, 0, 0, 1], [0.33, 0.33, 0.33, 0], [0.55, 0.5, 0, 0, 0, 0, 4]]; +GVAR(radiationEffect) ppEffectCommit 1; diff --git a/addons/feedback/functions/fnc_initEffects.sqf b/addons/feedback/functions/fnc_initEffects.sqf index 2f424ca75..07b384746 100644 --- a/addons/feedback/functions/fnc_initEffects.sqf +++ b/addons/feedback/functions/fnc_initEffects.sqf @@ -68,3 +68,10 @@ GVAR(ppBlurBlink) = [ 213706, [1] ] call _fnc_createEffect; + +// - Radiation sickness --------------------------------------------------- +GVAR(radiationEffect) = [ + "ColorCorrections", + 213707, + [1, 1, 1, [0, 0, 0, 0], [1, 1, 1, 1], [0.3, 0.45, 0.2, 0], [0, 0, 0, 0, 0, 0, 0]] +] call _fnc_createEffect; diff --git a/addons/pharma/functions/fnc_coagRegen.sqf b/addons/pharma/functions/fnc_coagRegen.sqf index 666df4cb2..26a9155bb 100644 --- a/addons/pharma/functions/fnc_coagRegen.sqf +++ b/addons/pharma/functions/fnc_coagRegen.sqf @@ -38,7 +38,7 @@ if !(GVAR(coagulation)) exitWith {}; private _currentCoagFactors = _unit getVariable [QGVAR(coagulationFactor), 30]; private _savedCoagFactors = _unit getVariable [QGVAR(coagulationSavedFactors), (_unit getVariable [QGVAR(coagulationFactor), 30])]; - private _limitRegenCoagFactors = missionNamespace getVariable [QGVAR(coagulation_factor_count), 30]; + private _limitRegenCoagFactors = (missionNamespace getVariable [QGVAR(coagulation_factor_count), 30]) * (_unit getVariable [QEGVAR(chemical,radMarrowFactor), 1]); private _cooldownON = _unit getVariable [QGVAR(coagulationRegenCooldown), false]; private _countTXA = ([_unit, "TXA"] call ACEFUNC(medical_status,getMedicationCount)) select 1; private _countEACA = ([_unit, "EACA"] call ACEFUNC(medical_status,getMedicationCount)) select 1; diff --git a/addons/pharma/functions/fnc_getBloodVolumeChange.sqf b/addons/pharma/functions/fnc_getBloodVolumeChange.sqf index ad21e6d65..6304edc4a 100644 --- a/addons/pharma/functions/fnc_getBloodVolumeChange.sqf +++ b/addons/pharma/functions/fnc_getBloodVolumeChange.sqf @@ -142,7 +142,7 @@ if (_enableFluidShift) then { if (_defaultShift) then { _ISP = _ISP + ((((DEFAULT_ISP - _ISP) max -2) min 2) *_deltaT); - _SRBC = _SRBC + ((((DEFAULT_SRBC - _SRBC) max -1) min 1) * _deltaT); + _SRBC = _SRBC + ((((DEFAULT_SRBC - _SRBC) max -1) min 1) * _deltaT * (_unit getVariable [QEGVAR(chemical,radMarrowFactor), 1])); }; }; diff --git a/addons/vitals/functions/fnc_handleTemperatureFunction.sqf b/addons/vitals/functions/fnc_handleTemperatureFunction.sqf index 5163f23e7..fc8fa7a0e 100644 --- a/addons/vitals/functions/fnc_handleTemperatureFunction.sqf +++ b/addons/vitals/functions/fnc_handleTemperatureFunction.sqf @@ -31,7 +31,7 @@ private _warmingImpact = (_unit getVariable [QEGVAR(hypothermia,warmingImpact), private _pointTemperature = linearConversion [0, 40, (-3.5 * (0.95 ^ _mapTemperature + _altitudeAdjustment)), 12, -9, true]; private _initialBodyTemperature = DEFAULT_TEMPERATURE min (((-0.3392 * (_bloodVolume^2)) + (6.00357 * _bloodVolume) + 13.3)); -private _currentTemperature = _initialBodyTemperature + _warmingImpact - (_pointTemperature / _bloodVolume); +private _currentTemperature = _initialBodyTemperature + _warmingImpact - (_pointTemperature / _bloodVolume) + (_unit getVariable [QEGVAR(chemical,radFever), 0]); _unit setVariable [QEGVAR(hypothermia,unitTemperature), _currentTemperature, _syncValue]; diff --git a/docs/de/Radiation/01_Info_and_QuickStart.md b/docs/de/Radiation/01_Info_and_QuickStart.md new file mode 100644 index 000000000..39670cf1f --- /dev/null +++ b/docs/de/Radiation/01_Info_and_QuickStart.md @@ -0,0 +1,51 @@ +# Radiation — Player & Mission-Maker Guide + +The **Radiation** system is an extension of the **Chemical** addon — the "R" and "N" in CBRN that the gases left on the table. It lives in the same addon, shares the same CBA settings category, and reuses the same decontamination kit and CBRN gear, so if you've already read the [Chemical guide](../Chemical/01_Info_and_QuickStart.md) a lot of this will feel familiar. If you haven't, the short version is: this mod treats hazards as things you prepare for, not things that simply tick your health down. + +Where the gases are about a cloud you can usually *see* and an antidote you carry, radiation is quieter and slower. You can't smell it, a mask won't stop most of it, and the dose you soak up today can put you in the ground a quarter of an hour from now with nothing visibly wrong in between. The only way to know what you're standing in is to carry a dosimeter and pay attention to it. + +This guide is written for two audiences: + +- **Players / medics** — what the four radiation types do, how to shield against them, and how to treat radiation casualties. +- **Mission makers / Zeus** — how to place radiation sources and how to tune the whole thing through CBA settings. + +> **A note on units.** Dose is measured in **Gray (Gy)**, the real SI unit of absorbed radiation. As a rough yardstick: a couple of Gy makes you sick, around 4 Gy is a coin-flip for survival without treatment, and 6 Gy and up is the danger zone. The defaults are built around those numbers but every threshold is configurable. + +--- + +## How dose works (the one concept to understand) + +There are three different numbers in play, and confusing them is the single most common mistake: + +- **Dose rate** — how *hot* the spot you're standing in is, in **Gy/h**. This is what your dosimeter's geiger reads. It measures the field around you; it does **not** care what you're wearing. +- **Accumulated dose** — how much radiation your body has actually *absorbed*, in **Gy**. This is what makes you sick, and **this** is what your shielding reduces. It only ever goes up while you're exposed, and it's permanent. +- **Internal contamination** — radioactive material you've **breathed in**. It sits inside you and keeps delivering dose for a long time after you've left the area. Washing it off does nothing; it has to be chelated out or wait out your body clearing it. + +So: the geiger screaming doesn't mean you're being hurt (your suit might be eating it), and the geiger going quiet doesn't mean you're safe (you might be carrying contamination inside you). Watch the *accumulated* dose, not just the rate. + +--- + +## Quick Start + +If you only read one section, read this one. + +1. **Carry a dosimeter.** The `KAT_Dosimeter` (watch slot) is your only way to see dose rate and accumulated dose. Turn it on, turn the sound on, and let the clicks warn you before the numbers do. +2. **Shielding depends on the type.** There's no single "rad suit." A gas mask matters for alpha (inhalation) and helps against beta; a full CBRN suit stops beta and dents gamma; vehicles and terrain are what cut gamma and neutron. Distance is always your friend. +3. **Dose is cumulative — manage your time.** You can't "heal" the radiation you've already absorbed by leaving. Treat a hot zone like a budget: get in, do the job, get out before the accumulated dose climbs into the danger tiers. +4. **Two kinds of contamination, two different cures.** Surface contamination (on your skin and gear) comes off with the **Decontamination Kit**. Internal contamination (breathed in) does **not** — it needs **Prussian Blue** chelation. Decon and chelation are not interchangeable. +5. **Prepare with KI, treat with supportive care.** Potassium iodide (**KI**) taken *before* exposure reduces uptake. After a serious dose, casualties need real medical care — IV fluids and blood for the anemia and dehydration, antibiotics if wounds get infected, and time. +6. **A lethal dose is lethal.** Below the top tier, radiation sickness is survivable and recovers slowly on its own. At the lethal tier it will not — that casualty needs to never have been there. + +--- + +## Where to go next + +- [Radiation types & dose](02_radiation_types_and_dose.md) — alpha, beta, gamma, neutron, and the three ways they dose you. +- [Protection & shielding](03_protection_and_shielding.md) — what actually stops what. +- [Radiation sickness](04_radiation_sickness.md) — what a dose does to the body over time. +- [Detection & items](05_detection_and_items.md) — the dosimeter and the full kit list. +- [Treatment & triage](06_treatment_and_triage.md) — decon, chelation, drugs, and a triage flow. +- [Zeus & mission makers](07_zeus_and_MissionMakers.md) — placing sources and every CBA setting. +- [FAQ & troubleshooting](08_faq_and_troubleshooting.md) — the gotchas. + +--- diff --git a/docs/de/Radiation/02_radiation_types_and_dose.md b/docs/de/Radiation/02_radiation_types_and_dose.md new file mode 100644 index 000000000..e27f149e1 --- /dev/null +++ b/docs/de/Radiation/02_radiation_types_and_dose.md @@ -0,0 +1,86 @@ +# Radiation Types & Dose + +Radiation isn't one thing. The system models **four types**, and the type decides almost everything that matters: what stops it, how it hurts you, and whether you even need to worry about it from across the room. A source can emit any mix of the four — a reactor leak is mostly gamma and neutron, fallout is beta and gamma, a dirty bomb is a bit of everything. + +## The four types at a glance + +| Type | Penetration | What stops it | Main threat | Skin burns? | +|------|-------------|---------------|-------------|-------------| +| **Alpha** | Almost none | Skin, clothing, a gas mask | **Inhalation only** — harmless outside, lethal inside | No (minor) | +| **Beta** | Low | A CBRN suit; heavy cover | Skin/surface burns + light whole-body | **Yes** | +| **Gamma** | High | Mass, distance, vehicles | Whole-body dose, penetrates almost everything | No (minor) | +| **Neutron** | Very high | Only thick shielding / vehicles | Whole-body dose, most damaging per Gy | No | + +### Alpha + +Alpha particles can't get through your skin or a layer of cloth, so an alpha source sitting on the ground next to you is, externally, almost harmless. The catch is **inhalation**. Breathe alpha-emitting dust without a gas mask and it lodges inside you, where there's no skin to stop it — and it just *keeps* dosing you, long after you've walked away. + +- **External danger:** essentially none. +- **The real danger:** internal contamination. No mask = you breathe it in and your accumulated dose keeps climbing after you leave. +- **Protection that matters:** a **gas mask**. Nothing else changes much. + +> Alpha is the textbook argument for masking up in any dusty contaminated area even when the geiger reads low — the rate can be modest while the stuff you're inhaling is the part that kills you. + +### Beta + +Beta is the burner. It doesn't penetrate deep, so it dumps its energy in your skin — which means **radiation burns** on exposed body parts, plus a smaller whole-body contribution. Light shielding goes a long way here. + +- **External danger:** skin burns on exposed parts; mild whole-body dose. +- **Protection that matters:** a **full CBRN suit** nearly stops it; a gas mask helps a little; sitting in a vehicle cuts it. +- **Handling note:** picking up a beta source concentrates the burns on your hands and arms — see the carryable source in [Zeus & mission makers](07_zeus_and_MissionMakers.md). + +### Gamma + +Gamma is the one most people picture: high-energy, penetrating, and indifferent to your gas mask. It drives **whole-body dose** — the number that pushes you up the radiation-sickness tiers — and the only real defences are **mass, distance, and getting behind something solid.** + +- **External danger:** whole-body dose, the primary driver of acute radiation syndrome. +- **Protection that matters:** vehicles and terrain (moderate), dedicated rad-gear (some), distance (always). A mask or suit barely touch it. +- **Burns:** negligible — gamma's skin contribution is tiny by design, so a pure gamma source won't cover you in burns. + +### Neutron + +The most penetrating of the lot and the most biologically damaging per unit of dose. Neutron radiation shrugs off masks and suits almost entirely; only the bulk of a vehicle or serious shielding makes a dent. + +- **External danger:** whole-body dose, weighted heavier than gamma for the same rate. +- **Protection that matters:** vehicles and heavy cover, and not much else. +- **Sources:** typically reactor cores and certain weapon scenarios. + +--- + +## The three ways radiation doses you + +The same exposure is split across three separate "books," because they behave completely differently and are treated completely differently. + +``` + A RADIATION SOURCE + | + +------+--------------------+-------------------------+ + | | | + WHOLE-BODY PER-LIMB INTERNAL + (penetrating (skin dose on (breathed-in + gamma/neutron) exposed parts) contamination) + | | | + accumulated dose radiation BURNS keeps dosing you + -> sickness tiers on body parts after you leave + | | | + reduced by reduced by cleared ONLY by + shielding a CBRN suit chelation, never + by washing +``` + +- **Whole-body dose** — the big one. Gamma and neutron pour into this; it's what climbs the [radiation-sickness tiers](04_radiation_sickness.md). Your shielding reduces how fast it accrues. +- **Per-limb skin dose** — beta (and handling a source point-blank) deposit dose on specific body parts. Cross a threshold and you get a **radiation burn** wound on that part, treated like any other burn through ACE/KAT medical. +- **Internal contamination** — breathe in particulates (mostly alpha, some beta) without a mask and you accumulate an internal burden that converts to whole-body dose slowly over time. This is the dose that **keeps rising after you've left the source.** + +--- + +## Dose rate vs accumulated dose (again, because it matters) + +- **Dose rate** (Gy/h) is the field strength where you're standing — the geiger number. It is **not** reduced by your gear, because a geiger measures the environment, not you. +- **Accumulated dose** (Gy) is what your body has absorbed. **This** is reduced by shielding, and it's what makes you sick. + +The practical upshot: to check whether a suit or a vehicle is actually protecting you, don't watch the geiger rate — watch how fast the **accumulated** dose climbs. A good shield barely changes the rate reading but dramatically slows the dose you bank. + +> **Mission makers:** the per-type behaviour — how much each type weights into whole-body vs skin vs inhalation, and how each piece of gear shields it — is defined in the type *profiles* and is fully tunable. See the [profiles note in Zeus & mission makers](07_zeus_and_MissionMakers.md). + +--- diff --git a/docs/de/Radiation/03_protection_and_shielding.md b/docs/de/Radiation/03_protection_and_shielding.md new file mode 100644 index 000000000..727efc946 --- /dev/null +++ b/docs/de/Radiation/03_protection_and_shielding.md @@ -0,0 +1,67 @@ +# Protection & Shielding + +There is no single "radiation suit" that makes you immune. Different gear stops different types, and the most penetrating types (gamma, neutron) aren't really stopped by anything you can *wear* — only by mass, distance, and cover. Shielding here is about **slowing the dose you accumulate**, not switching the danger off. + +## The shielding matrix + +How much each piece of gear protects you, by type. "Strong" means it cuts the absorbed dose hard; "none" means don't bother. + +| Type | Gas mask | Full CBRN suit | Rad-gear uniform | Vehicle / cover | +|------|----------|----------------|------------------|-----------------| +| **Alpha** | **Decisive** (stops inhalation) | Decisive | Decisive | Decisive | +| **Beta** | Some | **Strong** | Strong | Good | +| **Gamma** | Negligible | Slight | Moderate | Moderate | +| **Neutron** | None | Negligible | Some | Some | + +A few things to read out of that table: + +- **Alpha** is all-or-nothing and it's about your airway. With a mask you barely accumulate anything; without one you breathe it in. Every other piece of gear "stops" alpha too, but the mask is the one that matters because inhalation is the real route. +- **Beta** is where a CBRN suit earns its keep — it nearly stops beta and saves you from the burns. A mask alone won't. +- **Gamma and neutron** can't be out-dressed. The honest answers are **distance**, **putting mass between you and the source**, and **time spent**. A vehicle helps; a uniform doesn't do much. + +> **The key nuance, one more time:** your gear reduces the **accumulated dose**, not the geiger **rate**. Standing in a gamma field in a vehicle, the dosimeter rate looks the same — but the dose you're banking is lower. Judge protection by the dose total, not the rate. + +### What counts as "rad-gear" + +Rad-gear is a mission-defined whitelist of uniforms that count as radiation-protective, separate from the CBRN suit list. Out of the box it's empty — mission makers populate it via the *Radiation-protective uniforms* CBA setting (see [Zeus & mission makers](07_zeus_and_MissionMakers.md)). It's the lever for adding whatever anti-rad suits your loadout mods provide. + +The gas mask and full CBRN suit are the **same items** the [Chemical](../Chemical/02_protection.md) side uses — a worn, filtered mask and a whitelisted CBRN uniform. Radiation doesn't add new wearables; it reuses the CBRN kit and adds the uniform whitelist on top. + +--- + +## Contamination: external vs internal + +This split is the heart of radiation treatment, so it gets its own section. There are **two** kinds of contamination and they could not be more different. + +### External (surface) contamination + +Radioactive dust settling on your skin and gear. It: + +- **Reads on a geiger** — it makes *you* a weak source, so your own dosimeter keeps clicking even after you've left the area. +- **Doses you and the people next to you** (see cross-contamination below). +- **Comes off with the Decontamination Kit.** Washing it off is the whole fix. +- Slowly weathers away on its own over time. + +### Internal contamination + +Radioactive material you've **breathed in** (mostly from alpha/beta dust without a mask). It: + +- **Does not read on a geiger** — it's inside you, invisible to a survey. +- **Keeps converting to whole-body dose** for a long time, so your accumulated dose climbs even in clean air. +- **Cannot be washed off.** Decon does nothing. It needs **Prussian Blue** chelation to speed elimination, or your body slowly clears it on its own. + +> **The trap:** a casualty walks out of a contaminated area, you decon them, the geiger goes quiet — and they keep getting sicker. That's internal contamination. Decon cleaned the surface; the dose is coming from the inside. Reach for Prussian Blue, not the decon kit. + +--- + +## Cross-contamination + +A contaminated casualty isn't just a patient — they're a **source**. Surface contamination makes a unit emit a weak beta/gamma field of their own, which means: + +- Their **own** dosimeter reads hot even in clean air. +- **Medics treating them accumulate dose**, and a clean responder standing next to a contaminated casualty will see their own geiger tick up. +- A **rad survey** on the casualty (see [Detection & items](05_detection_and_items.md)) reads their contamination level and dominant type so you know what you're dealing with. + +The fix is the same: **decon the casualty** to remove the surface contamination, and the field they emit disappears with it. Until then, treat them like the hot object they are — work fast, and don't loiter. + +--- diff --git a/docs/de/Radiation/04_radiation_sickness.md b/docs/de/Radiation/04_radiation_sickness.md new file mode 100644 index 000000000..7983de37c --- /dev/null +++ b/docs/de/Radiation/04_radiation_sickness.md @@ -0,0 +1,89 @@ +# Radiation Sickness + +Acute Radiation Syndrome (ARS) is what a dose actually *does* to a body, and it's the deepest part of the system. Rather than a health bar ticking down, a serious dose sets off a staged cascade through the body's systems — blood, gut, brain — each on its own clock, each hooking into KAT's existing medical sims so the casualty genuinely behaves like someone who's been irradiated. + +The important mental model: **the dose lands in an instant, but the sickness unfolds over minutes.** Someone can soak a fatal dose, feel only queasy, and seem fine right up until the systems start failing. + +## The tier ladder + +Your accumulated dose maps to a severity **tier**, and the tier decides which syndromes switch on. Defaults shown — every threshold is configurable. + +| Tier | Dose (default) | Name | What switches on | +|------|----------------|------|------------------| +| **0** | < 1 Gy | None | Nothing | +| **1** | 1–2 Gy | Mild (prodromal) | Nausea/vomiting, pain, fever begins | +| **2** | 2–4 Gy | Moderate (hematopoietic) | Marrow suppression → anemia, won't-clot bleeding, infection risk | +| **3** | 4–6 Gy | Severe (GI) | Dehydration, blood-gas acidosis, heavy vomiting | +| **4** | ≥ 6 Gy | Lethal (neurovascular) | Hypotension, seizures, collapse → cardiac arrest | + +Higher tiers don't replace the lower ones — they **stack on top**, and they arrive **faster** (the latent period compresses as the dose climbs, mirroring the real-world "time to vomiting" biomarker that medics use to estimate dose). + +``` + DOSE ABSORBED + | + [accumulates] --> crosses 1 Gy --> TIER 1 prodromal (nausea, fever) + | | + | crosses 2 Gy --> TIER 2 marrow fails + | (anemia, bleeding, infection) + | | + | crosses 4 Gy --> TIER 3 gut fails + | (dehydration, acidosis) + | | + | crosses 6 Gy --> TIER 4 brain/circulation fails + | (hypotension -> collapse -> arrest) + v + higher dose = shorter time before each stage hits +``` + +--- + +## The syndromes, in plain terms + +### Prodromal (tier 1+) +The early warning. Nausea and vomiting, a creeping rise in pain, and the start of a fever. It's miserable but survivable — and it's the body telling you the real damage is already done and the clock is running. + +### Hematopoietic — the marrow (tier 2+) +The classic radiation kill mechanism, just slower than the dramatic stuff. Your bone marrow stops keeping up, and three things follow: + +- **Anemia** — your blood volume slowly falls and you can't replace it. A wound that would normally be survivable becomes a problem because you can't rebuild what you lose. +- **Thrombocytopenia** — your blood won't clot properly. Bleeding that should stop with a bandage keeps going. +- **Immunosuppression** — your immune system is on the floor, which opens the door to **wound infection** (below). + +### Gastrointestinal — the gut (tier 3+) +Now it's serious. Fluid pours out of the body (dehydration → falling blood volume), the blood chemistry tips into **acidosis**, and the vomiting becomes relentless. This is the tier where casualties start sliding toward hypovolemic shock. + +### Neurovascular / CNS — the lethal tier (tier 4) +Blood pressure craters (**hypotension**), brief **seizures** hit, and the casualty collapses into unconsciousness and then cardiac arrest. **This tier will not recover on its own** — but it is *not* an automatic death sentence: with a hard, sustained intensive-care effort a lethal casualty can be pulled back. See [Treatment & triage → Intensive care for lethal doses](06_treatment_and_triage.md#intensive-care-for-lethal-doses). Left alone, though, they die. + +### Systemic — fever & the screen +Running underneath all of it: a **fever** that climbs with severity, and a **visual effect** — the world desaturates into a sickly grade as you get worse (toggleable, on by default). The visual is your gut-feel warning when you're not staring at the dosimeter. + +--- + +## Recovery + +Here's the merciful part: **below the lethal tier, radiation sickness heals on its own.** Once you're out of the radiation (no field, no internal contamination left), your sickness slowly winds back down over minutes — marrow recovers, fever breaks, blood pressure normalises, and the tier ticks back to zero. + +- The **accumulated dose** on your dosimeter stays where it is — that's your permanent exposure record — but the *sickness* it caused fades. +- **Filgrastim** speeds this up considerably (see [Treatment](06_treatment_and_triage.md)). +- The **lethal tier does not spontaneously recover** — it only comes back with the active [intensive-care protocol](06_treatment_and_triage.md#intensive-care-for-lethal-doses). Everything below it heals on its own, given time and support. + +--- + +## Wound infection & sepsis + +When your immune system is suppressed (tier 2+) and you have **open or bandaged wounds**, those wounds can become **infected**. Once infected: + +- Pain and fever climb, and the wound bleeds in a way that drags your blood volume down. +- Left untreated, the infection worsens into **sepsis** — and sepsis here is **lethal**. A casualty who survives the radiation itself can still die of the infection it let in. This is the realistic sting in the tail of marrow failure. +- **Antibiotics** clear it. It also resolves on its own *if* the casualty's immunity recovers first — so it's a race between your immune system coming back and the infection getting ahead of it. + +> **Mission makers:** infection can be switched off entirely with the *Enable wound infection* setting if you don't want sepsis in your mission. + +--- + +## A note for mission makers: this rides on other systems + +The physiology layers drive **real KAT medical subsystems** — blood volume, coagulation, blood gas, blood pressure, body temperature. If a subsystem is disabled in the addon options, the matching radiation effect simply doesn't fire (cleanly, no errors), and the rest still work. Which layer needs which subsystem is laid out in the [dependency table in Zeus & mission makers](07_zeus_and_MissionMakers.md). All of them are on by default. + +--- diff --git a/docs/de/Radiation/05_detection_and_items.md b/docs/de/Radiation/05_detection_and_items.md new file mode 100644 index 000000000..e04be5ad6 --- /dev/null +++ b/docs/de/Radiation/05_detection_and_items.md @@ -0,0 +1,68 @@ +# Detection & Equipment + +You cannot see, smell, or feel radiation. Without a device you have no idea whether the room you just walked into is harmless or already killing you — so detection isn't optional here the way it sometimes is with a visible gas cloud. + +## The Dosimeter (your geiger) + +The `KAT_Dosimeter` is a worn device (watch slot, like the chemical JCAD). It's your eyes for radiation: a small HUD with the dose readout, plus the classic geiger clicks. + +**Turning it on** — three independent steps, mirroring how the JCAD works: + +1. **Show the HUD** — press the dosimeter key (**P** by default) to bring the readout up. +2. **Enable the dosimeter** — a self-action that switches on the live dose-*rate* reading. Until you do this, the HUD shows your accumulated dose but the rate reads `--`. +3. **Enable the sound** — a separate self-action that turns on the geiger clicks. The clicks get faster as the dose rate climbs, and go silent when you're in clean air. + +There are matching **Disable** / **Sound off** self-actions to turn each back off. + +**What it shows:** + +- **Accumulated dose (Gy)** — always visible. Your running total of absorbed radiation. This is the number that decides how sick you get. +- **Dose rate (Gy/h)** — visible once enabled. How hot your current spot is. Remember: this reads the *field*, not what you absorb, so it ignores your shielding. + +> The geiger reads the environment, so it'll keep clicking if **you** are contaminated even in clean air — that's the surface contamination making you a source. If the clicks won't stop after you've left a zone, survey/decon yourself. + +> **Asset note:** the dosimeter currently borrows the chemical detector's model and the geiger sounds reuse the detector's chime samples as placeholders. The numbers and behaviour are real; dedicated art and click audio are planned. + +## Rad Survey (diagnostic) + +A medical action — **Radiation Survey** — that points the dosimeter at a casualty and reports: + +- their **surface contamination** level (as a %), +- the **dominant radiation type** they're carrying, +- and the **ambient dose rate** at them. + +Requires a dosimeter in your kit. Use it on a casualty before you start treating to know whether you need to decon them (and to know whether *you're* about to get dosed working on them). + +## Dose Estimation (triage diagnostic) + +A second medical action — **Estimate Radiation Dose** — for triage. It reads the casualty's exposure and reports: + +- their **exact accumulated dose** in Gy, +- a **prognosis** band (from "no ARS expected" up to "likely lethal without intensive treatment"), +- and the **time-to-vomiting** biomarker, if they've vomited. + +This is your tool for deciding who's salvageable and who isn't when you have more casualties than supplies. + +--- + +## Equipment & Items + +Everything radiation-related, plus the shared decon kit. All available through ACE Arsenal. + +| Item | Classname | Purpose | How to use | +|------|-----------|---------|------------| +| Dosimeter | `KAT_Dosimeter` | Reads dose rate + accumulated dose; geiger clicks | Watch slot; key **P** + self-actions to enable/sound | +| Potassium Iodide (KI) | `kat_potassiumIodide` | **Prophylaxis** — reduces uptake if taken before/early | *Take Potassium Iodide* (self + medic) | +| Prussian Blue | `kat_prussianBlue` | **Chelation** — speeds clearing of internal contamination | *Administer Prussian Blue* (self + medic) | +| Antibiotics | `kat_antibiotics` | Fights radiation wound infection / sepsis | *Administer Antibiotics* (self + medic) | +| Filgrastim (G-CSF) | `kat_filgrastim` | Speeds marrow / sickness recovery | *Administer Filgrastim* (self + medic) | +| Antiemetic | `kat_antiemetic` | Suppresses radiation-sickness vomiting | *Administer Antiemetic* (self + medic) | +| Stem-Cell / Marrow Rescue | `kat_stemCells` | The pivotal cure for a **lethal** dose — enables intensive-care recovery | *Administer Stem-Cell Rescue* (**medic only**, lethal casualty) | +| Decontamination Kit | `kat_decon_kit` | Removes **surface** contamination (shared with Chemical) | *Decontaminate* (shown when contaminated) | +| Radioactive Source | `kat_radSource` | A carryable/placeable point source | Editor/Zeus object; ACE *Pick up* / *Drop* | + +> The decon kit and the CBRN mask/suit are the **same items** the [Chemical](../Chemical/05_detection_identification_items.md) side uses — radiation reuses them rather than adding duplicates. The drugs and the dosimeter are radiation's own additions. + +> **What decon does and doesn't do:** the decon kit clears **surface** contamination only. It will not touch internal contamination (use Prussian Blue) and it does nothing to the dose you've already absorbed. See [Treatment & triage](06_treatment_and_triage.md). + +--- diff --git a/docs/de/Radiation/06_treatment_and_triage.md b/docs/de/Radiation/06_treatment_and_triage.md new file mode 100644 index 000000000..6acdd8524 --- /dev/null +++ b/docs/de/Radiation/06_treatment_and_triage.md @@ -0,0 +1,120 @@ +# Treatment & Triage + +Radiation treatment is less about a single antidote and more about managing a casualty through a sickness that plays out over time. There's no "cure the radiation" button — there's removing what's still dosing them, slowing the damage, and supporting the body's systems while it recovers (or deciding it can't). + +## The one distinction that runs everything: decon vs chelation + +Two kinds of contamination, two completely separate cures. Mixing them up is the classic mistake. + +| Contamination | Where it is | Cleared by | NOT cleared by | +|---------------|-------------|-----------|----------------| +| **Surface (external)** | On skin & gear | **Decontamination Kit** | Prussian Blue | +| **Internal** | Breathed in, inside the body | **Prussian Blue** (chelation) | The decon kit / washing | + +- **Decon** scrubs the surface. It stops the casualty reading hot on a geiger and stops them cross-contaminating others. +- **Prussian Blue** chelates — it binds internal radionuclides so the body clears them faster, cutting off the internal dose that otherwise keeps climbing for ages. + +Neither one undoes dose already absorbed. They stop *further* dosing from contamination; the sickness from what's already in still has to be ridden out. + +--- + +## Treatment reference + +Match what you've found to what you reach for. + +| What you see / know | Use | Notes | +|---------------------|-----|-------| +| Casualty reads hot on a survey; geiger won't stop | **Decontamination Kit** | Clears surface contamination + stops cross-contamination | +| Dose keeps climbing in clean air (breathed it in) | **Prussian Blue** | Chelation; the only thing that touches internal contamination | +| *Before* entering a hot area | **Potassium Iodide (KI)** | Prophylactic — reduces uptake; useless after the fact | +| Vomiting from radiation sickness | **Antiemetic** | Suppresses the vomiting for a while | +| Infected wound / heading toward sepsis | **Antibiotics** | Clears infection; essential if infection is enabled | +| Slow to recover after a survivable dose | **Filgrastim (G-CSF)** | Speeds marrow/sickness recovery | +| Anemia, low blood volume, dehydration | **IV Blood / Saline** | Standard KAT fluids — radiation drains blood volume, so top it up | +| Radiation burns, open wounds | Standard ACE/KAT wound care | Treat as ordinary injuries | + +> **Timing is everything with the two anti-rad drugs.** KI only helps **before** uptake — it's a pre-exposure tablet, not a treatment. Prussian Blue is the opposite — it's for **after**, to speed clearing what's already inside. Carry KI for planned entries into hot zones; carry Prussian Blue for after the fact. + +> **Tracking what you've given:** every radiation drug logs to the patient's **triage card** in the medical menu when administered (with a tally on repeat doses), so you can see at a glance what's already on board. + +--- + +## Treating a casualty — quick flow + +``` + Radiation casualty (down or sick) + | + 1. MAKE IT SAFE FOR YOU + Survey them. If they read hot, DECON first — a contaminated + casualty doses you the whole time you're working on them. + | + 2. STOP THE DOSING + - DECON KIT -> clears surface contamination + - PRUSSIAN BLUE -> clears internal (inhaled) contamination + - move them clear of any radiation field + (until dosing stops, nothing you do below will hold) + | + 3. ESTIMATE THE DOSE (Estimate Radiation Dose action) + | + +-----+----------------------------------------+ + | | + SURVIVABLE (mild–severe) LETHAL (top tier, >6 Gy) + | | + supportive care: INTENSIVE CARE (hard, ~15 min): + - IV blood/saline (anemia, fluids) keep alive: IV or vasopressor + - antibiotics (if infected) cure (all at once, sustained): + - antiemetic (vomiting) filgrastim + antibiotics + - filgrastim (speeds recovery) + STEM-CELL RESCUE + | (source already removed) + recovers over minutes; -> see "Intensive care for + accumulated dose stays on record lethal doses" below + | + 4. MOP UP + Treat radiation burns and open wounds as normal ACE/KAT injuries. +``` + +The short version of supportive care for a survivable casualty: **stop the contamination (decon/chelate), replace the blood they're losing (IV), keep infection out (antibiotics), make them comfortable (antiemetic), and speed the marrow back (filgrastim).** Then time does the rest. A **lethal** casualty needs all of that *plus* the sustained intensive-care protocol below — they will not recover on supportive care alone. + +--- + +## Intensive care for lethal doses + +A lethal dose (the top tier, ≥ 6 Gy by default) **will not recover on its own** — but it's survivable if a medic commits to a hard, ~15-minute intensive-care fight. There are two layers: keep them alive, then actually cure them. (Mission makers can switch this off with *Lethal dose curable*, making the top tier terminal again.) + +### Layer 1 — keep them alive +A lethal casualty collapses unconscious and starts a hidden "time to arrest" clock. **Circulatory support holds that clock off:** + +- an **active IV line** (blood or saline), **or** +- a **vasopressor** in their system (epinephrine / norepinephrine). + +Let support lapse and the clock runs out → **cardiac arrest**, at which point it's a full CPR / defibrillator / rhythm-management emergency (the normal cardiac-arrest system, advanced rhythm and all). Support is the bare minimum just to stop them dying — it does **not** cure anything. + +### Layer 2 — actually cure them +Their radiation sickness only winds down while the **entire intensive-care stack is sustained at once**: + +1. **Source removed** — fully deconned *and* chelated (Prussian blue), out of any field. While any dose is still coming in, nothing improves. +2. **Circulatory support** — the IV or vasopressor from Layer 1. +3. **Filgrastim** — kept topped up. +4. **Antibiotics** — kept topped up (and the only thing stopping sepsis finishing them off in parallel). +5. **Stem-Cell / Marrow Rescue** (`kat_stemCells`) — the pivot. Medic-only, slow to administer, and re-dosed as it wears off. **Without it, full support only *holds* them — alive but never improving.** With it, the sickness finally starts to clear. + +Sustain all five and severity grinds down over roughly **12–16 minutes**, after which they drop out of the danger zone and finish recovering normally. Drop any one and the cure **stalls**. + +### They stay unstable until it's done +Bringing someone back from arrest doesn't make them safe. While they're still heavily irradiated their system keeps **crashing back into arrest** — even on an IV — and (with advanced rhythm on) throws **VF/VT far more often**. Both taper off as the cure progresses, so the way to *stop* the re-crashes is to push the cure down, not just park them on a pressor. Expect to resuscitate the same patient more than once before they're out of the woods. + +> This is deliberately brutal: one medic with a couple of items can't do it. It takes the full kit, constant re-dosing, and someone watching the monitor for the next arrest — a genuine team effort to save one person. + +--- + +## Prophylaxis: the smart play + +The cheapest treatment is the one you take before anything happens. If you know you're going into a contaminated area: + +- **Take KI first** — it reduces how much radioiodine your body takes up while you're in there. +- **Mask and suit up** per the [shielding rules](03_protection_and_shielding.md) — the mask especially, to keep internal contamination out. +- **Carry a dosimeter and watch the accumulated dose**, not just the rate. Leave before it climbs into the tiers you can't walk back from. + +A prepared unit can work a hot zone and recover. An unprepared one finds out about the dose when the vomiting starts. + +--- diff --git a/docs/de/Radiation/07_zeus_and_MissionMakers.md b/docs/de/Radiation/07_zeus_and_MissionMakers.md new file mode 100644 index 000000000..68e57a2d3 --- /dev/null +++ b/docs/de/Radiation/07_zeus_and_MissionMakers.md @@ -0,0 +1,179 @@ +# Zeus & Mission Makers + +How to put radiation on the map, and how to tune every part of it. + +## Placing radiation sources + +A source emits any mix of the four types, each with its own strength in **Gy/h**. You author that mix either by hand (the four per-type fields) or by picking a **preset** that fills them for you. + +### Radiation module (`kat_module_radiation`) + +In the editor under **Modules → KAT**, and the same module is available in **Zeus** as a curator module. Its attributes: + +- **Preset** — a dropdown that fills the four strength fields for you. Pick `Custom` to use the fields directly, or any named preset to auto-fill them. +- **Alpha / Beta / Gamma / Neutron (Gy/h)** — the per-type strengths. Used when Preset is `Custom`; a named preset overrides them. +- **Radius** — area size in metres. +- **Point source** — if enabled, the source falls off with the inverse-square law (a hot spot) instead of linearly across the radius (an area/zone). + +Sync the module to a `LocationArea` trigger for a zone, or enable **Point source** for a localised hotspot. The **Zeus** version opens the same attributes dialog — picking a preset there auto-fills the four fields before you confirm. + +### Source presets + +| Preset | Alpha | Beta | Gamma | Neutron | Reads like | +|--------|-------|------|-------|---------|-----------| +| **Custom** | — | — | — | — | Use the four fields | +| **Cobalt-60** | 0 | 0 | 100 | 0 | Strong sealed gamma source — whole-body dose, no burns | +| **Reactor** | 0 | 0 | 50 | 25 | Reactor core / criticality — deadliest, neutron-heavy | +| **Fallout** | 0 | 400 | 20 | 0 | Lingering area — beta skin burns + slow sickness | +| **Alpha Emitter** | 150 | 10 | 0 | 0 | Inhalation hazard — near-harmless unless breathed in | +| **Dirty Bomb** | 40 | 250 | 50 | 0 | A messy mix — burns, gamma, and inhalation | + +> Strengths are **Gy/h** — the dose rate at the reference point (the centre for zones, ~1 m for point sources). With the defaults, a casualty in a ~500 Gy/h gamma field reaches the lethal tier in roughly 40 seconds; the 100 Gy/h Cobalt-60 preset is a few-minutes hazard; Fallout's heavy beta is what produces skin burns over a few minutes. Scale to the pace you want. +> +> **Note on neutron:** the neutron field is weighted far heavier than the others for whole-body dose (high biological effect), so a small neutron number bites hard — that's why Reactor is the deadliest preset despite modest-looking figures. + +### Carryable radioactive source (`kat_radSource`) + +A placeable object (editor and Zeus) that acts as a **hot beta+gamma point source** you can pick up — think a lost industrial-radiography source. ACE-interact to **Pick up radioactive source**, and held point-blank it concentrates skin dose on your hands and arms (a burn in about a minute) while pouring whole-body dose into you — rapidly lethal unshielded, though a CBRN suit buys you a few minutes to make the carry. **Drop** it to set it back down. Great for "carry the source to the disposal site" objectives. + +> **Asset note:** `kat_radSource` uses a placeholder jerry-can model for now; dedicated art is planned. + +### Quick console source (testing) + +To drop a source at your feet without placing a module — handy for testing — run this as the server: + +```sqf +["kat_chemical_addRadSource", [getPosASL player, 30, [0,0,500,0], "linear", "testRad", {true}, []]] call CBA_fnc_serverEvent; +``` + +The array is `[alpha, beta, gamma, neutron]` in Gy/h. Remove it with: + +```sqf +["kat_chemical_removeRadSource", "testRad"] call CBA_fnc_serverEvent; +``` + +--- + +## Mission Configuration (CBA Settings) + +Everything below lives under **CBA Settings → KAT - ADV Medical: Chemical**, in the **"10. Radiation"** subcategory (radiation shares the chemical addon's settings category). Times are in seconds; dose values in Gray. + +### Master & display + +| Setting | Default | What it does | +|---------|---------|--------------| +| Enable radiation | on | Master switch for the whole system | +| Show sickness messages | on | Whether radiation-sickness hints appear on screen | +| Radiation visual effect | on | The desaturated screen effect while irradiated/sick (client-side) | + +### Dose thresholds (Gy) + +| Setting | Default | What it does | +|---------|---------|--------------| +| Mild dose threshold | 1 | Dose at which mild (prodromal) sickness begins | +| Moderate dose threshold | 2 | Dose at which the hematopoietic tier begins | +| Severe dose threshold | 4 | Dose at which the GI tier begins | +| Lethal dose threshold | 6 | Dose at which the neurovascular (lethal) tier begins | + +### Stage timings + +| Setting | Default | What it does | +|---------|---------|--------------| +| Prodromal delay | 120 | Time to the first prodromal symptoms | +| Hematopoietic delay | 600 | Time to marrow-suppression onset | +| GI delay | 480 | Time to GI-syndrome onset | +| CNS delay | 180 | Time to neurovascular onset | +| Cardiac delay | 300 | Time to the fatal cardiac event | + +> Higher tiers compress these delays automatically — a massive dose makes the stages arrive much faster than a borderline one. + +### Shielding + +| Setting | Default | What it does | +|---------|---------|--------------| +| Mask protection factor | 1.0 | Global effectiveness multiplier for gas-mask shielding | +| CBRN suit protection factor | 1.0 | Global multiplier for CBRN-suit shielding | +| Rad-gear protection factor | 1.0 | Global multiplier for rad-gear-uniform shielding | +| Vehicle protection factor | 1.0 | Global multiplier for vehicle shielding | +| Radiation-protective uniforms | *(empty)* | **Whitelist of uniform classnames that count as rad-gear** | + +> *Radiation-protective uniforms* is the radiation equivalent of the CBRN-suit whitelist — a quoted, comma-separated list of classnames. Populate it with whatever anti-rad suits your loadout mods provide. + +### Contamination + +| Setting | Default | What it does | +|---------|---------|--------------| +| Inhalation factor | 0.1 | How much unmasked exposure becomes internal contamination | +| Internal dose conversion rate | 0.001 | How fast internal contamination converts to whole-body dose | +| Internal decay rate | 0.0005 | How fast the body clears internal contamination on its own | +| Contamination deposition | 0.02 | How fast surface contamination builds up | +| Contamination decay | 0.002 | How fast surface contamination weathers away | +| Cross-contamination strength | 5 | How strong a field a contaminated casualty emits (Gy/h scale) | +| Local exposure distance | 1.5 | Within this range of a point source, skin dose concentrates on arms/hands | +| Skin burn threshold | 5 | Local skin dose per radiation-burn wound | + +### Drugs + +| Setting | Default | What it does | +|---------|---------|--------------| +| KI protection factor | 0.5 | How much KI reduces uptake while active | +| KI duration | 3600 | How long a KI dose protects | +| Chelation duration | 600 | How long Prussian Blue accelerates internal clearance | +| Chelation factor | 5 | How much faster chelation clears internal contamination | +| Antibiotic duration | 600 | How long antibiotics suppress infection | +| Antiemetic duration | 900 | How long an antiemetic suppresses vomiting | +| Filgrastim duration | 1800 | How long filgrastim accelerates recovery | +| Filgrastim recovery multiplier | 3 | How much faster sickness recovers while filgrastim is active | + +### Physiology + +| Setting | Default | What it does | +|---------|---------|--------------| +| Anemia rate (ml/s) | 2 | Blood-volume loss from marrow suppression (scaled by severity) | +| GI fluid loss (ml/s) | 3 | Blood-volume loss from GI dehydration | +| GI acidosis rate | 0.05 | Per-second drop in blood-gas bicarbonate/pH | +| CNS hypotension (mmHg) | 40 | Maximum blood-pressure drop at the lethal tier | +| Maximum fever (°C) | 2 | Peak temperature rise from radiation sickness | +| Recovery rate (Gy/s) | 0.01 | How fast sickness heals once out of radiation (below lethal) | + +### Infection + +| Setting | Default | What it does | +|---------|---------|--------------| +| Enable wound infection | on | Whether immunosuppressed wounds can get infected → sepsis | +| Infection chance | 0.05 | Per-second base chance of infection (scaled by immunosuppression) | +| Infection progression rate | 0.02 | How fast an untreated infection worsens | +| Sepsis blood loss (ml/s) | 15 | Blood loss at full infection — drives lethal septic shock | + +### Lethal-tier intensive care + +| Setting | Default | What it does | +|---------|---------|--------------| +| Lethal dose curable | on | If on, a lethal casualty can be saved with sustained intensive care; if off, the lethal tier is terminal | +| Collapse time (unsupported) | 150 | Seconds a critical casualty lasts without IV/vasopressor before cardiac arrest | +| Intensive-care recovery rate (Gy/s) | 0.006 | How fast a lethal casualty's sickness clears under the full stack (lower = harder) | +| Stem-cell rescue duration | 300 | How long one stem-cell dose enables recovery before re-dosing | +| Re-crash chance | 0.05 | Per-tick chance (at full severity) of crashing back into arrest; tapers with the cure, halved on life support | +| Shockable rhythm bias | 0.7 | Chance (at full severity, Advanced Rhythm on) a radiation arrest is VF/VT vs asystole/PEA | +| Stem-cell rescue required trait | Medics | Who can administer the stem-cell rescue (Anyone / Medics / Doctors) | +| Intensive-care readout | off | Show a status line in the medical menu for a critical casualty (cure progress + missing supports; never the arrest timer) | + +> The lethal-tier cure also leans on the **Circulation** cardiac-arrest system and, when enabled, **Advanced Rhythm** (`kat_circulation_AdvRhythm`) for the VF/VT behaviour — it cooperates with them rather than running its own death timer. + +--- + +## Subsystem dependencies (important) + +The physiology layers drive **other KAT medical subsystems**. If one is disabled in addon options, the matching radiation effect is **cleanly skipped** (no errors) and everything else keeps working. They all default **ON**, so this is usually a "don't accidentally turn it off" check. + +| Radiation effect | Needs this subsystem ON | Setting | +|------------------|------------------------|---------| +| Thrombocytopenia (won't-clot bleeding) | KAT Pharmacy → Coagulation | `kat_pharma_coagulation` | +| Anemia regeneration impairment | KAT Vitals → Fluid Shift | `kat_vitals_enableFluidShift` | +| GI acidosis (blood-gas pH/HCO3) | KAT Breathing → Enable | `kat_breathing_enable` | +| CNS hypotension (blood pressure) | KAT Circulation → Enable | `kat_circulation_enable` | +| Fever (body temperature) | KAT Hypothermia → Enable Hypothermia | `kat_hypothermia_hypothermiaActive` | + +> To exercise the full system on **AI** casualties, keep **KAT Vitals → Simple Medical OFF** — simple medical bypasses the detailed vitals loop the radiation effects ride on. Players always get the full sim. + +--- diff --git a/docs/de/Radiation/08_faq_and_troubleshooting.md b/docs/de/Radiation/08_faq_and_troubleshooting.md new file mode 100644 index 000000000..5f3e02518 --- /dev/null +++ b/docs/de/Radiation/08_faq_and_troubleshooting.md @@ -0,0 +1,34 @@ +## FAQ & Troubleshooting + +### **My geiger is screaming but I'm not taking any damage. Is it broken?** +No — that's working as intended, and it might be your gear doing its job. The geiger reads the **dose rate** (the field around you), which your shielding does *not* change. What your shielding reduces is the **accumulated dose** — the Gy total you actually soak up. Watch that number: if it's barely climbing while the rate is high, your suit/vehicle is protecting you. (And if you're in a pure-gamma field with only a mask on, the rate being scary while the dose climbs fast is *also* correct — a mask doesn't stop gamma.) + +### **I left the radiation hours ago but my dose is still going up.** +You breathed it in. That's **internal contamination** — radioactive material inside you that keeps converting to dose long after you've left. A geiger and a decon kit can't help with it because it isn't on your surface. Use **Prussian Blue** to chelate it out, or wait for your body to slowly clear it. + +### **I deconned the casualty but their dose didn't drop.** +Decon only removes **surface** contamination — it stops them reading hot and cross-contaminating others, but it does nothing to dose already absorbed, and nothing to internal contamination. If their dose is still climbing, it's internal (use Prussian Blue). If it's just high but stable, that's the permanent record of what they absorbed — there's no scrubbing that off, only treating the sickness. + +### **A pure gamma source gave me almost no burns. Shouldn't radiation burn me?** +Not gamma. Skin/radiation burns come from **beta** and from **handling a source point-blank**. Gamma and neutron drive whole-body dose, not skin dose, so a gamma zone makes you *sick* without covering you in burns. Stand in a beta field — or pick up a `kat_radSource` — to see burns. + +### **I walked into a hot zone and died almost instantly. Is that normal?** +Only if the source is enormous. Source strength is in **Gy/h**, and a very high value (say several hundred) will push you past the 6 Gy lethal threshold in well under a minute. If you want a survivable hazard, lower the source strength, raise the dose thresholds, or both — see [Zeus & mission makers](07_zeus_and_MissionMakers.md). + +### **One of the sickness effects does nothing — no fever / no blood-pressure drop / bleeding still clots.** +That effect's host subsystem is probably disabled. The physiology layers ride on other KAT systems: fever needs **Hypothermia**, acidosis needs **Breathing**, hypotension needs **Circulation**, won't-clot bleeding needs **Pharmacy Coagulation**, and anemia regen needs **Vitals Fluid Shift**. They're all on by default — check none got switched off. (Radiation skips a disabled layer cleanly; it won't error.) + +### **My AI test casualty ignores all the physiology.** +Turn **Simple Medical OFF** in KAT Vitals. Simple medical bypasses the detailed vitals loop that the radiation effects hook into. Players always get the full sim; AI only do when simple medical is off. + +### **The casualty recovered from severe radiation sickness on their own. Bug?** +Intended. Below the lethal tier, sickness heals slowly once the casualty is out of radiation (and clear of internal contamination). **Filgrastim** speeds it up. The **lethal tier** never self-recovers — it's survivable only with the sustained [intensive-care protocol](06_treatment_and_triage.md#intensive-care-for-lethal-doses), not by waiting. Note the *accumulated dose* on the dosimeter stays put — that's the exposure record; it's the sickness that fades, not the history. + +### **A medic treating a contaminated casualty started getting dosed.** +That's cross-contamination, and it's intended. A surface-contaminated casualty emits a weak field of their own. **Decon them** to shut it off — until you do, anyone working on them is standing next to a small source. Survey first, decon, then treat. + +### **The dosimeter clicks won't stop even in clean air.** +You're contaminated — *you* are the source the geiger is reading. Survey yourself and use the decon kit. (If you've turned the dosimeter sound off and it still seems to click, that's the placeholder chime samples — dedicated click audio is planned.) + +### **Is radiation a separate addon I need to enable?** +No. Radiation is part of the **Chemical** addon — same PBO, same CBA settings category (under the "10. Radiation" subcategory). If you have KAT's chemical addon, you have radiation. diff --git a/docs/en/Radiation/01_Info_and_QuickStart.md b/docs/en/Radiation/01_Info_and_QuickStart.md new file mode 100644 index 000000000..39670cf1f --- /dev/null +++ b/docs/en/Radiation/01_Info_and_QuickStart.md @@ -0,0 +1,51 @@ +# Radiation — Player & Mission-Maker Guide + +The **Radiation** system is an extension of the **Chemical** addon — the "R" and "N" in CBRN that the gases left on the table. It lives in the same addon, shares the same CBA settings category, and reuses the same decontamination kit and CBRN gear, so if you've already read the [Chemical guide](../Chemical/01_Info_and_QuickStart.md) a lot of this will feel familiar. If you haven't, the short version is: this mod treats hazards as things you prepare for, not things that simply tick your health down. + +Where the gases are about a cloud you can usually *see* and an antidote you carry, radiation is quieter and slower. You can't smell it, a mask won't stop most of it, and the dose you soak up today can put you in the ground a quarter of an hour from now with nothing visibly wrong in between. The only way to know what you're standing in is to carry a dosimeter and pay attention to it. + +This guide is written for two audiences: + +- **Players / medics** — what the four radiation types do, how to shield against them, and how to treat radiation casualties. +- **Mission makers / Zeus** — how to place radiation sources and how to tune the whole thing through CBA settings. + +> **A note on units.** Dose is measured in **Gray (Gy)**, the real SI unit of absorbed radiation. As a rough yardstick: a couple of Gy makes you sick, around 4 Gy is a coin-flip for survival without treatment, and 6 Gy and up is the danger zone. The defaults are built around those numbers but every threshold is configurable. + +--- + +## How dose works (the one concept to understand) + +There are three different numbers in play, and confusing them is the single most common mistake: + +- **Dose rate** — how *hot* the spot you're standing in is, in **Gy/h**. This is what your dosimeter's geiger reads. It measures the field around you; it does **not** care what you're wearing. +- **Accumulated dose** — how much radiation your body has actually *absorbed*, in **Gy**. This is what makes you sick, and **this** is what your shielding reduces. It only ever goes up while you're exposed, and it's permanent. +- **Internal contamination** — radioactive material you've **breathed in**. It sits inside you and keeps delivering dose for a long time after you've left the area. Washing it off does nothing; it has to be chelated out or wait out your body clearing it. + +So: the geiger screaming doesn't mean you're being hurt (your suit might be eating it), and the geiger going quiet doesn't mean you're safe (you might be carrying contamination inside you). Watch the *accumulated* dose, not just the rate. + +--- + +## Quick Start + +If you only read one section, read this one. + +1. **Carry a dosimeter.** The `KAT_Dosimeter` (watch slot) is your only way to see dose rate and accumulated dose. Turn it on, turn the sound on, and let the clicks warn you before the numbers do. +2. **Shielding depends on the type.** There's no single "rad suit." A gas mask matters for alpha (inhalation) and helps against beta; a full CBRN suit stops beta and dents gamma; vehicles and terrain are what cut gamma and neutron. Distance is always your friend. +3. **Dose is cumulative — manage your time.** You can't "heal" the radiation you've already absorbed by leaving. Treat a hot zone like a budget: get in, do the job, get out before the accumulated dose climbs into the danger tiers. +4. **Two kinds of contamination, two different cures.** Surface contamination (on your skin and gear) comes off with the **Decontamination Kit**. Internal contamination (breathed in) does **not** — it needs **Prussian Blue** chelation. Decon and chelation are not interchangeable. +5. **Prepare with KI, treat with supportive care.** Potassium iodide (**KI**) taken *before* exposure reduces uptake. After a serious dose, casualties need real medical care — IV fluids and blood for the anemia and dehydration, antibiotics if wounds get infected, and time. +6. **A lethal dose is lethal.** Below the top tier, radiation sickness is survivable and recovers slowly on its own. At the lethal tier it will not — that casualty needs to never have been there. + +--- + +## Where to go next + +- [Radiation types & dose](02_radiation_types_and_dose.md) — alpha, beta, gamma, neutron, and the three ways they dose you. +- [Protection & shielding](03_protection_and_shielding.md) — what actually stops what. +- [Radiation sickness](04_radiation_sickness.md) — what a dose does to the body over time. +- [Detection & items](05_detection_and_items.md) — the dosimeter and the full kit list. +- [Treatment & triage](06_treatment_and_triage.md) — decon, chelation, drugs, and a triage flow. +- [Zeus & mission makers](07_zeus_and_MissionMakers.md) — placing sources and every CBA setting. +- [FAQ & troubleshooting](08_faq_and_troubleshooting.md) — the gotchas. + +--- diff --git a/docs/en/Radiation/02_radiation_types_and_dose.md b/docs/en/Radiation/02_radiation_types_and_dose.md new file mode 100644 index 000000000..e27f149e1 --- /dev/null +++ b/docs/en/Radiation/02_radiation_types_and_dose.md @@ -0,0 +1,86 @@ +# Radiation Types & Dose + +Radiation isn't one thing. The system models **four types**, and the type decides almost everything that matters: what stops it, how it hurts you, and whether you even need to worry about it from across the room. A source can emit any mix of the four — a reactor leak is mostly gamma and neutron, fallout is beta and gamma, a dirty bomb is a bit of everything. + +## The four types at a glance + +| Type | Penetration | What stops it | Main threat | Skin burns? | +|------|-------------|---------------|-------------|-------------| +| **Alpha** | Almost none | Skin, clothing, a gas mask | **Inhalation only** — harmless outside, lethal inside | No (minor) | +| **Beta** | Low | A CBRN suit; heavy cover | Skin/surface burns + light whole-body | **Yes** | +| **Gamma** | High | Mass, distance, vehicles | Whole-body dose, penetrates almost everything | No (minor) | +| **Neutron** | Very high | Only thick shielding / vehicles | Whole-body dose, most damaging per Gy | No | + +### Alpha + +Alpha particles can't get through your skin or a layer of cloth, so an alpha source sitting on the ground next to you is, externally, almost harmless. The catch is **inhalation**. Breathe alpha-emitting dust without a gas mask and it lodges inside you, where there's no skin to stop it — and it just *keeps* dosing you, long after you've walked away. + +- **External danger:** essentially none. +- **The real danger:** internal contamination. No mask = you breathe it in and your accumulated dose keeps climbing after you leave. +- **Protection that matters:** a **gas mask**. Nothing else changes much. + +> Alpha is the textbook argument for masking up in any dusty contaminated area even when the geiger reads low — the rate can be modest while the stuff you're inhaling is the part that kills you. + +### Beta + +Beta is the burner. It doesn't penetrate deep, so it dumps its energy in your skin — which means **radiation burns** on exposed body parts, plus a smaller whole-body contribution. Light shielding goes a long way here. + +- **External danger:** skin burns on exposed parts; mild whole-body dose. +- **Protection that matters:** a **full CBRN suit** nearly stops it; a gas mask helps a little; sitting in a vehicle cuts it. +- **Handling note:** picking up a beta source concentrates the burns on your hands and arms — see the carryable source in [Zeus & mission makers](07_zeus_and_MissionMakers.md). + +### Gamma + +Gamma is the one most people picture: high-energy, penetrating, and indifferent to your gas mask. It drives **whole-body dose** — the number that pushes you up the radiation-sickness tiers — and the only real defences are **mass, distance, and getting behind something solid.** + +- **External danger:** whole-body dose, the primary driver of acute radiation syndrome. +- **Protection that matters:** vehicles and terrain (moderate), dedicated rad-gear (some), distance (always). A mask or suit barely touch it. +- **Burns:** negligible — gamma's skin contribution is tiny by design, so a pure gamma source won't cover you in burns. + +### Neutron + +The most penetrating of the lot and the most biologically damaging per unit of dose. Neutron radiation shrugs off masks and suits almost entirely; only the bulk of a vehicle or serious shielding makes a dent. + +- **External danger:** whole-body dose, weighted heavier than gamma for the same rate. +- **Protection that matters:** vehicles and heavy cover, and not much else. +- **Sources:** typically reactor cores and certain weapon scenarios. + +--- + +## The three ways radiation doses you + +The same exposure is split across three separate "books," because they behave completely differently and are treated completely differently. + +``` + A RADIATION SOURCE + | + +------+--------------------+-------------------------+ + | | | + WHOLE-BODY PER-LIMB INTERNAL + (penetrating (skin dose on (breathed-in + gamma/neutron) exposed parts) contamination) + | | | + accumulated dose radiation BURNS keeps dosing you + -> sickness tiers on body parts after you leave + | | | + reduced by reduced by cleared ONLY by + shielding a CBRN suit chelation, never + by washing +``` + +- **Whole-body dose** — the big one. Gamma and neutron pour into this; it's what climbs the [radiation-sickness tiers](04_radiation_sickness.md). Your shielding reduces how fast it accrues. +- **Per-limb skin dose** — beta (and handling a source point-blank) deposit dose on specific body parts. Cross a threshold and you get a **radiation burn** wound on that part, treated like any other burn through ACE/KAT medical. +- **Internal contamination** — breathe in particulates (mostly alpha, some beta) without a mask and you accumulate an internal burden that converts to whole-body dose slowly over time. This is the dose that **keeps rising after you've left the source.** + +--- + +## Dose rate vs accumulated dose (again, because it matters) + +- **Dose rate** (Gy/h) is the field strength where you're standing — the geiger number. It is **not** reduced by your gear, because a geiger measures the environment, not you. +- **Accumulated dose** (Gy) is what your body has absorbed. **This** is reduced by shielding, and it's what makes you sick. + +The practical upshot: to check whether a suit or a vehicle is actually protecting you, don't watch the geiger rate — watch how fast the **accumulated** dose climbs. A good shield barely changes the rate reading but dramatically slows the dose you bank. + +> **Mission makers:** the per-type behaviour — how much each type weights into whole-body vs skin vs inhalation, and how each piece of gear shields it — is defined in the type *profiles* and is fully tunable. See the [profiles note in Zeus & mission makers](07_zeus_and_MissionMakers.md). + +--- diff --git a/docs/en/Radiation/03_protection_and_shielding.md b/docs/en/Radiation/03_protection_and_shielding.md new file mode 100644 index 000000000..727efc946 --- /dev/null +++ b/docs/en/Radiation/03_protection_and_shielding.md @@ -0,0 +1,67 @@ +# Protection & Shielding + +There is no single "radiation suit" that makes you immune. Different gear stops different types, and the most penetrating types (gamma, neutron) aren't really stopped by anything you can *wear* — only by mass, distance, and cover. Shielding here is about **slowing the dose you accumulate**, not switching the danger off. + +## The shielding matrix + +How much each piece of gear protects you, by type. "Strong" means it cuts the absorbed dose hard; "none" means don't bother. + +| Type | Gas mask | Full CBRN suit | Rad-gear uniform | Vehicle / cover | +|------|----------|----------------|------------------|-----------------| +| **Alpha** | **Decisive** (stops inhalation) | Decisive | Decisive | Decisive | +| **Beta** | Some | **Strong** | Strong | Good | +| **Gamma** | Negligible | Slight | Moderate | Moderate | +| **Neutron** | None | Negligible | Some | Some | + +A few things to read out of that table: + +- **Alpha** is all-or-nothing and it's about your airway. With a mask you barely accumulate anything; without one you breathe it in. Every other piece of gear "stops" alpha too, but the mask is the one that matters because inhalation is the real route. +- **Beta** is where a CBRN suit earns its keep — it nearly stops beta and saves you from the burns. A mask alone won't. +- **Gamma and neutron** can't be out-dressed. The honest answers are **distance**, **putting mass between you and the source**, and **time spent**. A vehicle helps; a uniform doesn't do much. + +> **The key nuance, one more time:** your gear reduces the **accumulated dose**, not the geiger **rate**. Standing in a gamma field in a vehicle, the dosimeter rate looks the same — but the dose you're banking is lower. Judge protection by the dose total, not the rate. + +### What counts as "rad-gear" + +Rad-gear is a mission-defined whitelist of uniforms that count as radiation-protective, separate from the CBRN suit list. Out of the box it's empty — mission makers populate it via the *Radiation-protective uniforms* CBA setting (see [Zeus & mission makers](07_zeus_and_MissionMakers.md)). It's the lever for adding whatever anti-rad suits your loadout mods provide. + +The gas mask and full CBRN suit are the **same items** the [Chemical](../Chemical/02_protection.md) side uses — a worn, filtered mask and a whitelisted CBRN uniform. Radiation doesn't add new wearables; it reuses the CBRN kit and adds the uniform whitelist on top. + +--- + +## Contamination: external vs internal + +This split is the heart of radiation treatment, so it gets its own section. There are **two** kinds of contamination and they could not be more different. + +### External (surface) contamination + +Radioactive dust settling on your skin and gear. It: + +- **Reads on a geiger** — it makes *you* a weak source, so your own dosimeter keeps clicking even after you've left the area. +- **Doses you and the people next to you** (see cross-contamination below). +- **Comes off with the Decontamination Kit.** Washing it off is the whole fix. +- Slowly weathers away on its own over time. + +### Internal contamination + +Radioactive material you've **breathed in** (mostly from alpha/beta dust without a mask). It: + +- **Does not read on a geiger** — it's inside you, invisible to a survey. +- **Keeps converting to whole-body dose** for a long time, so your accumulated dose climbs even in clean air. +- **Cannot be washed off.** Decon does nothing. It needs **Prussian Blue** chelation to speed elimination, or your body slowly clears it on its own. + +> **The trap:** a casualty walks out of a contaminated area, you decon them, the geiger goes quiet — and they keep getting sicker. That's internal contamination. Decon cleaned the surface; the dose is coming from the inside. Reach for Prussian Blue, not the decon kit. + +--- + +## Cross-contamination + +A contaminated casualty isn't just a patient — they're a **source**. Surface contamination makes a unit emit a weak beta/gamma field of their own, which means: + +- Their **own** dosimeter reads hot even in clean air. +- **Medics treating them accumulate dose**, and a clean responder standing next to a contaminated casualty will see their own geiger tick up. +- A **rad survey** on the casualty (see [Detection & items](05_detection_and_items.md)) reads their contamination level and dominant type so you know what you're dealing with. + +The fix is the same: **decon the casualty** to remove the surface contamination, and the field they emit disappears with it. Until then, treat them like the hot object they are — work fast, and don't loiter. + +--- diff --git a/docs/en/Radiation/04_radiation_sickness.md b/docs/en/Radiation/04_radiation_sickness.md new file mode 100644 index 000000000..7983de37c --- /dev/null +++ b/docs/en/Radiation/04_radiation_sickness.md @@ -0,0 +1,89 @@ +# Radiation Sickness + +Acute Radiation Syndrome (ARS) is what a dose actually *does* to a body, and it's the deepest part of the system. Rather than a health bar ticking down, a serious dose sets off a staged cascade through the body's systems — blood, gut, brain — each on its own clock, each hooking into KAT's existing medical sims so the casualty genuinely behaves like someone who's been irradiated. + +The important mental model: **the dose lands in an instant, but the sickness unfolds over minutes.** Someone can soak a fatal dose, feel only queasy, and seem fine right up until the systems start failing. + +## The tier ladder + +Your accumulated dose maps to a severity **tier**, and the tier decides which syndromes switch on. Defaults shown — every threshold is configurable. + +| Tier | Dose (default) | Name | What switches on | +|------|----------------|------|------------------| +| **0** | < 1 Gy | None | Nothing | +| **1** | 1–2 Gy | Mild (prodromal) | Nausea/vomiting, pain, fever begins | +| **2** | 2–4 Gy | Moderate (hematopoietic) | Marrow suppression → anemia, won't-clot bleeding, infection risk | +| **3** | 4–6 Gy | Severe (GI) | Dehydration, blood-gas acidosis, heavy vomiting | +| **4** | ≥ 6 Gy | Lethal (neurovascular) | Hypotension, seizures, collapse → cardiac arrest | + +Higher tiers don't replace the lower ones — they **stack on top**, and they arrive **faster** (the latent period compresses as the dose climbs, mirroring the real-world "time to vomiting" biomarker that medics use to estimate dose). + +``` + DOSE ABSORBED + | + [accumulates] --> crosses 1 Gy --> TIER 1 prodromal (nausea, fever) + | | + | crosses 2 Gy --> TIER 2 marrow fails + | (anemia, bleeding, infection) + | | + | crosses 4 Gy --> TIER 3 gut fails + | (dehydration, acidosis) + | | + | crosses 6 Gy --> TIER 4 brain/circulation fails + | (hypotension -> collapse -> arrest) + v + higher dose = shorter time before each stage hits +``` + +--- + +## The syndromes, in plain terms + +### Prodromal (tier 1+) +The early warning. Nausea and vomiting, a creeping rise in pain, and the start of a fever. It's miserable but survivable — and it's the body telling you the real damage is already done and the clock is running. + +### Hematopoietic — the marrow (tier 2+) +The classic radiation kill mechanism, just slower than the dramatic stuff. Your bone marrow stops keeping up, and three things follow: + +- **Anemia** — your blood volume slowly falls and you can't replace it. A wound that would normally be survivable becomes a problem because you can't rebuild what you lose. +- **Thrombocytopenia** — your blood won't clot properly. Bleeding that should stop with a bandage keeps going. +- **Immunosuppression** — your immune system is on the floor, which opens the door to **wound infection** (below). + +### Gastrointestinal — the gut (tier 3+) +Now it's serious. Fluid pours out of the body (dehydration → falling blood volume), the blood chemistry tips into **acidosis**, and the vomiting becomes relentless. This is the tier where casualties start sliding toward hypovolemic shock. + +### Neurovascular / CNS — the lethal tier (tier 4) +Blood pressure craters (**hypotension**), brief **seizures** hit, and the casualty collapses into unconsciousness and then cardiac arrest. **This tier will not recover on its own** — but it is *not* an automatic death sentence: with a hard, sustained intensive-care effort a lethal casualty can be pulled back. See [Treatment & triage → Intensive care for lethal doses](06_treatment_and_triage.md#intensive-care-for-lethal-doses). Left alone, though, they die. + +### Systemic — fever & the screen +Running underneath all of it: a **fever** that climbs with severity, and a **visual effect** — the world desaturates into a sickly grade as you get worse (toggleable, on by default). The visual is your gut-feel warning when you're not staring at the dosimeter. + +--- + +## Recovery + +Here's the merciful part: **below the lethal tier, radiation sickness heals on its own.** Once you're out of the radiation (no field, no internal contamination left), your sickness slowly winds back down over minutes — marrow recovers, fever breaks, blood pressure normalises, and the tier ticks back to zero. + +- The **accumulated dose** on your dosimeter stays where it is — that's your permanent exposure record — but the *sickness* it caused fades. +- **Filgrastim** speeds this up considerably (see [Treatment](06_treatment_and_triage.md)). +- The **lethal tier does not spontaneously recover** — it only comes back with the active [intensive-care protocol](06_treatment_and_triage.md#intensive-care-for-lethal-doses). Everything below it heals on its own, given time and support. + +--- + +## Wound infection & sepsis + +When your immune system is suppressed (tier 2+) and you have **open or bandaged wounds**, those wounds can become **infected**. Once infected: + +- Pain and fever climb, and the wound bleeds in a way that drags your blood volume down. +- Left untreated, the infection worsens into **sepsis** — and sepsis here is **lethal**. A casualty who survives the radiation itself can still die of the infection it let in. This is the realistic sting in the tail of marrow failure. +- **Antibiotics** clear it. It also resolves on its own *if* the casualty's immunity recovers first — so it's a race between your immune system coming back and the infection getting ahead of it. + +> **Mission makers:** infection can be switched off entirely with the *Enable wound infection* setting if you don't want sepsis in your mission. + +--- + +## A note for mission makers: this rides on other systems + +The physiology layers drive **real KAT medical subsystems** — blood volume, coagulation, blood gas, blood pressure, body temperature. If a subsystem is disabled in the addon options, the matching radiation effect simply doesn't fire (cleanly, no errors), and the rest still work. Which layer needs which subsystem is laid out in the [dependency table in Zeus & mission makers](07_zeus_and_MissionMakers.md). All of them are on by default. + +--- diff --git a/docs/en/Radiation/05_detection_and_items.md b/docs/en/Radiation/05_detection_and_items.md new file mode 100644 index 000000000..e04be5ad6 --- /dev/null +++ b/docs/en/Radiation/05_detection_and_items.md @@ -0,0 +1,68 @@ +# Detection & Equipment + +You cannot see, smell, or feel radiation. Without a device you have no idea whether the room you just walked into is harmless or already killing you — so detection isn't optional here the way it sometimes is with a visible gas cloud. + +## The Dosimeter (your geiger) + +The `KAT_Dosimeter` is a worn device (watch slot, like the chemical JCAD). It's your eyes for radiation: a small HUD with the dose readout, plus the classic geiger clicks. + +**Turning it on** — three independent steps, mirroring how the JCAD works: + +1. **Show the HUD** — press the dosimeter key (**P** by default) to bring the readout up. +2. **Enable the dosimeter** — a self-action that switches on the live dose-*rate* reading. Until you do this, the HUD shows your accumulated dose but the rate reads `--`. +3. **Enable the sound** — a separate self-action that turns on the geiger clicks. The clicks get faster as the dose rate climbs, and go silent when you're in clean air. + +There are matching **Disable** / **Sound off** self-actions to turn each back off. + +**What it shows:** + +- **Accumulated dose (Gy)** — always visible. Your running total of absorbed radiation. This is the number that decides how sick you get. +- **Dose rate (Gy/h)** — visible once enabled. How hot your current spot is. Remember: this reads the *field*, not what you absorb, so it ignores your shielding. + +> The geiger reads the environment, so it'll keep clicking if **you** are contaminated even in clean air — that's the surface contamination making you a source. If the clicks won't stop after you've left a zone, survey/decon yourself. + +> **Asset note:** the dosimeter currently borrows the chemical detector's model and the geiger sounds reuse the detector's chime samples as placeholders. The numbers and behaviour are real; dedicated art and click audio are planned. + +## Rad Survey (diagnostic) + +A medical action — **Radiation Survey** — that points the dosimeter at a casualty and reports: + +- their **surface contamination** level (as a %), +- the **dominant radiation type** they're carrying, +- and the **ambient dose rate** at them. + +Requires a dosimeter in your kit. Use it on a casualty before you start treating to know whether you need to decon them (and to know whether *you're* about to get dosed working on them). + +## Dose Estimation (triage diagnostic) + +A second medical action — **Estimate Radiation Dose** — for triage. It reads the casualty's exposure and reports: + +- their **exact accumulated dose** in Gy, +- a **prognosis** band (from "no ARS expected" up to "likely lethal without intensive treatment"), +- and the **time-to-vomiting** biomarker, if they've vomited. + +This is your tool for deciding who's salvageable and who isn't when you have more casualties than supplies. + +--- + +## Equipment & Items + +Everything radiation-related, plus the shared decon kit. All available through ACE Arsenal. + +| Item | Classname | Purpose | How to use | +|------|-----------|---------|------------| +| Dosimeter | `KAT_Dosimeter` | Reads dose rate + accumulated dose; geiger clicks | Watch slot; key **P** + self-actions to enable/sound | +| Potassium Iodide (KI) | `kat_potassiumIodide` | **Prophylaxis** — reduces uptake if taken before/early | *Take Potassium Iodide* (self + medic) | +| Prussian Blue | `kat_prussianBlue` | **Chelation** — speeds clearing of internal contamination | *Administer Prussian Blue* (self + medic) | +| Antibiotics | `kat_antibiotics` | Fights radiation wound infection / sepsis | *Administer Antibiotics* (self + medic) | +| Filgrastim (G-CSF) | `kat_filgrastim` | Speeds marrow / sickness recovery | *Administer Filgrastim* (self + medic) | +| Antiemetic | `kat_antiemetic` | Suppresses radiation-sickness vomiting | *Administer Antiemetic* (self + medic) | +| Stem-Cell / Marrow Rescue | `kat_stemCells` | The pivotal cure for a **lethal** dose — enables intensive-care recovery | *Administer Stem-Cell Rescue* (**medic only**, lethal casualty) | +| Decontamination Kit | `kat_decon_kit` | Removes **surface** contamination (shared with Chemical) | *Decontaminate* (shown when contaminated) | +| Radioactive Source | `kat_radSource` | A carryable/placeable point source | Editor/Zeus object; ACE *Pick up* / *Drop* | + +> The decon kit and the CBRN mask/suit are the **same items** the [Chemical](../Chemical/05_detection_identification_items.md) side uses — radiation reuses them rather than adding duplicates. The drugs and the dosimeter are radiation's own additions. + +> **What decon does and doesn't do:** the decon kit clears **surface** contamination only. It will not touch internal contamination (use Prussian Blue) and it does nothing to the dose you've already absorbed. See [Treatment & triage](06_treatment_and_triage.md). + +--- diff --git a/docs/en/Radiation/06_treatment_and_triage.md b/docs/en/Radiation/06_treatment_and_triage.md new file mode 100644 index 000000000..6acdd8524 --- /dev/null +++ b/docs/en/Radiation/06_treatment_and_triage.md @@ -0,0 +1,120 @@ +# Treatment & Triage + +Radiation treatment is less about a single antidote and more about managing a casualty through a sickness that plays out over time. There's no "cure the radiation" button — there's removing what's still dosing them, slowing the damage, and supporting the body's systems while it recovers (or deciding it can't). + +## The one distinction that runs everything: decon vs chelation + +Two kinds of contamination, two completely separate cures. Mixing them up is the classic mistake. + +| Contamination | Where it is | Cleared by | NOT cleared by | +|---------------|-------------|-----------|----------------| +| **Surface (external)** | On skin & gear | **Decontamination Kit** | Prussian Blue | +| **Internal** | Breathed in, inside the body | **Prussian Blue** (chelation) | The decon kit / washing | + +- **Decon** scrubs the surface. It stops the casualty reading hot on a geiger and stops them cross-contaminating others. +- **Prussian Blue** chelates — it binds internal radionuclides so the body clears them faster, cutting off the internal dose that otherwise keeps climbing for ages. + +Neither one undoes dose already absorbed. They stop *further* dosing from contamination; the sickness from what's already in still has to be ridden out. + +--- + +## Treatment reference + +Match what you've found to what you reach for. + +| What you see / know | Use | Notes | +|---------------------|-----|-------| +| Casualty reads hot on a survey; geiger won't stop | **Decontamination Kit** | Clears surface contamination + stops cross-contamination | +| Dose keeps climbing in clean air (breathed it in) | **Prussian Blue** | Chelation; the only thing that touches internal contamination | +| *Before* entering a hot area | **Potassium Iodide (KI)** | Prophylactic — reduces uptake; useless after the fact | +| Vomiting from radiation sickness | **Antiemetic** | Suppresses the vomiting for a while | +| Infected wound / heading toward sepsis | **Antibiotics** | Clears infection; essential if infection is enabled | +| Slow to recover after a survivable dose | **Filgrastim (G-CSF)** | Speeds marrow/sickness recovery | +| Anemia, low blood volume, dehydration | **IV Blood / Saline** | Standard KAT fluids — radiation drains blood volume, so top it up | +| Radiation burns, open wounds | Standard ACE/KAT wound care | Treat as ordinary injuries | + +> **Timing is everything with the two anti-rad drugs.** KI only helps **before** uptake — it's a pre-exposure tablet, not a treatment. Prussian Blue is the opposite — it's for **after**, to speed clearing what's already inside. Carry KI for planned entries into hot zones; carry Prussian Blue for after the fact. + +> **Tracking what you've given:** every radiation drug logs to the patient's **triage card** in the medical menu when administered (with a tally on repeat doses), so you can see at a glance what's already on board. + +--- + +## Treating a casualty — quick flow + +``` + Radiation casualty (down or sick) + | + 1. MAKE IT SAFE FOR YOU + Survey them. If they read hot, DECON first — a contaminated + casualty doses you the whole time you're working on them. + | + 2. STOP THE DOSING + - DECON KIT -> clears surface contamination + - PRUSSIAN BLUE -> clears internal (inhaled) contamination + - move them clear of any radiation field + (until dosing stops, nothing you do below will hold) + | + 3. ESTIMATE THE DOSE (Estimate Radiation Dose action) + | + +-----+----------------------------------------+ + | | + SURVIVABLE (mild–severe) LETHAL (top tier, >6 Gy) + | | + supportive care: INTENSIVE CARE (hard, ~15 min): + - IV blood/saline (anemia, fluids) keep alive: IV or vasopressor + - antibiotics (if infected) cure (all at once, sustained): + - antiemetic (vomiting) filgrastim + antibiotics + - filgrastim (speeds recovery) + STEM-CELL RESCUE + | (source already removed) + recovers over minutes; -> see "Intensive care for + accumulated dose stays on record lethal doses" below + | + 4. MOP UP + Treat radiation burns and open wounds as normal ACE/KAT injuries. +``` + +The short version of supportive care for a survivable casualty: **stop the contamination (decon/chelate), replace the blood they're losing (IV), keep infection out (antibiotics), make them comfortable (antiemetic), and speed the marrow back (filgrastim).** Then time does the rest. A **lethal** casualty needs all of that *plus* the sustained intensive-care protocol below — they will not recover on supportive care alone. + +--- + +## Intensive care for lethal doses + +A lethal dose (the top tier, ≥ 6 Gy by default) **will not recover on its own** — but it's survivable if a medic commits to a hard, ~15-minute intensive-care fight. There are two layers: keep them alive, then actually cure them. (Mission makers can switch this off with *Lethal dose curable*, making the top tier terminal again.) + +### Layer 1 — keep them alive +A lethal casualty collapses unconscious and starts a hidden "time to arrest" clock. **Circulatory support holds that clock off:** + +- an **active IV line** (blood or saline), **or** +- a **vasopressor** in their system (epinephrine / norepinephrine). + +Let support lapse and the clock runs out → **cardiac arrest**, at which point it's a full CPR / defibrillator / rhythm-management emergency (the normal cardiac-arrest system, advanced rhythm and all). Support is the bare minimum just to stop them dying — it does **not** cure anything. + +### Layer 2 — actually cure them +Their radiation sickness only winds down while the **entire intensive-care stack is sustained at once**: + +1. **Source removed** — fully deconned *and* chelated (Prussian blue), out of any field. While any dose is still coming in, nothing improves. +2. **Circulatory support** — the IV or vasopressor from Layer 1. +3. **Filgrastim** — kept topped up. +4. **Antibiotics** — kept topped up (and the only thing stopping sepsis finishing them off in parallel). +5. **Stem-Cell / Marrow Rescue** (`kat_stemCells`) — the pivot. Medic-only, slow to administer, and re-dosed as it wears off. **Without it, full support only *holds* them — alive but never improving.** With it, the sickness finally starts to clear. + +Sustain all five and severity grinds down over roughly **12–16 minutes**, after which they drop out of the danger zone and finish recovering normally. Drop any one and the cure **stalls**. + +### They stay unstable until it's done +Bringing someone back from arrest doesn't make them safe. While they're still heavily irradiated their system keeps **crashing back into arrest** — even on an IV — and (with advanced rhythm on) throws **VF/VT far more often**. Both taper off as the cure progresses, so the way to *stop* the re-crashes is to push the cure down, not just park them on a pressor. Expect to resuscitate the same patient more than once before they're out of the woods. + +> This is deliberately brutal: one medic with a couple of items can't do it. It takes the full kit, constant re-dosing, and someone watching the monitor for the next arrest — a genuine team effort to save one person. + +--- + +## Prophylaxis: the smart play + +The cheapest treatment is the one you take before anything happens. If you know you're going into a contaminated area: + +- **Take KI first** — it reduces how much radioiodine your body takes up while you're in there. +- **Mask and suit up** per the [shielding rules](03_protection_and_shielding.md) — the mask especially, to keep internal contamination out. +- **Carry a dosimeter and watch the accumulated dose**, not just the rate. Leave before it climbs into the tiers you can't walk back from. + +A prepared unit can work a hot zone and recover. An unprepared one finds out about the dose when the vomiting starts. + +--- diff --git a/docs/en/Radiation/07_zeus_and_MissionMakers.md b/docs/en/Radiation/07_zeus_and_MissionMakers.md new file mode 100644 index 000000000..68e57a2d3 --- /dev/null +++ b/docs/en/Radiation/07_zeus_and_MissionMakers.md @@ -0,0 +1,179 @@ +# Zeus & Mission Makers + +How to put radiation on the map, and how to tune every part of it. + +## Placing radiation sources + +A source emits any mix of the four types, each with its own strength in **Gy/h**. You author that mix either by hand (the four per-type fields) or by picking a **preset** that fills them for you. + +### Radiation module (`kat_module_radiation`) + +In the editor under **Modules → KAT**, and the same module is available in **Zeus** as a curator module. Its attributes: + +- **Preset** — a dropdown that fills the four strength fields for you. Pick `Custom` to use the fields directly, or any named preset to auto-fill them. +- **Alpha / Beta / Gamma / Neutron (Gy/h)** — the per-type strengths. Used when Preset is `Custom`; a named preset overrides them. +- **Radius** — area size in metres. +- **Point source** — if enabled, the source falls off with the inverse-square law (a hot spot) instead of linearly across the radius (an area/zone). + +Sync the module to a `LocationArea` trigger for a zone, or enable **Point source** for a localised hotspot. The **Zeus** version opens the same attributes dialog — picking a preset there auto-fills the four fields before you confirm. + +### Source presets + +| Preset | Alpha | Beta | Gamma | Neutron | Reads like | +|--------|-------|------|-------|---------|-----------| +| **Custom** | — | — | — | — | Use the four fields | +| **Cobalt-60** | 0 | 0 | 100 | 0 | Strong sealed gamma source — whole-body dose, no burns | +| **Reactor** | 0 | 0 | 50 | 25 | Reactor core / criticality — deadliest, neutron-heavy | +| **Fallout** | 0 | 400 | 20 | 0 | Lingering area — beta skin burns + slow sickness | +| **Alpha Emitter** | 150 | 10 | 0 | 0 | Inhalation hazard — near-harmless unless breathed in | +| **Dirty Bomb** | 40 | 250 | 50 | 0 | A messy mix — burns, gamma, and inhalation | + +> Strengths are **Gy/h** — the dose rate at the reference point (the centre for zones, ~1 m for point sources). With the defaults, a casualty in a ~500 Gy/h gamma field reaches the lethal tier in roughly 40 seconds; the 100 Gy/h Cobalt-60 preset is a few-minutes hazard; Fallout's heavy beta is what produces skin burns over a few minutes. Scale to the pace you want. +> +> **Note on neutron:** the neutron field is weighted far heavier than the others for whole-body dose (high biological effect), so a small neutron number bites hard — that's why Reactor is the deadliest preset despite modest-looking figures. + +### Carryable radioactive source (`kat_radSource`) + +A placeable object (editor and Zeus) that acts as a **hot beta+gamma point source** you can pick up — think a lost industrial-radiography source. ACE-interact to **Pick up radioactive source**, and held point-blank it concentrates skin dose on your hands and arms (a burn in about a minute) while pouring whole-body dose into you — rapidly lethal unshielded, though a CBRN suit buys you a few minutes to make the carry. **Drop** it to set it back down. Great for "carry the source to the disposal site" objectives. + +> **Asset note:** `kat_radSource` uses a placeholder jerry-can model for now; dedicated art is planned. + +### Quick console source (testing) + +To drop a source at your feet without placing a module — handy for testing — run this as the server: + +```sqf +["kat_chemical_addRadSource", [getPosASL player, 30, [0,0,500,0], "linear", "testRad", {true}, []]] call CBA_fnc_serverEvent; +``` + +The array is `[alpha, beta, gamma, neutron]` in Gy/h. Remove it with: + +```sqf +["kat_chemical_removeRadSource", "testRad"] call CBA_fnc_serverEvent; +``` + +--- + +## Mission Configuration (CBA Settings) + +Everything below lives under **CBA Settings → KAT - ADV Medical: Chemical**, in the **"10. Radiation"** subcategory (radiation shares the chemical addon's settings category). Times are in seconds; dose values in Gray. + +### Master & display + +| Setting | Default | What it does | +|---------|---------|--------------| +| Enable radiation | on | Master switch for the whole system | +| Show sickness messages | on | Whether radiation-sickness hints appear on screen | +| Radiation visual effect | on | The desaturated screen effect while irradiated/sick (client-side) | + +### Dose thresholds (Gy) + +| Setting | Default | What it does | +|---------|---------|--------------| +| Mild dose threshold | 1 | Dose at which mild (prodromal) sickness begins | +| Moderate dose threshold | 2 | Dose at which the hematopoietic tier begins | +| Severe dose threshold | 4 | Dose at which the GI tier begins | +| Lethal dose threshold | 6 | Dose at which the neurovascular (lethal) tier begins | + +### Stage timings + +| Setting | Default | What it does | +|---------|---------|--------------| +| Prodromal delay | 120 | Time to the first prodromal symptoms | +| Hematopoietic delay | 600 | Time to marrow-suppression onset | +| GI delay | 480 | Time to GI-syndrome onset | +| CNS delay | 180 | Time to neurovascular onset | +| Cardiac delay | 300 | Time to the fatal cardiac event | + +> Higher tiers compress these delays automatically — a massive dose makes the stages arrive much faster than a borderline one. + +### Shielding + +| Setting | Default | What it does | +|---------|---------|--------------| +| Mask protection factor | 1.0 | Global effectiveness multiplier for gas-mask shielding | +| CBRN suit protection factor | 1.0 | Global multiplier for CBRN-suit shielding | +| Rad-gear protection factor | 1.0 | Global multiplier for rad-gear-uniform shielding | +| Vehicle protection factor | 1.0 | Global multiplier for vehicle shielding | +| Radiation-protective uniforms | *(empty)* | **Whitelist of uniform classnames that count as rad-gear** | + +> *Radiation-protective uniforms* is the radiation equivalent of the CBRN-suit whitelist — a quoted, comma-separated list of classnames. Populate it with whatever anti-rad suits your loadout mods provide. + +### Contamination + +| Setting | Default | What it does | +|---------|---------|--------------| +| Inhalation factor | 0.1 | How much unmasked exposure becomes internal contamination | +| Internal dose conversion rate | 0.001 | How fast internal contamination converts to whole-body dose | +| Internal decay rate | 0.0005 | How fast the body clears internal contamination on its own | +| Contamination deposition | 0.02 | How fast surface contamination builds up | +| Contamination decay | 0.002 | How fast surface contamination weathers away | +| Cross-contamination strength | 5 | How strong a field a contaminated casualty emits (Gy/h scale) | +| Local exposure distance | 1.5 | Within this range of a point source, skin dose concentrates on arms/hands | +| Skin burn threshold | 5 | Local skin dose per radiation-burn wound | + +### Drugs + +| Setting | Default | What it does | +|---------|---------|--------------| +| KI protection factor | 0.5 | How much KI reduces uptake while active | +| KI duration | 3600 | How long a KI dose protects | +| Chelation duration | 600 | How long Prussian Blue accelerates internal clearance | +| Chelation factor | 5 | How much faster chelation clears internal contamination | +| Antibiotic duration | 600 | How long antibiotics suppress infection | +| Antiemetic duration | 900 | How long an antiemetic suppresses vomiting | +| Filgrastim duration | 1800 | How long filgrastim accelerates recovery | +| Filgrastim recovery multiplier | 3 | How much faster sickness recovers while filgrastim is active | + +### Physiology + +| Setting | Default | What it does | +|---------|---------|--------------| +| Anemia rate (ml/s) | 2 | Blood-volume loss from marrow suppression (scaled by severity) | +| GI fluid loss (ml/s) | 3 | Blood-volume loss from GI dehydration | +| GI acidosis rate | 0.05 | Per-second drop in blood-gas bicarbonate/pH | +| CNS hypotension (mmHg) | 40 | Maximum blood-pressure drop at the lethal tier | +| Maximum fever (°C) | 2 | Peak temperature rise from radiation sickness | +| Recovery rate (Gy/s) | 0.01 | How fast sickness heals once out of radiation (below lethal) | + +### Infection + +| Setting | Default | What it does | +|---------|---------|--------------| +| Enable wound infection | on | Whether immunosuppressed wounds can get infected → sepsis | +| Infection chance | 0.05 | Per-second base chance of infection (scaled by immunosuppression) | +| Infection progression rate | 0.02 | How fast an untreated infection worsens | +| Sepsis blood loss (ml/s) | 15 | Blood loss at full infection — drives lethal septic shock | + +### Lethal-tier intensive care + +| Setting | Default | What it does | +|---------|---------|--------------| +| Lethal dose curable | on | If on, a lethal casualty can be saved with sustained intensive care; if off, the lethal tier is terminal | +| Collapse time (unsupported) | 150 | Seconds a critical casualty lasts without IV/vasopressor before cardiac arrest | +| Intensive-care recovery rate (Gy/s) | 0.006 | How fast a lethal casualty's sickness clears under the full stack (lower = harder) | +| Stem-cell rescue duration | 300 | How long one stem-cell dose enables recovery before re-dosing | +| Re-crash chance | 0.05 | Per-tick chance (at full severity) of crashing back into arrest; tapers with the cure, halved on life support | +| Shockable rhythm bias | 0.7 | Chance (at full severity, Advanced Rhythm on) a radiation arrest is VF/VT vs asystole/PEA | +| Stem-cell rescue required trait | Medics | Who can administer the stem-cell rescue (Anyone / Medics / Doctors) | +| Intensive-care readout | off | Show a status line in the medical menu for a critical casualty (cure progress + missing supports; never the arrest timer) | + +> The lethal-tier cure also leans on the **Circulation** cardiac-arrest system and, when enabled, **Advanced Rhythm** (`kat_circulation_AdvRhythm`) for the VF/VT behaviour — it cooperates with them rather than running its own death timer. + +--- + +## Subsystem dependencies (important) + +The physiology layers drive **other KAT medical subsystems**. If one is disabled in addon options, the matching radiation effect is **cleanly skipped** (no errors) and everything else keeps working. They all default **ON**, so this is usually a "don't accidentally turn it off" check. + +| Radiation effect | Needs this subsystem ON | Setting | +|------------------|------------------------|---------| +| Thrombocytopenia (won't-clot bleeding) | KAT Pharmacy → Coagulation | `kat_pharma_coagulation` | +| Anemia regeneration impairment | KAT Vitals → Fluid Shift | `kat_vitals_enableFluidShift` | +| GI acidosis (blood-gas pH/HCO3) | KAT Breathing → Enable | `kat_breathing_enable` | +| CNS hypotension (blood pressure) | KAT Circulation → Enable | `kat_circulation_enable` | +| Fever (body temperature) | KAT Hypothermia → Enable Hypothermia | `kat_hypothermia_hypothermiaActive` | + +> To exercise the full system on **AI** casualties, keep **KAT Vitals → Simple Medical OFF** — simple medical bypasses the detailed vitals loop the radiation effects ride on. Players always get the full sim. + +--- diff --git a/docs/en/Radiation/08_faq_and_troubleshooting.md b/docs/en/Radiation/08_faq_and_troubleshooting.md new file mode 100644 index 000000000..5f3e02518 --- /dev/null +++ b/docs/en/Radiation/08_faq_and_troubleshooting.md @@ -0,0 +1,34 @@ +## FAQ & Troubleshooting + +### **My geiger is screaming but I'm not taking any damage. Is it broken?** +No — that's working as intended, and it might be your gear doing its job. The geiger reads the **dose rate** (the field around you), which your shielding does *not* change. What your shielding reduces is the **accumulated dose** — the Gy total you actually soak up. Watch that number: if it's barely climbing while the rate is high, your suit/vehicle is protecting you. (And if you're in a pure-gamma field with only a mask on, the rate being scary while the dose climbs fast is *also* correct — a mask doesn't stop gamma.) + +### **I left the radiation hours ago but my dose is still going up.** +You breathed it in. That's **internal contamination** — radioactive material inside you that keeps converting to dose long after you've left. A geiger and a decon kit can't help with it because it isn't on your surface. Use **Prussian Blue** to chelate it out, or wait for your body to slowly clear it. + +### **I deconned the casualty but their dose didn't drop.** +Decon only removes **surface** contamination — it stops them reading hot and cross-contaminating others, but it does nothing to dose already absorbed, and nothing to internal contamination. If their dose is still climbing, it's internal (use Prussian Blue). If it's just high but stable, that's the permanent record of what they absorbed — there's no scrubbing that off, only treating the sickness. + +### **A pure gamma source gave me almost no burns. Shouldn't radiation burn me?** +Not gamma. Skin/radiation burns come from **beta** and from **handling a source point-blank**. Gamma and neutron drive whole-body dose, not skin dose, so a gamma zone makes you *sick* without covering you in burns. Stand in a beta field — or pick up a `kat_radSource` — to see burns. + +### **I walked into a hot zone and died almost instantly. Is that normal?** +Only if the source is enormous. Source strength is in **Gy/h**, and a very high value (say several hundred) will push you past the 6 Gy lethal threshold in well under a minute. If you want a survivable hazard, lower the source strength, raise the dose thresholds, or both — see [Zeus & mission makers](07_zeus_and_MissionMakers.md). + +### **One of the sickness effects does nothing — no fever / no blood-pressure drop / bleeding still clots.** +That effect's host subsystem is probably disabled. The physiology layers ride on other KAT systems: fever needs **Hypothermia**, acidosis needs **Breathing**, hypotension needs **Circulation**, won't-clot bleeding needs **Pharmacy Coagulation**, and anemia regen needs **Vitals Fluid Shift**. They're all on by default — check none got switched off. (Radiation skips a disabled layer cleanly; it won't error.) + +### **My AI test casualty ignores all the physiology.** +Turn **Simple Medical OFF** in KAT Vitals. Simple medical bypasses the detailed vitals loop that the radiation effects hook into. Players always get the full sim; AI only do when simple medical is off. + +### **The casualty recovered from severe radiation sickness on their own. Bug?** +Intended. Below the lethal tier, sickness heals slowly once the casualty is out of radiation (and clear of internal contamination). **Filgrastim** speeds it up. The **lethal tier** never self-recovers — it's survivable only with the sustained [intensive-care protocol](06_treatment_and_triage.md#intensive-care-for-lethal-doses), not by waiting. Note the *accumulated dose* on the dosimeter stays put — that's the exposure record; it's the sickness that fades, not the history. + +### **A medic treating a contaminated casualty started getting dosed.** +That's cross-contamination, and it's intended. A surface-contaminated casualty emits a weak field of their own. **Decon them** to shut it off — until you do, anyone working on them is standing next to a small source. Survey first, decon, then treat. + +### **The dosimeter clicks won't stop even in clean air.** +You're contaminated — *you* are the source the geiger is reading. Survey yourself and use the decon kit. (If you've turned the dosimeter sound off and it still seems to click, that's the placeholder chime samples — dedicated click audio is planned.) + +### **Is radiation a separate addon I need to enable?** +No. Radiation is part of the **Chemical** addon — same PBO, same CBA settings category (under the "10. Radiation" subcategory). If you have KAT's chemical addon, you have radiation. diff --git a/docs/jp/Radiation/01_Info_and_QuickStart.md b/docs/jp/Radiation/01_Info_and_QuickStart.md new file mode 100644 index 000000000..39670cf1f --- /dev/null +++ b/docs/jp/Radiation/01_Info_and_QuickStart.md @@ -0,0 +1,51 @@ +# Radiation — Player & Mission-Maker Guide + +The **Radiation** system is an extension of the **Chemical** addon — the "R" and "N" in CBRN that the gases left on the table. It lives in the same addon, shares the same CBA settings category, and reuses the same decontamination kit and CBRN gear, so if you've already read the [Chemical guide](../Chemical/01_Info_and_QuickStart.md) a lot of this will feel familiar. If you haven't, the short version is: this mod treats hazards as things you prepare for, not things that simply tick your health down. + +Where the gases are about a cloud you can usually *see* and an antidote you carry, radiation is quieter and slower. You can't smell it, a mask won't stop most of it, and the dose you soak up today can put you in the ground a quarter of an hour from now with nothing visibly wrong in between. The only way to know what you're standing in is to carry a dosimeter and pay attention to it. + +This guide is written for two audiences: + +- **Players / medics** — what the four radiation types do, how to shield against them, and how to treat radiation casualties. +- **Mission makers / Zeus** — how to place radiation sources and how to tune the whole thing through CBA settings. + +> **A note on units.** Dose is measured in **Gray (Gy)**, the real SI unit of absorbed radiation. As a rough yardstick: a couple of Gy makes you sick, around 4 Gy is a coin-flip for survival without treatment, and 6 Gy and up is the danger zone. The defaults are built around those numbers but every threshold is configurable. + +--- + +## How dose works (the one concept to understand) + +There are three different numbers in play, and confusing them is the single most common mistake: + +- **Dose rate** — how *hot* the spot you're standing in is, in **Gy/h**. This is what your dosimeter's geiger reads. It measures the field around you; it does **not** care what you're wearing. +- **Accumulated dose** — how much radiation your body has actually *absorbed*, in **Gy**. This is what makes you sick, and **this** is what your shielding reduces. It only ever goes up while you're exposed, and it's permanent. +- **Internal contamination** — radioactive material you've **breathed in**. It sits inside you and keeps delivering dose for a long time after you've left the area. Washing it off does nothing; it has to be chelated out or wait out your body clearing it. + +So: the geiger screaming doesn't mean you're being hurt (your suit might be eating it), and the geiger going quiet doesn't mean you're safe (you might be carrying contamination inside you). Watch the *accumulated* dose, not just the rate. + +--- + +## Quick Start + +If you only read one section, read this one. + +1. **Carry a dosimeter.** The `KAT_Dosimeter` (watch slot) is your only way to see dose rate and accumulated dose. Turn it on, turn the sound on, and let the clicks warn you before the numbers do. +2. **Shielding depends on the type.** There's no single "rad suit." A gas mask matters for alpha (inhalation) and helps against beta; a full CBRN suit stops beta and dents gamma; vehicles and terrain are what cut gamma and neutron. Distance is always your friend. +3. **Dose is cumulative — manage your time.** You can't "heal" the radiation you've already absorbed by leaving. Treat a hot zone like a budget: get in, do the job, get out before the accumulated dose climbs into the danger tiers. +4. **Two kinds of contamination, two different cures.** Surface contamination (on your skin and gear) comes off with the **Decontamination Kit**. Internal contamination (breathed in) does **not** — it needs **Prussian Blue** chelation. Decon and chelation are not interchangeable. +5. **Prepare with KI, treat with supportive care.** Potassium iodide (**KI**) taken *before* exposure reduces uptake. After a serious dose, casualties need real medical care — IV fluids and blood for the anemia and dehydration, antibiotics if wounds get infected, and time. +6. **A lethal dose is lethal.** Below the top tier, radiation sickness is survivable and recovers slowly on its own. At the lethal tier it will not — that casualty needs to never have been there. + +--- + +## Where to go next + +- [Radiation types & dose](02_radiation_types_and_dose.md) — alpha, beta, gamma, neutron, and the three ways they dose you. +- [Protection & shielding](03_protection_and_shielding.md) — what actually stops what. +- [Radiation sickness](04_radiation_sickness.md) — what a dose does to the body over time. +- [Detection & items](05_detection_and_items.md) — the dosimeter and the full kit list. +- [Treatment & triage](06_treatment_and_triage.md) — decon, chelation, drugs, and a triage flow. +- [Zeus & mission makers](07_zeus_and_MissionMakers.md) — placing sources and every CBA setting. +- [FAQ & troubleshooting](08_faq_and_troubleshooting.md) — the gotchas. + +--- diff --git a/docs/jp/Radiation/02_radiation_types_and_dose.md b/docs/jp/Radiation/02_radiation_types_and_dose.md new file mode 100644 index 000000000..e27f149e1 --- /dev/null +++ b/docs/jp/Radiation/02_radiation_types_and_dose.md @@ -0,0 +1,86 @@ +# Radiation Types & Dose + +Radiation isn't one thing. The system models **four types**, and the type decides almost everything that matters: what stops it, how it hurts you, and whether you even need to worry about it from across the room. A source can emit any mix of the four — a reactor leak is mostly gamma and neutron, fallout is beta and gamma, a dirty bomb is a bit of everything. + +## The four types at a glance + +| Type | Penetration | What stops it | Main threat | Skin burns? | +|------|-------------|---------------|-------------|-------------| +| **Alpha** | Almost none | Skin, clothing, a gas mask | **Inhalation only** — harmless outside, lethal inside | No (minor) | +| **Beta** | Low | A CBRN suit; heavy cover | Skin/surface burns + light whole-body | **Yes** | +| **Gamma** | High | Mass, distance, vehicles | Whole-body dose, penetrates almost everything | No (minor) | +| **Neutron** | Very high | Only thick shielding / vehicles | Whole-body dose, most damaging per Gy | No | + +### Alpha + +Alpha particles can't get through your skin or a layer of cloth, so an alpha source sitting on the ground next to you is, externally, almost harmless. The catch is **inhalation**. Breathe alpha-emitting dust without a gas mask and it lodges inside you, where there's no skin to stop it — and it just *keeps* dosing you, long after you've walked away. + +- **External danger:** essentially none. +- **The real danger:** internal contamination. No mask = you breathe it in and your accumulated dose keeps climbing after you leave. +- **Protection that matters:** a **gas mask**. Nothing else changes much. + +> Alpha is the textbook argument for masking up in any dusty contaminated area even when the geiger reads low — the rate can be modest while the stuff you're inhaling is the part that kills you. + +### Beta + +Beta is the burner. It doesn't penetrate deep, so it dumps its energy in your skin — which means **radiation burns** on exposed body parts, plus a smaller whole-body contribution. Light shielding goes a long way here. + +- **External danger:** skin burns on exposed parts; mild whole-body dose. +- **Protection that matters:** a **full CBRN suit** nearly stops it; a gas mask helps a little; sitting in a vehicle cuts it. +- **Handling note:** picking up a beta source concentrates the burns on your hands and arms — see the carryable source in [Zeus & mission makers](07_zeus_and_MissionMakers.md). + +### Gamma + +Gamma is the one most people picture: high-energy, penetrating, and indifferent to your gas mask. It drives **whole-body dose** — the number that pushes you up the radiation-sickness tiers — and the only real defences are **mass, distance, and getting behind something solid.** + +- **External danger:** whole-body dose, the primary driver of acute radiation syndrome. +- **Protection that matters:** vehicles and terrain (moderate), dedicated rad-gear (some), distance (always). A mask or suit barely touch it. +- **Burns:** negligible — gamma's skin contribution is tiny by design, so a pure gamma source won't cover you in burns. + +### Neutron + +The most penetrating of the lot and the most biologically damaging per unit of dose. Neutron radiation shrugs off masks and suits almost entirely; only the bulk of a vehicle or serious shielding makes a dent. + +- **External danger:** whole-body dose, weighted heavier than gamma for the same rate. +- **Protection that matters:** vehicles and heavy cover, and not much else. +- **Sources:** typically reactor cores and certain weapon scenarios. + +--- + +## The three ways radiation doses you + +The same exposure is split across three separate "books," because they behave completely differently and are treated completely differently. + +``` + A RADIATION SOURCE + | + +------+--------------------+-------------------------+ + | | | + WHOLE-BODY PER-LIMB INTERNAL + (penetrating (skin dose on (breathed-in + gamma/neutron) exposed parts) contamination) + | | | + accumulated dose radiation BURNS keeps dosing you + -> sickness tiers on body parts after you leave + | | | + reduced by reduced by cleared ONLY by + shielding a CBRN suit chelation, never + by washing +``` + +- **Whole-body dose** — the big one. Gamma and neutron pour into this; it's what climbs the [radiation-sickness tiers](04_radiation_sickness.md). Your shielding reduces how fast it accrues. +- **Per-limb skin dose** — beta (and handling a source point-blank) deposit dose on specific body parts. Cross a threshold and you get a **radiation burn** wound on that part, treated like any other burn through ACE/KAT medical. +- **Internal contamination** — breathe in particulates (mostly alpha, some beta) without a mask and you accumulate an internal burden that converts to whole-body dose slowly over time. This is the dose that **keeps rising after you've left the source.** + +--- + +## Dose rate vs accumulated dose (again, because it matters) + +- **Dose rate** (Gy/h) is the field strength where you're standing — the geiger number. It is **not** reduced by your gear, because a geiger measures the environment, not you. +- **Accumulated dose** (Gy) is what your body has absorbed. **This** is reduced by shielding, and it's what makes you sick. + +The practical upshot: to check whether a suit or a vehicle is actually protecting you, don't watch the geiger rate — watch how fast the **accumulated** dose climbs. A good shield barely changes the rate reading but dramatically slows the dose you bank. + +> **Mission makers:** the per-type behaviour — how much each type weights into whole-body vs skin vs inhalation, and how each piece of gear shields it — is defined in the type *profiles* and is fully tunable. See the [profiles note in Zeus & mission makers](07_zeus_and_MissionMakers.md). + +--- diff --git a/docs/jp/Radiation/03_protection_and_shielding.md b/docs/jp/Radiation/03_protection_and_shielding.md new file mode 100644 index 000000000..727efc946 --- /dev/null +++ b/docs/jp/Radiation/03_protection_and_shielding.md @@ -0,0 +1,67 @@ +# Protection & Shielding + +There is no single "radiation suit" that makes you immune. Different gear stops different types, and the most penetrating types (gamma, neutron) aren't really stopped by anything you can *wear* — only by mass, distance, and cover. Shielding here is about **slowing the dose you accumulate**, not switching the danger off. + +## The shielding matrix + +How much each piece of gear protects you, by type. "Strong" means it cuts the absorbed dose hard; "none" means don't bother. + +| Type | Gas mask | Full CBRN suit | Rad-gear uniform | Vehicle / cover | +|------|----------|----------------|------------------|-----------------| +| **Alpha** | **Decisive** (stops inhalation) | Decisive | Decisive | Decisive | +| **Beta** | Some | **Strong** | Strong | Good | +| **Gamma** | Negligible | Slight | Moderate | Moderate | +| **Neutron** | None | Negligible | Some | Some | + +A few things to read out of that table: + +- **Alpha** is all-or-nothing and it's about your airway. With a mask you barely accumulate anything; without one you breathe it in. Every other piece of gear "stops" alpha too, but the mask is the one that matters because inhalation is the real route. +- **Beta** is where a CBRN suit earns its keep — it nearly stops beta and saves you from the burns. A mask alone won't. +- **Gamma and neutron** can't be out-dressed. The honest answers are **distance**, **putting mass between you and the source**, and **time spent**. A vehicle helps; a uniform doesn't do much. + +> **The key nuance, one more time:** your gear reduces the **accumulated dose**, not the geiger **rate**. Standing in a gamma field in a vehicle, the dosimeter rate looks the same — but the dose you're banking is lower. Judge protection by the dose total, not the rate. + +### What counts as "rad-gear" + +Rad-gear is a mission-defined whitelist of uniforms that count as radiation-protective, separate from the CBRN suit list. Out of the box it's empty — mission makers populate it via the *Radiation-protective uniforms* CBA setting (see [Zeus & mission makers](07_zeus_and_MissionMakers.md)). It's the lever for adding whatever anti-rad suits your loadout mods provide. + +The gas mask and full CBRN suit are the **same items** the [Chemical](../Chemical/02_protection.md) side uses — a worn, filtered mask and a whitelisted CBRN uniform. Radiation doesn't add new wearables; it reuses the CBRN kit and adds the uniform whitelist on top. + +--- + +## Contamination: external vs internal + +This split is the heart of radiation treatment, so it gets its own section. There are **two** kinds of contamination and they could not be more different. + +### External (surface) contamination + +Radioactive dust settling on your skin and gear. It: + +- **Reads on a geiger** — it makes *you* a weak source, so your own dosimeter keeps clicking even after you've left the area. +- **Doses you and the people next to you** (see cross-contamination below). +- **Comes off with the Decontamination Kit.** Washing it off is the whole fix. +- Slowly weathers away on its own over time. + +### Internal contamination + +Radioactive material you've **breathed in** (mostly from alpha/beta dust without a mask). It: + +- **Does not read on a geiger** — it's inside you, invisible to a survey. +- **Keeps converting to whole-body dose** for a long time, so your accumulated dose climbs even in clean air. +- **Cannot be washed off.** Decon does nothing. It needs **Prussian Blue** chelation to speed elimination, or your body slowly clears it on its own. + +> **The trap:** a casualty walks out of a contaminated area, you decon them, the geiger goes quiet — and they keep getting sicker. That's internal contamination. Decon cleaned the surface; the dose is coming from the inside. Reach for Prussian Blue, not the decon kit. + +--- + +## Cross-contamination + +A contaminated casualty isn't just a patient — they're a **source**. Surface contamination makes a unit emit a weak beta/gamma field of their own, which means: + +- Their **own** dosimeter reads hot even in clean air. +- **Medics treating them accumulate dose**, and a clean responder standing next to a contaminated casualty will see their own geiger tick up. +- A **rad survey** on the casualty (see [Detection & items](05_detection_and_items.md)) reads their contamination level and dominant type so you know what you're dealing with. + +The fix is the same: **decon the casualty** to remove the surface contamination, and the field they emit disappears with it. Until then, treat them like the hot object they are — work fast, and don't loiter. + +--- diff --git a/docs/jp/Radiation/04_radiation_sickness.md b/docs/jp/Radiation/04_radiation_sickness.md new file mode 100644 index 000000000..7983de37c --- /dev/null +++ b/docs/jp/Radiation/04_radiation_sickness.md @@ -0,0 +1,89 @@ +# Radiation Sickness + +Acute Radiation Syndrome (ARS) is what a dose actually *does* to a body, and it's the deepest part of the system. Rather than a health bar ticking down, a serious dose sets off a staged cascade through the body's systems — blood, gut, brain — each on its own clock, each hooking into KAT's existing medical sims so the casualty genuinely behaves like someone who's been irradiated. + +The important mental model: **the dose lands in an instant, but the sickness unfolds over minutes.** Someone can soak a fatal dose, feel only queasy, and seem fine right up until the systems start failing. + +## The tier ladder + +Your accumulated dose maps to a severity **tier**, and the tier decides which syndromes switch on. Defaults shown — every threshold is configurable. + +| Tier | Dose (default) | Name | What switches on | +|------|----------------|------|------------------| +| **0** | < 1 Gy | None | Nothing | +| **1** | 1–2 Gy | Mild (prodromal) | Nausea/vomiting, pain, fever begins | +| **2** | 2–4 Gy | Moderate (hematopoietic) | Marrow suppression → anemia, won't-clot bleeding, infection risk | +| **3** | 4–6 Gy | Severe (GI) | Dehydration, blood-gas acidosis, heavy vomiting | +| **4** | ≥ 6 Gy | Lethal (neurovascular) | Hypotension, seizures, collapse → cardiac arrest | + +Higher tiers don't replace the lower ones — they **stack on top**, and they arrive **faster** (the latent period compresses as the dose climbs, mirroring the real-world "time to vomiting" biomarker that medics use to estimate dose). + +``` + DOSE ABSORBED + | + [accumulates] --> crosses 1 Gy --> TIER 1 prodromal (nausea, fever) + | | + | crosses 2 Gy --> TIER 2 marrow fails + | (anemia, bleeding, infection) + | | + | crosses 4 Gy --> TIER 3 gut fails + | (dehydration, acidosis) + | | + | crosses 6 Gy --> TIER 4 brain/circulation fails + | (hypotension -> collapse -> arrest) + v + higher dose = shorter time before each stage hits +``` + +--- + +## The syndromes, in plain terms + +### Prodromal (tier 1+) +The early warning. Nausea and vomiting, a creeping rise in pain, and the start of a fever. It's miserable but survivable — and it's the body telling you the real damage is already done and the clock is running. + +### Hematopoietic — the marrow (tier 2+) +The classic radiation kill mechanism, just slower than the dramatic stuff. Your bone marrow stops keeping up, and three things follow: + +- **Anemia** — your blood volume slowly falls and you can't replace it. A wound that would normally be survivable becomes a problem because you can't rebuild what you lose. +- **Thrombocytopenia** — your blood won't clot properly. Bleeding that should stop with a bandage keeps going. +- **Immunosuppression** — your immune system is on the floor, which opens the door to **wound infection** (below). + +### Gastrointestinal — the gut (tier 3+) +Now it's serious. Fluid pours out of the body (dehydration → falling blood volume), the blood chemistry tips into **acidosis**, and the vomiting becomes relentless. This is the tier where casualties start sliding toward hypovolemic shock. + +### Neurovascular / CNS — the lethal tier (tier 4) +Blood pressure craters (**hypotension**), brief **seizures** hit, and the casualty collapses into unconsciousness and then cardiac arrest. **This tier will not recover on its own** — but it is *not* an automatic death sentence: with a hard, sustained intensive-care effort a lethal casualty can be pulled back. See [Treatment & triage → Intensive care for lethal doses](06_treatment_and_triage.md#intensive-care-for-lethal-doses). Left alone, though, they die. + +### Systemic — fever & the screen +Running underneath all of it: a **fever** that climbs with severity, and a **visual effect** — the world desaturates into a sickly grade as you get worse (toggleable, on by default). The visual is your gut-feel warning when you're not staring at the dosimeter. + +--- + +## Recovery + +Here's the merciful part: **below the lethal tier, radiation sickness heals on its own.** Once you're out of the radiation (no field, no internal contamination left), your sickness slowly winds back down over minutes — marrow recovers, fever breaks, blood pressure normalises, and the tier ticks back to zero. + +- The **accumulated dose** on your dosimeter stays where it is — that's your permanent exposure record — but the *sickness* it caused fades. +- **Filgrastim** speeds this up considerably (see [Treatment](06_treatment_and_triage.md)). +- The **lethal tier does not spontaneously recover** — it only comes back with the active [intensive-care protocol](06_treatment_and_triage.md#intensive-care-for-lethal-doses). Everything below it heals on its own, given time and support. + +--- + +## Wound infection & sepsis + +When your immune system is suppressed (tier 2+) and you have **open or bandaged wounds**, those wounds can become **infected**. Once infected: + +- Pain and fever climb, and the wound bleeds in a way that drags your blood volume down. +- Left untreated, the infection worsens into **sepsis** — and sepsis here is **lethal**. A casualty who survives the radiation itself can still die of the infection it let in. This is the realistic sting in the tail of marrow failure. +- **Antibiotics** clear it. It also resolves on its own *if* the casualty's immunity recovers first — so it's a race between your immune system coming back and the infection getting ahead of it. + +> **Mission makers:** infection can be switched off entirely with the *Enable wound infection* setting if you don't want sepsis in your mission. + +--- + +## A note for mission makers: this rides on other systems + +The physiology layers drive **real KAT medical subsystems** — blood volume, coagulation, blood gas, blood pressure, body temperature. If a subsystem is disabled in the addon options, the matching radiation effect simply doesn't fire (cleanly, no errors), and the rest still work. Which layer needs which subsystem is laid out in the [dependency table in Zeus & mission makers](07_zeus_and_MissionMakers.md). All of them are on by default. + +--- diff --git a/docs/jp/Radiation/05_detection_and_items.md b/docs/jp/Radiation/05_detection_and_items.md new file mode 100644 index 000000000..e04be5ad6 --- /dev/null +++ b/docs/jp/Radiation/05_detection_and_items.md @@ -0,0 +1,68 @@ +# Detection & Equipment + +You cannot see, smell, or feel radiation. Without a device you have no idea whether the room you just walked into is harmless or already killing you — so detection isn't optional here the way it sometimes is with a visible gas cloud. + +## The Dosimeter (your geiger) + +The `KAT_Dosimeter` is a worn device (watch slot, like the chemical JCAD). It's your eyes for radiation: a small HUD with the dose readout, plus the classic geiger clicks. + +**Turning it on** — three independent steps, mirroring how the JCAD works: + +1. **Show the HUD** — press the dosimeter key (**P** by default) to bring the readout up. +2. **Enable the dosimeter** — a self-action that switches on the live dose-*rate* reading. Until you do this, the HUD shows your accumulated dose but the rate reads `--`. +3. **Enable the sound** — a separate self-action that turns on the geiger clicks. The clicks get faster as the dose rate climbs, and go silent when you're in clean air. + +There are matching **Disable** / **Sound off** self-actions to turn each back off. + +**What it shows:** + +- **Accumulated dose (Gy)** — always visible. Your running total of absorbed radiation. This is the number that decides how sick you get. +- **Dose rate (Gy/h)** — visible once enabled. How hot your current spot is. Remember: this reads the *field*, not what you absorb, so it ignores your shielding. + +> The geiger reads the environment, so it'll keep clicking if **you** are contaminated even in clean air — that's the surface contamination making you a source. If the clicks won't stop after you've left a zone, survey/decon yourself. + +> **Asset note:** the dosimeter currently borrows the chemical detector's model and the geiger sounds reuse the detector's chime samples as placeholders. The numbers and behaviour are real; dedicated art and click audio are planned. + +## Rad Survey (diagnostic) + +A medical action — **Radiation Survey** — that points the dosimeter at a casualty and reports: + +- their **surface contamination** level (as a %), +- the **dominant radiation type** they're carrying, +- and the **ambient dose rate** at them. + +Requires a dosimeter in your kit. Use it on a casualty before you start treating to know whether you need to decon them (and to know whether *you're* about to get dosed working on them). + +## Dose Estimation (triage diagnostic) + +A second medical action — **Estimate Radiation Dose** — for triage. It reads the casualty's exposure and reports: + +- their **exact accumulated dose** in Gy, +- a **prognosis** band (from "no ARS expected" up to "likely lethal without intensive treatment"), +- and the **time-to-vomiting** biomarker, if they've vomited. + +This is your tool for deciding who's salvageable and who isn't when you have more casualties than supplies. + +--- + +## Equipment & Items + +Everything radiation-related, plus the shared decon kit. All available through ACE Arsenal. + +| Item | Classname | Purpose | How to use | +|------|-----------|---------|------------| +| Dosimeter | `KAT_Dosimeter` | Reads dose rate + accumulated dose; geiger clicks | Watch slot; key **P** + self-actions to enable/sound | +| Potassium Iodide (KI) | `kat_potassiumIodide` | **Prophylaxis** — reduces uptake if taken before/early | *Take Potassium Iodide* (self + medic) | +| Prussian Blue | `kat_prussianBlue` | **Chelation** — speeds clearing of internal contamination | *Administer Prussian Blue* (self + medic) | +| Antibiotics | `kat_antibiotics` | Fights radiation wound infection / sepsis | *Administer Antibiotics* (self + medic) | +| Filgrastim (G-CSF) | `kat_filgrastim` | Speeds marrow / sickness recovery | *Administer Filgrastim* (self + medic) | +| Antiemetic | `kat_antiemetic` | Suppresses radiation-sickness vomiting | *Administer Antiemetic* (self + medic) | +| Stem-Cell / Marrow Rescue | `kat_stemCells` | The pivotal cure for a **lethal** dose — enables intensive-care recovery | *Administer Stem-Cell Rescue* (**medic only**, lethal casualty) | +| Decontamination Kit | `kat_decon_kit` | Removes **surface** contamination (shared with Chemical) | *Decontaminate* (shown when contaminated) | +| Radioactive Source | `kat_radSource` | A carryable/placeable point source | Editor/Zeus object; ACE *Pick up* / *Drop* | + +> The decon kit and the CBRN mask/suit are the **same items** the [Chemical](../Chemical/05_detection_identification_items.md) side uses — radiation reuses them rather than adding duplicates. The drugs and the dosimeter are radiation's own additions. + +> **What decon does and doesn't do:** the decon kit clears **surface** contamination only. It will not touch internal contamination (use Prussian Blue) and it does nothing to the dose you've already absorbed. See [Treatment & triage](06_treatment_and_triage.md). + +--- diff --git a/docs/jp/Radiation/06_treatment_and_triage.md b/docs/jp/Radiation/06_treatment_and_triage.md new file mode 100644 index 000000000..6acdd8524 --- /dev/null +++ b/docs/jp/Radiation/06_treatment_and_triage.md @@ -0,0 +1,120 @@ +# Treatment & Triage + +Radiation treatment is less about a single antidote and more about managing a casualty through a sickness that plays out over time. There's no "cure the radiation" button — there's removing what's still dosing them, slowing the damage, and supporting the body's systems while it recovers (or deciding it can't). + +## The one distinction that runs everything: decon vs chelation + +Two kinds of contamination, two completely separate cures. Mixing them up is the classic mistake. + +| Contamination | Where it is | Cleared by | NOT cleared by | +|---------------|-------------|-----------|----------------| +| **Surface (external)** | On skin & gear | **Decontamination Kit** | Prussian Blue | +| **Internal** | Breathed in, inside the body | **Prussian Blue** (chelation) | The decon kit / washing | + +- **Decon** scrubs the surface. It stops the casualty reading hot on a geiger and stops them cross-contaminating others. +- **Prussian Blue** chelates — it binds internal radionuclides so the body clears them faster, cutting off the internal dose that otherwise keeps climbing for ages. + +Neither one undoes dose already absorbed. They stop *further* dosing from contamination; the sickness from what's already in still has to be ridden out. + +--- + +## Treatment reference + +Match what you've found to what you reach for. + +| What you see / know | Use | Notes | +|---------------------|-----|-------| +| Casualty reads hot on a survey; geiger won't stop | **Decontamination Kit** | Clears surface contamination + stops cross-contamination | +| Dose keeps climbing in clean air (breathed it in) | **Prussian Blue** | Chelation; the only thing that touches internal contamination | +| *Before* entering a hot area | **Potassium Iodide (KI)** | Prophylactic — reduces uptake; useless after the fact | +| Vomiting from radiation sickness | **Antiemetic** | Suppresses the vomiting for a while | +| Infected wound / heading toward sepsis | **Antibiotics** | Clears infection; essential if infection is enabled | +| Slow to recover after a survivable dose | **Filgrastim (G-CSF)** | Speeds marrow/sickness recovery | +| Anemia, low blood volume, dehydration | **IV Blood / Saline** | Standard KAT fluids — radiation drains blood volume, so top it up | +| Radiation burns, open wounds | Standard ACE/KAT wound care | Treat as ordinary injuries | + +> **Timing is everything with the two anti-rad drugs.** KI only helps **before** uptake — it's a pre-exposure tablet, not a treatment. Prussian Blue is the opposite — it's for **after**, to speed clearing what's already inside. Carry KI for planned entries into hot zones; carry Prussian Blue for after the fact. + +> **Tracking what you've given:** every radiation drug logs to the patient's **triage card** in the medical menu when administered (with a tally on repeat doses), so you can see at a glance what's already on board. + +--- + +## Treating a casualty — quick flow + +``` + Radiation casualty (down or sick) + | + 1. MAKE IT SAFE FOR YOU + Survey them. If they read hot, DECON first — a contaminated + casualty doses you the whole time you're working on them. + | + 2. STOP THE DOSING + - DECON KIT -> clears surface contamination + - PRUSSIAN BLUE -> clears internal (inhaled) contamination + - move them clear of any radiation field + (until dosing stops, nothing you do below will hold) + | + 3. ESTIMATE THE DOSE (Estimate Radiation Dose action) + | + +-----+----------------------------------------+ + | | + SURVIVABLE (mild–severe) LETHAL (top tier, >6 Gy) + | | + supportive care: INTENSIVE CARE (hard, ~15 min): + - IV blood/saline (anemia, fluids) keep alive: IV or vasopressor + - antibiotics (if infected) cure (all at once, sustained): + - antiemetic (vomiting) filgrastim + antibiotics + - filgrastim (speeds recovery) + STEM-CELL RESCUE + | (source already removed) + recovers over minutes; -> see "Intensive care for + accumulated dose stays on record lethal doses" below + | + 4. MOP UP + Treat radiation burns and open wounds as normal ACE/KAT injuries. +``` + +The short version of supportive care for a survivable casualty: **stop the contamination (decon/chelate), replace the blood they're losing (IV), keep infection out (antibiotics), make them comfortable (antiemetic), and speed the marrow back (filgrastim).** Then time does the rest. A **lethal** casualty needs all of that *plus* the sustained intensive-care protocol below — they will not recover on supportive care alone. + +--- + +## Intensive care for lethal doses + +A lethal dose (the top tier, ≥ 6 Gy by default) **will not recover on its own** — but it's survivable if a medic commits to a hard, ~15-minute intensive-care fight. There are two layers: keep them alive, then actually cure them. (Mission makers can switch this off with *Lethal dose curable*, making the top tier terminal again.) + +### Layer 1 — keep them alive +A lethal casualty collapses unconscious and starts a hidden "time to arrest" clock. **Circulatory support holds that clock off:** + +- an **active IV line** (blood or saline), **or** +- a **vasopressor** in their system (epinephrine / norepinephrine). + +Let support lapse and the clock runs out → **cardiac arrest**, at which point it's a full CPR / defibrillator / rhythm-management emergency (the normal cardiac-arrest system, advanced rhythm and all). Support is the bare minimum just to stop them dying — it does **not** cure anything. + +### Layer 2 — actually cure them +Their radiation sickness only winds down while the **entire intensive-care stack is sustained at once**: + +1. **Source removed** — fully deconned *and* chelated (Prussian blue), out of any field. While any dose is still coming in, nothing improves. +2. **Circulatory support** — the IV or vasopressor from Layer 1. +3. **Filgrastim** — kept topped up. +4. **Antibiotics** — kept topped up (and the only thing stopping sepsis finishing them off in parallel). +5. **Stem-Cell / Marrow Rescue** (`kat_stemCells`) — the pivot. Medic-only, slow to administer, and re-dosed as it wears off. **Without it, full support only *holds* them — alive but never improving.** With it, the sickness finally starts to clear. + +Sustain all five and severity grinds down over roughly **12–16 minutes**, after which they drop out of the danger zone and finish recovering normally. Drop any one and the cure **stalls**. + +### They stay unstable until it's done +Bringing someone back from arrest doesn't make them safe. While they're still heavily irradiated their system keeps **crashing back into arrest** — even on an IV — and (with advanced rhythm on) throws **VF/VT far more often**. Both taper off as the cure progresses, so the way to *stop* the re-crashes is to push the cure down, not just park them on a pressor. Expect to resuscitate the same patient more than once before they're out of the woods. + +> This is deliberately brutal: one medic with a couple of items can't do it. It takes the full kit, constant re-dosing, and someone watching the monitor for the next arrest — a genuine team effort to save one person. + +--- + +## Prophylaxis: the smart play + +The cheapest treatment is the one you take before anything happens. If you know you're going into a contaminated area: + +- **Take KI first** — it reduces how much radioiodine your body takes up while you're in there. +- **Mask and suit up** per the [shielding rules](03_protection_and_shielding.md) — the mask especially, to keep internal contamination out. +- **Carry a dosimeter and watch the accumulated dose**, not just the rate. Leave before it climbs into the tiers you can't walk back from. + +A prepared unit can work a hot zone and recover. An unprepared one finds out about the dose when the vomiting starts. + +--- diff --git a/docs/jp/Radiation/07_zeus_and_MissionMakers.md b/docs/jp/Radiation/07_zeus_and_MissionMakers.md new file mode 100644 index 000000000..68e57a2d3 --- /dev/null +++ b/docs/jp/Radiation/07_zeus_and_MissionMakers.md @@ -0,0 +1,179 @@ +# Zeus & Mission Makers + +How to put radiation on the map, and how to tune every part of it. + +## Placing radiation sources + +A source emits any mix of the four types, each with its own strength in **Gy/h**. You author that mix either by hand (the four per-type fields) or by picking a **preset** that fills them for you. + +### Radiation module (`kat_module_radiation`) + +In the editor under **Modules → KAT**, and the same module is available in **Zeus** as a curator module. Its attributes: + +- **Preset** — a dropdown that fills the four strength fields for you. Pick `Custom` to use the fields directly, or any named preset to auto-fill them. +- **Alpha / Beta / Gamma / Neutron (Gy/h)** — the per-type strengths. Used when Preset is `Custom`; a named preset overrides them. +- **Radius** — area size in metres. +- **Point source** — if enabled, the source falls off with the inverse-square law (a hot spot) instead of linearly across the radius (an area/zone). + +Sync the module to a `LocationArea` trigger for a zone, or enable **Point source** for a localised hotspot. The **Zeus** version opens the same attributes dialog — picking a preset there auto-fills the four fields before you confirm. + +### Source presets + +| Preset | Alpha | Beta | Gamma | Neutron | Reads like | +|--------|-------|------|-------|---------|-----------| +| **Custom** | — | — | — | — | Use the four fields | +| **Cobalt-60** | 0 | 0 | 100 | 0 | Strong sealed gamma source — whole-body dose, no burns | +| **Reactor** | 0 | 0 | 50 | 25 | Reactor core / criticality — deadliest, neutron-heavy | +| **Fallout** | 0 | 400 | 20 | 0 | Lingering area — beta skin burns + slow sickness | +| **Alpha Emitter** | 150 | 10 | 0 | 0 | Inhalation hazard — near-harmless unless breathed in | +| **Dirty Bomb** | 40 | 250 | 50 | 0 | A messy mix — burns, gamma, and inhalation | + +> Strengths are **Gy/h** — the dose rate at the reference point (the centre for zones, ~1 m for point sources). With the defaults, a casualty in a ~500 Gy/h gamma field reaches the lethal tier in roughly 40 seconds; the 100 Gy/h Cobalt-60 preset is a few-minutes hazard; Fallout's heavy beta is what produces skin burns over a few minutes. Scale to the pace you want. +> +> **Note on neutron:** the neutron field is weighted far heavier than the others for whole-body dose (high biological effect), so a small neutron number bites hard — that's why Reactor is the deadliest preset despite modest-looking figures. + +### Carryable radioactive source (`kat_radSource`) + +A placeable object (editor and Zeus) that acts as a **hot beta+gamma point source** you can pick up — think a lost industrial-radiography source. ACE-interact to **Pick up radioactive source**, and held point-blank it concentrates skin dose on your hands and arms (a burn in about a minute) while pouring whole-body dose into you — rapidly lethal unshielded, though a CBRN suit buys you a few minutes to make the carry. **Drop** it to set it back down. Great for "carry the source to the disposal site" objectives. + +> **Asset note:** `kat_radSource` uses a placeholder jerry-can model for now; dedicated art is planned. + +### Quick console source (testing) + +To drop a source at your feet without placing a module — handy for testing — run this as the server: + +```sqf +["kat_chemical_addRadSource", [getPosASL player, 30, [0,0,500,0], "linear", "testRad", {true}, []]] call CBA_fnc_serverEvent; +``` + +The array is `[alpha, beta, gamma, neutron]` in Gy/h. Remove it with: + +```sqf +["kat_chemical_removeRadSource", "testRad"] call CBA_fnc_serverEvent; +``` + +--- + +## Mission Configuration (CBA Settings) + +Everything below lives under **CBA Settings → KAT - ADV Medical: Chemical**, in the **"10. Radiation"** subcategory (radiation shares the chemical addon's settings category). Times are in seconds; dose values in Gray. + +### Master & display + +| Setting | Default | What it does | +|---------|---------|--------------| +| Enable radiation | on | Master switch for the whole system | +| Show sickness messages | on | Whether radiation-sickness hints appear on screen | +| Radiation visual effect | on | The desaturated screen effect while irradiated/sick (client-side) | + +### Dose thresholds (Gy) + +| Setting | Default | What it does | +|---------|---------|--------------| +| Mild dose threshold | 1 | Dose at which mild (prodromal) sickness begins | +| Moderate dose threshold | 2 | Dose at which the hematopoietic tier begins | +| Severe dose threshold | 4 | Dose at which the GI tier begins | +| Lethal dose threshold | 6 | Dose at which the neurovascular (lethal) tier begins | + +### Stage timings + +| Setting | Default | What it does | +|---------|---------|--------------| +| Prodromal delay | 120 | Time to the first prodromal symptoms | +| Hematopoietic delay | 600 | Time to marrow-suppression onset | +| GI delay | 480 | Time to GI-syndrome onset | +| CNS delay | 180 | Time to neurovascular onset | +| Cardiac delay | 300 | Time to the fatal cardiac event | + +> Higher tiers compress these delays automatically — a massive dose makes the stages arrive much faster than a borderline one. + +### Shielding + +| Setting | Default | What it does | +|---------|---------|--------------| +| Mask protection factor | 1.0 | Global effectiveness multiplier for gas-mask shielding | +| CBRN suit protection factor | 1.0 | Global multiplier for CBRN-suit shielding | +| Rad-gear protection factor | 1.0 | Global multiplier for rad-gear-uniform shielding | +| Vehicle protection factor | 1.0 | Global multiplier for vehicle shielding | +| Radiation-protective uniforms | *(empty)* | **Whitelist of uniform classnames that count as rad-gear** | + +> *Radiation-protective uniforms* is the radiation equivalent of the CBRN-suit whitelist — a quoted, comma-separated list of classnames. Populate it with whatever anti-rad suits your loadout mods provide. + +### Contamination + +| Setting | Default | What it does | +|---------|---------|--------------| +| Inhalation factor | 0.1 | How much unmasked exposure becomes internal contamination | +| Internal dose conversion rate | 0.001 | How fast internal contamination converts to whole-body dose | +| Internal decay rate | 0.0005 | How fast the body clears internal contamination on its own | +| Contamination deposition | 0.02 | How fast surface contamination builds up | +| Contamination decay | 0.002 | How fast surface contamination weathers away | +| Cross-contamination strength | 5 | How strong a field a contaminated casualty emits (Gy/h scale) | +| Local exposure distance | 1.5 | Within this range of a point source, skin dose concentrates on arms/hands | +| Skin burn threshold | 5 | Local skin dose per radiation-burn wound | + +### Drugs + +| Setting | Default | What it does | +|---------|---------|--------------| +| KI protection factor | 0.5 | How much KI reduces uptake while active | +| KI duration | 3600 | How long a KI dose protects | +| Chelation duration | 600 | How long Prussian Blue accelerates internal clearance | +| Chelation factor | 5 | How much faster chelation clears internal contamination | +| Antibiotic duration | 600 | How long antibiotics suppress infection | +| Antiemetic duration | 900 | How long an antiemetic suppresses vomiting | +| Filgrastim duration | 1800 | How long filgrastim accelerates recovery | +| Filgrastim recovery multiplier | 3 | How much faster sickness recovers while filgrastim is active | + +### Physiology + +| Setting | Default | What it does | +|---------|---------|--------------| +| Anemia rate (ml/s) | 2 | Blood-volume loss from marrow suppression (scaled by severity) | +| GI fluid loss (ml/s) | 3 | Blood-volume loss from GI dehydration | +| GI acidosis rate | 0.05 | Per-second drop in blood-gas bicarbonate/pH | +| CNS hypotension (mmHg) | 40 | Maximum blood-pressure drop at the lethal tier | +| Maximum fever (°C) | 2 | Peak temperature rise from radiation sickness | +| Recovery rate (Gy/s) | 0.01 | How fast sickness heals once out of radiation (below lethal) | + +### Infection + +| Setting | Default | What it does | +|---------|---------|--------------| +| Enable wound infection | on | Whether immunosuppressed wounds can get infected → sepsis | +| Infection chance | 0.05 | Per-second base chance of infection (scaled by immunosuppression) | +| Infection progression rate | 0.02 | How fast an untreated infection worsens | +| Sepsis blood loss (ml/s) | 15 | Blood loss at full infection — drives lethal septic shock | + +### Lethal-tier intensive care + +| Setting | Default | What it does | +|---------|---------|--------------| +| Lethal dose curable | on | If on, a lethal casualty can be saved with sustained intensive care; if off, the lethal tier is terminal | +| Collapse time (unsupported) | 150 | Seconds a critical casualty lasts without IV/vasopressor before cardiac arrest | +| Intensive-care recovery rate (Gy/s) | 0.006 | How fast a lethal casualty's sickness clears under the full stack (lower = harder) | +| Stem-cell rescue duration | 300 | How long one stem-cell dose enables recovery before re-dosing | +| Re-crash chance | 0.05 | Per-tick chance (at full severity) of crashing back into arrest; tapers with the cure, halved on life support | +| Shockable rhythm bias | 0.7 | Chance (at full severity, Advanced Rhythm on) a radiation arrest is VF/VT vs asystole/PEA | +| Stem-cell rescue required trait | Medics | Who can administer the stem-cell rescue (Anyone / Medics / Doctors) | +| Intensive-care readout | off | Show a status line in the medical menu for a critical casualty (cure progress + missing supports; never the arrest timer) | + +> The lethal-tier cure also leans on the **Circulation** cardiac-arrest system and, when enabled, **Advanced Rhythm** (`kat_circulation_AdvRhythm`) for the VF/VT behaviour — it cooperates with them rather than running its own death timer. + +--- + +## Subsystem dependencies (important) + +The physiology layers drive **other KAT medical subsystems**. If one is disabled in addon options, the matching radiation effect is **cleanly skipped** (no errors) and everything else keeps working. They all default **ON**, so this is usually a "don't accidentally turn it off" check. + +| Radiation effect | Needs this subsystem ON | Setting | +|------------------|------------------------|---------| +| Thrombocytopenia (won't-clot bleeding) | KAT Pharmacy → Coagulation | `kat_pharma_coagulation` | +| Anemia regeneration impairment | KAT Vitals → Fluid Shift | `kat_vitals_enableFluidShift` | +| GI acidosis (blood-gas pH/HCO3) | KAT Breathing → Enable | `kat_breathing_enable` | +| CNS hypotension (blood pressure) | KAT Circulation → Enable | `kat_circulation_enable` | +| Fever (body temperature) | KAT Hypothermia → Enable Hypothermia | `kat_hypothermia_hypothermiaActive` | + +> To exercise the full system on **AI** casualties, keep **KAT Vitals → Simple Medical OFF** — simple medical bypasses the detailed vitals loop the radiation effects ride on. Players always get the full sim. + +--- diff --git a/docs/jp/Radiation/08_faq_and_troubleshooting.md b/docs/jp/Radiation/08_faq_and_troubleshooting.md new file mode 100644 index 000000000..5f3e02518 --- /dev/null +++ b/docs/jp/Radiation/08_faq_and_troubleshooting.md @@ -0,0 +1,34 @@ +## FAQ & Troubleshooting + +### **My geiger is screaming but I'm not taking any damage. Is it broken?** +No — that's working as intended, and it might be your gear doing its job. The geiger reads the **dose rate** (the field around you), which your shielding does *not* change. What your shielding reduces is the **accumulated dose** — the Gy total you actually soak up. Watch that number: if it's barely climbing while the rate is high, your suit/vehicle is protecting you. (And if you're in a pure-gamma field with only a mask on, the rate being scary while the dose climbs fast is *also* correct — a mask doesn't stop gamma.) + +### **I left the radiation hours ago but my dose is still going up.** +You breathed it in. That's **internal contamination** — radioactive material inside you that keeps converting to dose long after you've left. A geiger and a decon kit can't help with it because it isn't on your surface. Use **Prussian Blue** to chelate it out, or wait for your body to slowly clear it. + +### **I deconned the casualty but their dose didn't drop.** +Decon only removes **surface** contamination — it stops them reading hot and cross-contaminating others, but it does nothing to dose already absorbed, and nothing to internal contamination. If their dose is still climbing, it's internal (use Prussian Blue). If it's just high but stable, that's the permanent record of what they absorbed — there's no scrubbing that off, only treating the sickness. + +### **A pure gamma source gave me almost no burns. Shouldn't radiation burn me?** +Not gamma. Skin/radiation burns come from **beta** and from **handling a source point-blank**. Gamma and neutron drive whole-body dose, not skin dose, so a gamma zone makes you *sick* without covering you in burns. Stand in a beta field — or pick up a `kat_radSource` — to see burns. + +### **I walked into a hot zone and died almost instantly. Is that normal?** +Only if the source is enormous. Source strength is in **Gy/h**, and a very high value (say several hundred) will push you past the 6 Gy lethal threshold in well under a minute. If you want a survivable hazard, lower the source strength, raise the dose thresholds, or both — see [Zeus & mission makers](07_zeus_and_MissionMakers.md). + +### **One of the sickness effects does nothing — no fever / no blood-pressure drop / bleeding still clots.** +That effect's host subsystem is probably disabled. The physiology layers ride on other KAT systems: fever needs **Hypothermia**, acidosis needs **Breathing**, hypotension needs **Circulation**, won't-clot bleeding needs **Pharmacy Coagulation**, and anemia regen needs **Vitals Fluid Shift**. They're all on by default — check none got switched off. (Radiation skips a disabled layer cleanly; it won't error.) + +### **My AI test casualty ignores all the physiology.** +Turn **Simple Medical OFF** in KAT Vitals. Simple medical bypasses the detailed vitals loop that the radiation effects hook into. Players always get the full sim; AI only do when simple medical is off. + +### **The casualty recovered from severe radiation sickness on their own. Bug?** +Intended. Below the lethal tier, sickness heals slowly once the casualty is out of radiation (and clear of internal contamination). **Filgrastim** speeds it up. The **lethal tier** never self-recovers — it's survivable only with the sustained [intensive-care protocol](06_treatment_and_triage.md#intensive-care-for-lethal-doses), not by waiting. Note the *accumulated dose* on the dosimeter stays put — that's the exposure record; it's the sickness that fades, not the history. + +### **A medic treating a contaminated casualty started getting dosed.** +That's cross-contamination, and it's intended. A surface-contaminated casualty emits a weak field of their own. **Decon them** to shut it off — until you do, anyone working on them is standing next to a small source. Survey first, decon, then treat. + +### **The dosimeter clicks won't stop even in clean air.** +You're contaminated — *you* are the source the geiger is reading. Survey yourself and use the decon kit. (If you've turned the dosimeter sound off and it still seems to click, that's the placeholder chime samples — dedicated click audio is planned.) + +### **Is radiation a separate addon I need to enable?** +No. Radiation is part of the **Chemical** addon — same PBO, same CBA settings category (under the "10. Radiation" subcategory). If you have KAT's chemical addon, you have radiation.