CleverRaven / Cataclysm-DDA

Cataclysm - Dark Days Ahead. A turn-based survival game set in a post-apocalyptic world.
http://cataclysmdda.org
Other
10.62k stars 4.17k forks source link

Features in-game vitamins and the discrepancy between description and actual performance #76905

Open IdleSol opened 4 weeks ago

IdleSol commented 4 weeks ago

Describe the bug

Discount my poor command of the English language.

Vitamin documentation: https://github.com/CleverRaven/Cataclysm-DDA/tree/master/doc/VITAMIN.md

I. Introduction In this topic, I will look at two ways to obtain vitamins. Here are both ways, in one example:

    "use_action": {
      "type": "consume_drug",
      "activation_message": "You take some %s.",
      "vitamins": [ [ "vit_AMED_I", 1 ] ]
    },
    "vitamins": [ [ "vit_AMED_II", 1 ] ]

As you can see from the example, we can add a vitamin as:

They do not conflict with each other and can be used simultaneously. Tested on version cdda-windows-tiles-x64-2024-10-04-0532.

On a separate note, there is another way. Add an effect that adds a vitamin during its effect. Theoretically, it could also set the absorption rate of the vitamins. But I am not considering it in this topic. (And I don't plan on checking it). So if anyone wants to test it, they can feel free to start.

While testing the methods described above, I found a few bugs in the work. At least between the way I understood the documentation and the results I got. So this thread is a bug report, not a suggestion.

II. How does it work? What is the difference between these methods? To find out, a test version of the A-MED pill will help us. test_med.json

Details ``` [ { "id": "test_AMED", "type": "COMESTIBLE", "comestible_type": "MED", "name": { "str_sp": "TEST A-MED" }, "description": "Abstract medicine", "weight": "1 g", "volume": "1 ml", "price": "2 cent", "price_postapoc": "30 cent", "material": [ "drug_filler" ], "symbol": "!", "color": "white", "container": "bottle_plastic_pill_painkiller", "healthy": -1, "flags": [ "WATER_DISSOLVE", "EDIBLE_FROZEN" ], "use_action": { "type": "consume_drug", "activation_message": "You take some %s.", "vitamins": [ [ "vit_AMED_I", 1 ] ] }, "vitamins": [ [ "vit_AMED_II", 1 ] ] }, { "id": "vit_AMED_I", "type": "vitamin", "vit_type": "toxin", "name": { "str": "AMED_I" }, "excess": "TEST_MESSAGE_AMED_I", "min": 0, "max": 10, "rate": "15 m", "disease_excess": [ [ 1, 10 ] ] }, { "type": "effect_type", "id": "TEST_MESSAGE_AMED_I", "max_intensity": 1, "rating": "good", "apply_message": "vit_AMED_I START", "remove_message": "vit_AMED_I STOP" }, { "id": "vit_AMED_II", "type": "vitamin", "vit_type": "toxin", "name": { "str": "AMED_II" }, "excess": "TEST_MESSAGE_AMED_II", "min": 0, "max": 10, "rate": "15 m", "disease_excess": [ [ 1, 10 ] ] }, { "type": "effect_type", "id": "TEST_MESSAGE_AMED_II", "max_intensity": 1, "rating": "mixed", "apply_message": "vit_AMED_II START", "remove_message": "vit_AMED_II STOP" } ] ```

Key details:

    "id": "test_AMED",
    "name": { "str_sp": "TEST A-MED" },
...
    "use_action": {
...
      "vitamins": [ [ "vit_AMED_I", 1 ] ]
    },
    "vitamins": [ [ "vit_AMED_II", 1 ] ]
    "id": "vit_AMED_I",
    "excess": "TEST_MESSAGE_AMED_I",
    "rate": "15 m",
----------
    "id": "vit_AMED_II",
    "excess": "TEST_MESSAGE_AMED_II",
    "rate": "15 m",
    "id": "TEST_MESSAGE_AMED_I",
    "apply_message": "vit_AMED_I                                                              START",
    "remove_message": "vit_AMED_I                                                              STOP"
----------
    "id": "TEST_MESSAGE_AMED_II",
    "apply_message": "vit_AMED_II                                                              START",
    "remove_message": "vit_AMED_II                                                              STOP"

As you can see, they are the same vitamins, with the same concentration and time of absorption. And the effects make corresponding entries in the log messages. So all the differences will just depend on the location of the vitamin section.

2.1. "vit_type": "vitamin"

Not within the audit scope.

2.2. "vit_type": "toxin"

This is some toxic chemical or component. This currently has no effect.

It seems simple: t = 0. Used the tablet. Received both vitamins (two text messages about the beginning of the effects) t = +15 minutes. The vitamins are absorbed by the body. (two text messages about the finishing of the effects)

Practical result. I will be indicating game time. Hours-minutes-seconds Time
8:59:50 Tablet consumed. Message received about vit_AMED_I vitamin appearance
9:00:00 Message received about vit_AMED_I vitamin missing
9:30:00 Two messages received. Vitamin vit_AMED_II appeared and then disappeared immediately

1

Shift the pill time by 10 seconds Time
9:00:00 Tablet consumed. Message received about vit_AMED_I vitamin appearance
9:15:00 Message received about vit_AMED_I vitamin missing
9:30:00 Nothing
10:00:00 Two messages received. Vitamin vit_AMED_II appeared and then disappeared immediately.

2

Let's change the concentration of the tablets. Let's set it to 10 units each. Checks every 15 minutes, through the debug menu. 8:59:50 - Tablet consumed. The consumption time of the tablet is 6 seconds, so the first measurement is at 8:59:56. Format for recording the concentration: daily / overall

Time vit_AMED_I vit_AMED_II
8:59:56 10 / 10 0 / 0
8:59:59 10 / 10 0 / 0
9:00:00 10 / 9 0 / 0
9:14:59 10 / 9 0 / 0
9:15:00 10 / 8 0 / 0
9:29:59 10 / 8 0 / 0
9:30:00 10 / 7 2 / 1
9:44:59 10 / 7 2 / 1
9:45:00 10 / 6 2 / 0
9:59:59 10 / 6 2 / 0
10:00:00 10 / 5 3 / 0
10:15:00 10 / 4 3 / 0
10:29:59 10 / 4 3 / 0
10:30:00 10 / 3 4 / 0
10:45:00 10 / 2 4 / 0
11:00:00 10 / 1 5 / 0
11:15:00 10 / 0 5 / 0
11:30:00 10 / 0 6 / 0
12:00:00 10 / 0 7 / 0
12:30:00 10 / 0 8 / 0
13:00:00 10 / 0 9 / 0
13:30:00 10 / 0 10 / 0
14:00:00 10 / 0 10 / 0

Change the rate value by setting it to 1 hour. "rate": "60 m", For all vitamins. Let's leave the other parameters as in the previous example. (Concentration 10 units).

Time vit_AMED_I vit_AMED_II
8:59:56 10 / 10 0 / 0
9:00:00 10 / 9 0 / 0
9:29:59 10 / 9 0 / 0
9:30:00 10 / 9 2 / 2
9:59:59 10 / 9 2 / 2
10:00:00 10 / 8 3 / 2
10:30:00 10 / 8 4 / 3
11:00:00 10 / 7 5 / 3
11:30:00 10 / 7 6 / 4
12:00:00 10 / 6 7 / 4
12:30:00 10 / 6 8 / 5
13:00:00 10 / 5 9 / 5
13:30:00 10 / 5 10 / 6
14:00:00 10 / 4 10 / 5
14:30:00 10 / 4 10 / 5
15:00:00 10 / 3 10 / 4
16:00:00 10 / 2 10 / 3
17:00:00 10 / 1 10 / 2
18:00:00 10 / 0 10 / 1
19:00:00 10 / 0 10 / 0

Conclusions

  1. Vitamin vit_AMED_I enters the body (?) immediately. The time of absorption of the first unit depends on what expires first. The time defined in the rate or the current stomach cycle, equal to 30 minutes, will be completed. Subsequent units are absorbed according to the rate value.
  2. Vitamin vit_AMED_II. Strange behavior. The addition of a new vitaman occurs every stomach cycle, except for the cycle in which the drug is taken and the one following it. Instead, 2 units are added at once at the beginning of the third cycle. Absorption? Some strange interaction between the stomach cycle and the rate parameter.
  3. In any case, this is nowhere near what one would expect.

2.3. "vit_type": "counter"

This is a counter for something, that is neither a toxin, vitamin, or drug.

Expectations haven't changed. However, the results have not changed either. They fully correspond to the results with “vit_type”: “toxin”

2.3. "vit_type": "drug"

This is a drug. This currently acts as a 'counter', except that it takes 30 minutes (1 stomach cycle) to effect the player character, in order to simulate slow digestion and metabolism of drugs. In order to properly make use of this delay effect, make sure to add it to the base drug item itself, and not it's use effect(s). Look at ibuprofen at med.json for an example.

The description talks about the stomach cycle. And that it should take 30 minutes at first. Simple?

Expectation:

t = 0. Used the tablet. t = +30 min. Received both vitamins (two text messages about the beginning of the effects) t = +45 min. The vitamins are absorbed by the body. (two text messages about the finishing of the effects)

Cancel all changes in the test_med.json file. Concentration is equal to 1, rate parameter is equal to 15 minutes. Change the vit_type.

Practical result. Time
8:59:50 Tablet consumed. Message received about vit_AMED_I vitamin appearance
9:00:00 Three messages. Vitamin vit_AMED_I is missing. Vitamin vit_AMED_II appeared and immediately disappeared

3

Shift the pill time by 10 seconds Time
9:00:00 Tablet consumed. Message received about vit_AMED_I vitamin appearance
9:15:00 Message received about vit_AMED_I vitamin missing
9:30:00 Two messages received. Vitamin vit_AMED_II appeared and then disappeared immediately.

4

Now let's increase the concentration to 10 units. 8:59:50 - Tablet consumed. The consumption time of the tablet is 6 seconds, so the first measurement is at 8:59:56. Format for recording the concentration: daily / overall

Time vit_AMED_I vit_AMED_II
8:59:56 10 / 10 0 / 0
8:59:59 10 / 10 0 / 0
9:00:00 10 / 9 10 / 9
9:14:59 10 / 9 10 / 9
9:15:00 10 / 8 10 / 8
9:29:59 10 / 8 10 / 8
9:30:00 10 / 7 10 / 7
9:44:59 10 / 7 10 / 7
9:45:00 10 / 6 10 / 6
10:00:00 10 / 5 10 / 5
10:15:00 10 / 4 10 / 4
10:30:00 10 / 3 10 / 3
10:45:00 10 / 2 10 / 2
11:00:00 10 / 1 10 / 1
11:15:00 10 / 0 10 / 0

One last check, let's increase the rate parameter to 60 minutes.

Time vit_AMED_I vit_AMED_II
8:59:56 10 / 10 0 / 0
8:59:59 10 / 10 0 / 0
9:00:00 10 / 9 10 / 9
9:30:00 10 / 9 10 / 9
9:59:59 10 / 9 10 / 9
10:00:00 10 / 8 10 / 8
11:00:00 10 / 7 10 / 7
12:00:00 10 / 6 10 / 6
13:00:00 10 / 5 10 / 5
14:00:00 10 / 4 10 / 4
15:00:00 10 / 3 10 / 3
16:00:00 10 / 2 10 / 2
17:00:00 10 / 1 10 / 1
18:00:00 10 / 0 10 / 0

Conclusions

  1. Vitamin vit_AMED_I enters the body immediately. The time of absorption of the first unit depends on what expires first. The time defined in the rate or the current stomach cycle, equal to 30 minutes, will be completed. Subsequent units are absorbed according to the rate value.
  2. Vitamin vit_AMED_II enters the body after the cycle is completed. It immediately consumes one unit. Further absorption is based on the rate value only.
  3. In any case, this is nowhere near what one would expect.

3. Conclusion. None of the ways in which the vitamin enters the body are consistent with the documentation. I'm not at liberty to say what the problem is. Perhaps incorrect implementation or insufficiently detailed description in the documentation.

The most universal method is to include the vitamin in the use_action section. Then regardless of the type of vitamin, it has the same behavior. If the item is not supposed to use this section (why does it need vitamins?). Then it is better to use the drug type. Since they have the most predictable behavior.

Separately, I would like to point out that the higher the concentration, the less the influence of the way the vitamin is recorded. For example, if the concentration is 1000, it makes no difference whether the count starts at 1000 or 999.

At the same time, it is not possible to accurately predict the duration of the vitamin. Because it is not known at what point in the stomach cycle the tablet will be taken. This is especially critical for long-acting vitamins with small concentrations. To give you an example: 1 vitamin with a 1-day duration, will be absorbed in the first half hour.

Attach save file

n/a

Steps to reproduce

n/a

Expected behavior

  1. I would like clearer documentation.
  2. I would like these vitamins (toxin, counter, drug) to be independent of the stomach cycle. 2.1. Or it was counted from the moment of taking the vitamin. 2.2. If dreaming, a separate parameter setting the time after which it will appear in the body. But this is more to the redesign of the entire drug system.

Screenshots

No response

Versions and configuration

Tested on game version: cdda-windows-tiles-x64-2024-10-04-0532

Additional context

No response

IdleSol commented 3 weeks ago

Turns out that's not the end of it. Let's take the original version of the pill. The concentration is 1, set the absorption time to 16 minutes (so that it is not a multiple of 30 minutes).

3.1 "vit_type": "toxin" and "vit_type": "counter" Time
8:59:50 Tablet consumed. Message received about vit_AMED_I vitamin appearance
9:00:00 Nothing
9:04:00 Message received about vit_AMED_I vitamin missing
9:30:00 Message received about vit_AMED_II vitamin appearance
9:36:00 Message received about vit_AMED_II vitamin missing

5

Time
9:00:00 Tablet consumed. Message received about vit_AMED_I vitamin appearance
9:04:00 Message received about vit_AMED_I vitamin missing
10:00:00 Message received about vit_AMED_II vitamin appearance
10:08:00 Message received about vit_AMED_II vitamin missing

6

8:00:00 + 4x16 = 9:04:00 + 2x16 = 9:36:00 + 2x16 = 10:08:00

But 8 hours, that's 8 x 60 / 16 = 30. Let's change it to 17 minutes, to check the starting point.

Time
8:59:50 Tablet consumed. Message received about vit_AMED_I vitamin appearance
9:15:00 Message received about vit_AMED_I vitamin missing
9:30:00 Message received about vit_AMED_II vitamin appearance
9:32:00 Message received about vit_AMED_II vitamin missing

9:15:00 + 1x17 = 9:32:00

08:00:00 + 4x17 = 9:08:00 != 9:15:00 00:00:00 + 32x17 = 9:04:00 != 9:15:00

??? 19 min: 9:04:00 23 min: 9:00:00

And also 9:00:00 is 5216400 moves (=sec), which corresponds to 60 full days and 9 hours. So we count the cycle from the “creation” of the world? I guess that makes sense?

No one wants to see how much resources it takes? Make a tablet with 10-20 different vitamins and different rate parameters and look at the load.

3.2. "vit_type": "drug" rate = 16 min Time
8:59:50 Tablet consumed. Message received about vit_AMED_I vitamin appearance
9:00:00 Message received about vit_AMED_II vitamin appearance
9:04:00 Two messages. Vitamin vit_AMED_I and vit_AMED_II is missing
Time
9:00:00 Tablet consumed. Message received about vit_AMED_I vitamin appearance
9:04:00 Message received about vit_AMED_I vitamin missing
9:30:00 Message received about vit_AMED_II vitamin appearance
9:36:00 Message received about vit_AMED_II vitamin missing