Skip to content

The future of riot damage and other post-processing generators #79943

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
RenechCDDA opened this issue Mar 2, 2025 · 3 comments
Closed

The future of riot damage and other post-processing generators #79943

RenechCDDA opened this issue Mar 2, 2025 · 3 comments
Labels
[C++] Changes (can be) made in C++. Previously named `Code` Code: Infrastructure / Style / Static Analysis Code internal infrastructure and style [JSON] Changes (can be) made in JSON Map / Mapgen Overmap, Mapgen, Map extras, Map display stale Closed for lack of activity, but still valid. <Suggestion / Discussion> Talk it out before implementing

Comments

@RenechCDDA
Copy link
Member

RenechCDDA commented Mar 2, 2025

Is your feature request related to a problem? Please describe.

The current implementation of the 'riot damage' generator is hardcoded except for the flag which controls whether it runs. This is not ideal for a variety of reasons:

-Changing or tweaking any values require compiling C++, raising the effort bar for contributors.

-The same (re)compilation means turnaround time for testing changes to it is slow. JSON changes have almost 0 overhead, C++ changes have a very sharp minimum.

-The settings are not always appropriate for different gameplay experiences. Right now they are tailored towards vanilla CDDA, but not everything wants vanilla CDDA settings! For example we have the 'No Hope' mod, which aims for a darker bleaker world. It likely wants more riot damage, crazier stuff. But it has no way to do that, it can only toggle the riot damage on or off.

Solution you would like.

The solution is obvious: We offload most of the specific values into JSON, where mods can overwrite, extend, and modify it as they see fit.

The way I envision doing this requires a new JSON object type.

Here's an example of what the JSON format would look like:

  {
    "id": "PP_RIOT_DAMAGE",
    "type": "pp_generator",
    "generators": [
      { "id": "move_stuff_around", "attempts": 20, "min_distance": 1, "max_distance": 5 },
      { "id": "smash_stuff_up", "attempts": 20, "chance": 20, "min_bash": 6, "max_bash": 60 },
      { "id": "place_blood_streak", "attempts": 2 },
      { "id": "place_blood_circular_pool", "attempts": 1, "chance": 50 },
      { "id": "start_a_fire", "attempts": 1, "chance": 10 }
    ]
  }

This data would be attached to the overmap_terrain object and could be copy-from'd or extended/deleted, as a whole. That is if we added the above to generic_city_building_no_sidewalk it would apply to anything copying from that abstract. But it would not apply to rural buildings, as they would "delete": { "pp_generator": [ "PP_RIOT_DAMAGE" ] },.

If buildings needed finer control over which generators run, they would create a new pp_generator object. Here's one that only sets a bunch of fires:

  {
    "id": "PP_RANDOM_FIRES_ONLY",
    "type": "pp_generator",
    "generators": [ { "id": "start_a_fire", "attempts": 10, "chance": 100 } ]
  }

This allows granular control over the exact 'noise' applied to mapgen, to a degree. (If even more granular control becomes needed, we could do away with the pp_generator object and apply generators directly as part of the overmap_terrain.)

This will require some refactoring of the existing C++ code in addition to the new json objects. Let's take a look at some of it. Pretend we are running the program with our earlier riot damage generator, on smash_stuff_up.

{ "id": "smash_stuff_up", "attempts": 20, "chance": 20, "min_bash": 6, "max_bash": 60 },

https://github.com/CleverRaven/Cataclysm-DDA/blob/master/src/mapgen.cpp#L446-L449

The post-changes code would look something like this:

        for( auto generator : md.all_generators ) {
            switch( generator_type ) {
			
			    // insert other sub-generators as individual cases

                case generator_type::smash_stuff_up:
                    for( int i = 0; i < generator.attempts; i++ ) {
                        if( x_in_y( generator.chance, 100 ) ) {
                            tripoint_bub_ms current_tile = random_entry( all_points_in_map );
                            md.bash( current_tile, rng( generator.min_bash, generator.max_bash ) );
                        }
                    }
                    break;

                default:
                    break;
            }
        }

Notice how we've reduced the "magic numbers" down to a single one, 100. As an overarching rule this is much better for readability and maintenance. As a side benefit, breaking these up into individual "sub"-generators will eliminate much of the math weirdness I introduced. Instead of having to calculate 3-4 dependent events which may preclude your math from having the exact chance it says that it does, we run them independently at the exact chance. This will head off confusion before it starts.

Describe alternatives you have considered.

No response

Additional context

No response

@RenechCDDA RenechCDDA added <Suggestion / Discussion> Talk it out before implementing [JSON] Changes (can be) made in JSON Map / Mapgen Overmap, Mapgen, Map extras, Map display [C++] Changes (can be) made in C++. Previously named `Code` Code: Infrastructure / Style / Static Analysis Code internal infrastructure and style labels Mar 2, 2025
@PatrikLundell
Copy link
Contributor

PatrikLundell commented Mar 2, 2025

As a side note, if the lead developers are going to decide to try to keep mapgen strictly separated from game play map functionality in order to use bubble coordinates with implicit reality bubble references throughout except in mapgen, you have to be very careful with what functionality you add to the post processing, including exactly which operations you use to achieve it, as it's incredibly easy to call some operation that uses reference less coordinates somewhere down the call chain unless you know exactly what you're doing.
Moving items is probably fine, adding pools of blood as well, since that functionality is already provided to mapgen, and thus presumed to be safe and maintained. Bashing, too, is available currently, so that might be safe too, at least if you use exactly the same version as the standard mapgen does.

Once you try to add something that's not in the current mapgen functionality set you have to be very careful, especially if it invokes weirdo call chains such as ammo checking or doing something to vehicles (beyond placing them and bashing them with the current mapgen used operation while they're fully within the OMT generated. Pushing vehicles around? I wouldn't count on it working correctly. Trying to do something with appliances? Ditto.

Don't expect things to work just because it's a map operation: many have ugly call chains that involve reference less (i.e. implicit reality bubble) usage rather than the (mapgen) map that originated the chain.

@LyranRenegade
Copy link
Contributor

LyranRenegade commented Mar 6, 2025

My 2 cts:
Just as a note, besides moving stuff (and adding damage to it?) we can already do these things in JSON. Albeit very cumbersome.

Besides the ability to just disable it for some quests my main concern with the RIOT damage is that it looks so random.. (Don't understand why all buildings have a chance to randomly catch fire, etc.) It would be way cooler if there was some logic involved in picking hotspots for violence / violent looting instead of spreading it (thinly) all over the place.

[Maybe by means of a list of mapgen-ids that have increased riot % [customizable in json?] -> ) When having determined some hotspots in the city also within that area specify some spots for outburst of violence / damage, so instead of a building randomly having 20 damaged tiles, get a spot or 2, 3 and have all the tiles around that damaged..
(But this can just be a variable 'centripetal_force' or something, deviating according to the scenario, so some damage being more widespread and light (hooligans trashing a train), and some more intense and localized (cars crashing into building, grenades)

(Chance for riot-effects diminishing based on distance to those centers..)
And have separate logic for damage, fire, blood and people throwing stuff around. (It can be more or less the same logic, but with slightly different weights, so it all will look much more organic)

Blood outdoors would also disappear pretty fast depending on the weather.
I won't be of help writing C++ code but I've done a lot of simulations of (faking) organic processes so I could write down some algorithms for those if desired

(Also missing is a variable to set the decreased riot impacts over time.. like just swapping (most -> all) fires with clusters of debris/destroyed buildings)

Copy link
Contributor

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. Please do not bump or comment on this issue unless you are actively working on it. Stale issues, and stale issues that are closed are still considered.

@github-actions github-actions bot added the stale Closed for lack of activity, but still valid. label Mar 21, 2025
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Apr 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[C++] Changes (can be) made in C++. Previously named `Code` Code: Infrastructure / Style / Static Analysis Code internal infrastructure and style [JSON] Changes (can be) made in JSON Map / Mapgen Overmap, Mapgen, Map extras, Map display stale Closed for lack of activity, but still valid. <Suggestion / Discussion> Talk it out before implementing
Projects
None yet
Development

No branches or pull requests

3 participants