Does pond/stream water make you sick in DayZ?

I tried submitting this various different ways to /r/dayz and automod would always immediately remove it so here is a giant block of HTML.

I've seen this discussion pop up now and then and there doesn't seem to be a clear answer. Some say bad water won't make you sick unless you're low blood, others swear they've gotten sick while showing full green healthy status. I've tinkered with modding ArmA so thought I'd go straight to the source (as it were) and look in the code itself.

The code is a little convoluted and there is a mix of new and old scripting. I'm making the assumption that the files I'll show below are actually what's used in game. This is experimental build 0.62.139748 but I believe it should be the same on current stable 0.61.138957. Note the file paths I'm showing are extracted from PBOs and may also be unbinned (config.bin -> config.cpp). If you don't know what that means use Google or just don't worry about it. Also I've removed comments, whitespace, and extraneous lines from code blocks for brevity.

So what happens behind the scenes when you look at water and click Drink? Well buckle up and let's go for a ride!

Let's start with the class for the water one can drink from streams and ponds, RiverWater.

C:\Steam\SteamApps\common\DayZ\Addons\gear_drinks\config.cpp

class RiverWater: DrinksItemBase {
    scope = 1;
    diseases = {"Cholera"};

    class Nutrition {
        totalVolume = 150;
        energy = 0;
        water = 300;
        nutritionalIndex = 15;
    };
};

As you can see there is one disease that this class carries and that is Cholera. A lot of the objects you look at in game have actions associated with them. For example when you look at a bush you get "Chop sticks". When you look at stream or pond water you get "Drink". This is setup in the code block below.

C:\Steam\SteamApps\common\DayZ\Addons\server_data\config.cpp

class CfgObjectActions {
    class Freshwater {
        model = "#Freshwater";

        class Water {
            displayName = "Drink";
            priority = 0.100000;
            showWindow = 1;
            hideOnUse = 1;
            condition = "_canUseActions && _owner getVariable ['isUsingSomething',0] == 0 && isNull _inHands";
            statement = "_owner setVariable ['isUsingSomething',1];                 [this, _inHands, _owner,'water'] call player_liquidSource;              [_owner,'RiverWater','Direct',1] call event_transferModifiers;          ";
        };

The "statement =" lines shows the code that runs when you use action "Drink" in game. The first part tells your character it is using something, the second part does the actual drinking, and the third takes care of any transferring or modifiers. I won't go into the animation and nutrition stuff for the drinking part but if you're curious the code can be found in player_liquidSource.sqf as shown below.

C:\Steam\SteamApps\common\DayZ\Addons\server_data\scripts\init.sqf

player_liquidSource = compile preprocessFileLineNumbers "\dz\server\scripts\players\player_liquidSource.sqf";

The file path on disk for player_liquidSource.sqf would be:

C:\Steam\SteamApps\common\DayZ\Addons\server_data\scripts\players\player_liquidSource.sqf

The transfer of things from one item to another (such as diseases) is handled by a generic function called event_transferModifiers. Before we dive into that let's take a look at the class for Cholera.

C:\Steam\SteamApps\common\DayZ\Addons\server_data\config.cpp

class Cholera: Default {
    messagesExit = {};
    messageExitStyle = "";

    class Transmission {
        invasivity = 0.600000;
        toxicity = 0.400000;
        physicalResistance = 0.500000;
        chemicalResistance = 0.600000;

        class Direct: DefaultDirect {
            transferability = 0.700000;
            fromPlayer = 1;
        };
    };

Those variables under Transmission will all come into play in the next block of code, which determines if you get sick. Anyone still awake? 1 person, OK great! The event_transferModifiers function is defined in init.sqf.

C:\Steam\SteamApps\common\DayZ\Addons\server_data\scripts\init.sqf

event_transferModifiers =   compile preprocessFileLineNumbers "\dz\server\scripts\events\event_transferModifiers.sqf";

Here I've got just the relevant bits of code. The file has much more in it, including a lot of code that is commented out.

C:\Steam\SteamApps\common\DayZ\Addons\server_data\scripts\events\event_transferModifiers.sqf

_target = _this select 0;
_source = _this select 1;
_method = _this select 2;
_interactionWeight = _this select 3; // interaction weight value of given action for use in disease transfer formula
_transferability = getNumber (_config >> "Transmission" >> _method >> "transferability"); // Efficiency rate of penetrate receptive person AKA chance of spread
_probability = _interactionWeight - _obstruction + _transferability; // probability to transfer disease
_probabilityToNotTransfer = 1 - _probability; // probability of not getting disease on player
_randomNum = random 1;
_obstruction = 0;

if (_randomNum >= _probabilityToNotTransfer) then
{
    if (_a isKindOf "SurvivorBase") then
    {   
        _invasivity = getNumber (_config >> "Transmission" >> "invasivity");
        _toxicity = getNumber (_config >> "Transmission" >> "toxicity");
                            
        _survivorDiet = _a getVariable "diet";
        _survivorBlood = _a getVariable "blood";    
        _survivorHealth = _a getVariable "health";              
        _immunityStrength = (_survivorDiet + (_survivorBlood/5000) + (_survivorHealth/5000)) / 3;  // Draft of immunity strength formula
        _allStages = configFile >> "CfgModifiers" >> _modifier >> "Stages";
        _stagesCount = count _allStages;
        _stagesStep = 1 / _stagesCount;
        
        if (_invasivity >= _immunityStrength) then
        {
            _impactOnPlayer =  _toxicity / _immunityStrength; // Higher the number is, the lighter impact disease have on player (lower number == heavier impact)
            for "_i" from (_stagesCount - 1) to 1 step -1 do
            {   
                if (_impactOnPlayer >= (_stagesStep * _i)) exitWith
                {
                    [2,_a,_x,_i] call event_modifier;
                };
            };

So what does all that mean? Well, let's break it down a bit with an example. This function gets called like so: [_owner,'RiverWater','Direct',1] call event_transferModifiers
_target will be _owner, which is the player
_source will be class RiverWater
_method will be Direct
_interactionWeight will be 1

_transferability = getNumber (_config >> "Transmission" >> _method >> "transferability");

_transferability = 0.7 (from the Cholera class we looked at above)

_probability = _interactionWeight - _obstruction + _transferability;

_probability = 1 - 0 + 0.7 = 1.7

_probabilityToNotTransfer = 1 - _probability;

_probabilityToNotTransfer = 1 - 1.7 = -0.7

_randomNum = random 1

_randomNum will be a random number between 0 and 1

if (_randomNum >= _probabilityToNotTransfer) then

Since _probabilityToNotTransfer is less than zero then this will always be true.

if (_a isKindOf "SurvivorBase") then

This will be true if you are a player drinking, so always true unless something has gone wrong

_invasivity = getNumber (_config >> "Transmission" >> "invasivity");

_invasivity = 0.6 (from the Cholera class we looked at above)

_toxicity = getNumber (_config >> "Transmission" >> "toxicity");

_toxicity = 0.4 (from the Cholera class we looked at above)

_survivorDiet = _a getVariable "diet";

Your character keeps track of the "diet" variable and it seems to be based on what you last consumed. I've not dug entirely into the nutrition system, which is quite complex, so am going to assume diet is 1 for now.

_survivorBlood = _a getVariable "blood";
_survivorHealth = _a getVariable "health";

These should be familiar, let's assume they're both 5000 (full blood/health).

_immunityStrength = (_survivorDiet + (_survivorBlood/5000) + (_survivorHealth/5000)) / 3;

_immunityStrength = (1 + (5000/5000) + (5000/5000)) / 3 = (1 + 1 + 1 ) / 3 = 1

if (_invasivity >= _immunityStrength) then
{
    _impactOnPlayer =  _toxicity / _immunityStrength; // Higher the number is, the lighter impact disease have on player (lower number == heavier impact)

In our example _invasivity is 0.6 and _immunityStrength is 1 so we don't get sick. Hurray! But is it possible to have full blood and health but still get sick? The only other factor is _survivorDiet so how low would it have to be? Let's do some algebra. I know, exciting right?

(x + 2) / 3 = 0.6
x + 2 = 1.8
x = -0.2

So to get sick with full blood and health your diet variable would have to be at least as low as -0.2.

C:\Steam\SteamApps\common\DayZ\Addons\characters_data\config.cpp

// change diet
_dietGathered = _consumableNutriIndex * _scale * 0.01; // nutrients actually gathered from serving  
_diet = (((9 * _diet) + _dietGathered) / 10) min 1; // diet formula (will be probably changed)
_person setVariable ["diet",_diet];

I don't think _diet can ever be less than 0 so in theory you shouldn't get Cholera from dirty water if you're healthy. But, I hear you asking, how low can my blood/health be and still be safe? Let's assume diet is 1, health and blood are equal, and do some more math.

(2x + 1) / 3 = 0.6
2x + 1 = 1.8
2x = 0.8
x = 0.4
5000 ** 0.4 = 2000

If your blood and health are 2000 or below, you're going to get sick.

So in conclusion (tl;dr): If your green healthy status is showing then you can drink dirty water with impunity. If both your health and blood are above 2000 and you're not hungry (maybe?) then you should be safe.

Feel free to pick this apart, I probably made mistakes and jumped to conclusions.