Nuclear Missle Damage + map deformation

Greetings,

I was reading the issues on github and issue #33606 at https://github.com/CleverRaven/Cataclysm-DDA/issues/33606 seems like a cool thing to implement.

So I wanted to locate the file that is responsible for the reality bubble, i.e. the camera and grepping through the files and could not locate what I was looking for. As I am yet still unfamiliar with a vast majority of the file structure can anyone tell me what the exact mechanic is that works on this.

Also thinking on this what is the exact chain of events that needs to occur to perform this action.

Source of information:
http://www.atomicarchive.com/Effects/index.shtml

  1. Zombies will not die directly unless >40psi is observed, greater pressure for evolved zombies.
  2. 5psi destroys most buildings
  3. heavy damage up to 3psi
  4. 1megaton bomb has a 1psi front up to 10miles from center if bomb detonates above the ground due to mach stem effect
  5. thermal energy is immediate for all due purposes or lasting up to 10 secs
  6. 1 minute after detonation of a 1megaton bomb it no longer has radiant heat
  7. Collapsed structures have a greatly increased chance to ignite
  8. a firestorm can occur at the location if there is greater than 8lbs of combustibles per sq ft and wind is less than 8mph
  9. a 1megaton bomb can cause flash burns to exposed skin up to 7miles away -> something like albino effects for everyone given distance from scene
  10. can cause flash blindness up to 13miles on a clear day or 53 miles on a clear night
  11. radiation is questionable -> can last only minutes or months/years depending on make up of the bomb.
  12. fallout is the dangerous part and suffers from the same limitation as 11
  13. EMP effects should occur to vehicles surround blast zone -> radius should be a function of bombs height -> should destroy any working controls in vehicles to simulate effect + possible other damage.

With all the above taken into account the next big thing is loading the reality bubble on the zones to be effected and then modifying them accordingly.

The chain of events is something I am not clear on.

In my mind it should go something like

  1. unload character
  2. move camera
  3. detonate bomb
  4. deform environment + buildings + vehicles given above effects
  5. update everything
  6. unload camera
  7. reload player

Now if the player is within the radius of the effects the player will not be unloaded but kept within to be effected.

I would like to know if this would be something interesting to add for anyone besides me because this sounds like a crazy “clear this entire zone of a wander spawn” option or like in the linked post an option to take out a bandit 100+ overmap tiles away.

I think that the adding an ability to unload and move the camera around however one likes would add the ability to create real artillery as well. This would allow for more complex weapon systems to be implemented both in the base game and by mods.

If this sounds like a cool idea let me know as I am reading though the game files to become more familiar with them before I start monkeying around with them.

EDIT: Moved to The Lab as I had it in the wrong category.

2 Likes

Also was thinking about this a little more.

Some assumptions I have after launch occurs.

  1. The flight path of the missile can either be visible or not depending on if there is a satellite system that tracks the missile

If there is a system that tracks the missile then show and update the map as it moves as presumably the player would like to watch this in motion.

  1. The yield of the missile can be adjusted based on some chance changing the effective range of the fallout/damage

Would be cool to find the Moab randomly that can annihilate somewhere like 30+ overworld map radius from point of detonation, although it would definitely be a game stopper.

This just sounds like too much fun so it should most certainly be in the game.

1 Like

I don’t have any useful coding knowledge to contribute, but I really like this idea. Have you been to the discord to ask around? We have the mod-dev-general channel there and someone could probably direct you to the actual developer discord channel (with no time constraints on repeat comment). This is a good place for long term discussion, but if you want some quick direction on where things are in the code the discord is a great place.

Nope on the discord but thanks for the information. I will get around to getting over there sooner or later.

1 Like

You should really just load a tinymap, adjust the contents of the tinymap, and save the tinymap. It’s a perfectly valid way to change existing map during play and doesn’t require unloading the existing character or move the character.

If you want the existing character to see the explosion, you’d be better off by giving them the debug invincibility trait, teleporting them to the bomb site, setting off the bomb, and teleporting them back to where they start and removing the debug invincibility trait if they didn’t have it before the teleports.

2 Likes

I don’t want them to “see” it but it’s location as it moves on the overmap. If they are in a location to see it they should be affected by the blast’s effects.

The deformation of the map is a must though as that is the cool part of the whole thing. The overmap movement is a w/e as it would be just another status that the player could observe.

1 Like

Ok, so here is what I am looking as so far.

In the src/explosions.cpp line 822-852 explosion_handler::nuke & src/computer.cpp line 624-693 computer::activate_function.

In these two files are the handles for the nuke. The explosions file handles the submaps, so the 12x12 section and the computer handles the overmap locations of the explosion.

For the computer.cpp it seems that the whole nuke explosion should be moved to the explosion_handler.cpp file.

From there I purpose the following.

Add

void nuke( const tripoint &p , const float megatons)
{
    const float blastPower = 4184000000000000;
    float realBlastPower = blastPower * megatons;
    tripoint dest( 0, 0, p.z );
    float powerloss ( const float power, const int x, const int y, const in z ) {
        // get the distance from the destination point and then modify the power by
        //  the inverse square to simulate power loss over distance
        float v = sqrt(pow(dest.x - x, 2), pow(dest.y - y, 2), pow(dest.z - z, 2));
        return power * 1 / sqrt(v);
    }

The megatons pass in is the real damage the nuke would bring to the equation. If it is over a certain threshold it will annihilate the tile else it will damage everything in the tiles appropriately.

Also, following my previous post about the contents causing fallout there could be a parameter that causes the nuke to be dirty randomly or something else.

Also as a note the power is in joules.

In addition I would also add in Z-level deformation with this while moving all deformation code to the explosion.cpp from the computer.cpp.

The radius of the blast would be directly linked with the power of the nuke. I have to ask though how distance should be handled though as the effects of the nuke should be HUGE.

I was thinking about something like the following,

int c_x = 0, c_y = 0, c_z = 0;
float c_power = realBlastPower;
while ( (c_power = powerloss(realBlastPower, c_x, c_y, c_z)) > 0) {
    // code to deform map
    deform(c_power, dest.xy(), c_x, c_y, c_z);
    // code to increment c_x, c_y, c_z
}

If anyone has an opinion on this let me know. I am going to flesh it out over the next few days.

The above will rapidly lose power as it leaves the epicenter of the explosion just like IRL. On top of that it would make the nuke adjustable and very dangerous.

Seeing overmap locations decimated in a radius of 4+ should be easy enough with much larger ones only a slight change to the megatons.

2 Likes

OK, I made a little progress and would like some feedback if anyone would.

So the code is more like pseudo code atm but that will change.

So here is what I am thinking of doing after checking some resources out.

  1. Calculate optimal height for an airburst detonation

This will be used when I implement z-level deformation

  1. Calculate the radius of the blast for differing psi levels
  2. Start deforming the map based on the potential damage given the psi at that location
  3. Kill any npcs at that location if needed

So the above are the steps I’m taking right now. With radiation it should be added depending on several factors but that is up for debate as there are many factors to consider with it.

Where I am at now is that I need to implement some methods to change the tiles for the lesser damage types so that the actual effects can be seen.

Another thing I need help with is how much the radius in meters is translated into the game.

An example is a 1kiloton nuke which has a effective 1psi wave up to 1.7 kilometers and a 10 psi wave up to 380 meters. At 1 psi it does mild damage to wooden structures and 10psi will practically destroy anything in the game minus subterranean stuff. So my question is how much of the overmap is covered by this 390 meter and 1.7 kilometers?

Here is the code

void nuke( const tripoint &p , const double kilotons)
{
    // Much of the information from
    //  https://www.princeton.edu/~aglaser/lecture2007_weaponeffects.pdf
    //  http://nuclearweaponarchive.org/Nwfaq/Nfaq0.html
    // was used to generate the effects
    int heightOnBurst (const int yield) {
        return 220 * pow(yield, 3); // Result in meters
    }

    const float twentypsiC = 0.2459600,
                tenpsiC = 0.3771600;
                fivepsiC = 0.5783200,
                twopsiC = 1.0427,
                onepsiC = 1.6639000;

    float radiusBlast ( const double yield, const float constant ) {
        return constant * pow(yield, 0.333);  // Output in meters
    }

    // TODO:
    //  Have to scale this R to game
    int twentypsiR = (int) radiusBlast(kilotons, twentypsiC),
        tenpsiR = (int) radiusBlast(kilotons, tenpsiC),
        fivepsiR = (int) radiusBlast(kilotons, fivepsiR),
        twopsiR = (int) radiusBlast(kilotons, twopsiR),
        onepsiR = (int) radiusBlast(kilotons, onepsiR);

    // Damage Types
    //  DESTROY:
    //      Destroys all things in tiles
    //  MAJORWITHCARS:
    //      Destroys most of a structure and cars
    //  MAJOR:
    //      Breaks most structures along with heavy damage to cars to simulate moving them
    //  MINORWITHANIMALS:
    //      Structures still stand with heavy damage and most animals are killed
    //  MINOR:
    //      Structures are moderately damaged with some in a complete state
    enum damageTypes = {
            DESTROY, MAJORWITHCARS, MAJOR, MINORWITHANIMALS, MINOR
    };
    void deformMap( const tripoint &point,  damageTypes damage) {
        tripoint p_zlevel( point.xy() , 0);
        tinymap tmpmap;
        tmpmap.load(p_zlevel);
        int &i = dest.x, &j = dest.y;

        for ( i = 0, i < SEEX * 2; i++ ) {
            for ( j = 0; j < SEEY * 2; j++ ) {
                switch ( damage ) {
                    // TODO:
                    //  Add more map modifiers to tmpmap for these special use cases
                    case DESTROY:
                        tmpmap.make_rubble( dest, f_rubble_rock, true, t_dirt, true );
                    case MAJORWITHCARS:;
                    case MAJOR:;
                    case MINORWITHANIMALS:;
                    case MINOR:;
                }
            }
        }

        tmpmap.save();
        overmap_buffer.ter( p_zlevel ) = oter_id( "crater" );   // Special zone for nuke

        if !(MINOR == damage)
        {
            // Kill any npcs on that omap location.
            for (const auto &npc : overmap_buffer.get_npcs_near_omt(p_zlevel, 0)) {
                npc->marked_for_death = true;
            }
        }
    }

    // Now for the actual work to be done.
    // Starting from the outer most R -> 1 psi too the center
    // Want to make this cleaner but cannot figure out how to do so atm
    for ( int y = onepsiR; y > 0, y++ ) {
        for ( int x = onepsiR; x > 0, x++) {
            tripoint c_point( dest.x + x, dest.y + y );
            if ( x < twentypsiR || y  < twentypsiR ) {
                deformMap( c_point, DESTROY )
            }
            else if ( x < tenpsiR || y  < tenpsiR ) {
                deformMap( c_point, MAJORWITHCARS )
            }
            else if ( x < fivepsiR || y  < fivepsiR ) {
                deformMap( c_point, MAJOR )
            }
            else if ( x < twopsiR || y  < twopsiR ) {
                deformMap( c_point, MINORWITHANIMALS )
            }
            else {
                deformMap( c_point, MINOR )
            }
        }
    }
}
1 Like

What I’d like to see is recasting this as a heavy artillery bombardment, perhaps 155mm howitzer or so.
In practice this is a scale that makes sense in the game, and it’s a resource that actually makes sense to have the player acquire.

That 380m is roughly 15 town blocks, which is about as big as our towns get, and the 1.7km is almost a quarter of an overmap (unless it’s radius, then it’s nearly an overmap). That’s way too big.

1 Like

I was thinking this was the same vein actually.

Where I am at right now though is thinking on how I will shell out the damage it does. this damage can be scaled in my mind which means that it can be applied by many different systems and not just the nuke/other large weapons. The core of the damage is caused by the over-pressure and not the explosion itself. This is the same thing larger weapons systems like a 155mm+ though there are special rounds designed to cause direct damage or extra effects like incendiary.

On the nuke side of things, a 1kiloton is a very small one most used now are in the multi-megaton range which makes their effective range much much bigger. It would be cool to completely destroy the map but that should require a huge amount of effort and should not be as simple as a computer check.

Overall I would like to have larger explosions, such as one that would take out a apartment building or so. It would be cool. A nuke might be too much but a theoretical “mini” nuke might work where it is sub 1kiloton. It could be used to destroy 2-3 radius tiles on the over map with its damage localized to the map where the effects are not to just destroy the map but the buildings and entities inside.

Also as a note, if I can get it to work the way I want. Not only would remote detonations work from projectiles but place-able c4 type things would work on the tiles as well.

Thanks for the input as I was looking for it.

1 Like

Modern nukes are generally in the 150 kton range, because destructiveness goes up with the square root of tonnage but production and maintenance costs are linear or worse. Multi-megaton bombs are really expensive, and a 10 warhead MIRV is generally cheaper and inflicts more damage.

The game’s current mini-nuke pretty much wrecks a single map tile’s worth of terrain.

1 Like

If it would be possible to “draw a circle” on the overmap to vector the omtiles queued for destruction of certain kind, you colud then apply a map extra on those tiles to simulate destruction. Problem with that is that map extra aims at overmap tile specifically so bigger craters that keep their roundness through multiple omts is something I can’t imagine how to achieve.

1 Like

instead of doing map_extras, do mapgen_update. You can specify mapgen_update for each overmap tile and each tile can be different.

So you would set an impact tile that gets the ground_zero JSON applied to, and the tile at (-1,-1) to the impact_tile would get ground_zero_nw JSON, and so on. There’s no limit here.

I do think adding a jmapgen_explosive would be a really elegant solution to this, and generally useful for simulating artillery strikes.

2 Likes

Sounds like a good idea. I will look into this later.

1 Like

OK, so what I am seeing right now is this. I would load the relevant json for that tile and then transform it based on what ever conditions I am going to apply correct?

So something like the gym

  "rows": [
    ".........,,,,,,.........",
    ".U.....,,,,,,,,,,U......",
    ".......,|--==--|,.......",
    ".......,8y    y8,.......",
    ".......,8##   r8,.......",
    ".......,8a#   f8,.......",
    ".......,8 #   r8,.......",
    "..,,,,,,8      8,,,,,,..",
    "..|55555|      |55555|..",
    "..|                  |..",
    "..| ! ! c      c @ @ |..",
    "..|     c      c     |..",
    "..| ! ! c      c @ @ |..",
    "..|     c      c     |..",
    "..| ! ! c      c @ @ |..",
    "..|                  |..",
    "..|+|    VVVVVV    |+|..",
    "..|&|  B        B  |&|..",
    "..|--+------+--|--+--|..",
    "..|cc cc||cc cc|*= =*|..",
    "..|     ||     |-| |-|..",
    "..|OOOOO||OOOOO|*= =*|4.",
    "..|------------|-----|..",
    "........................"
  ],

After being hit at a (x, y) would turn into

  "rows": [
    ".........,,,,,,.........",
    ".U.....,,,,,,,,,,U......",
    ".......,|--==--|,.......",
    ".......,8y    y8,.......",
    ".......,8##   r8,.......",
    ".......,8a#   f8,.......",
    ".......,8 #   r8,.......",
    "..,,,,,,8      8,,,,,,..",
    "..|55555R      |55555|..",
    "..|    RRR           |..",
    "..| ! RRRRR    c @ @ |..",
    "..|  RRRRRRR   c     |..",
    "..| ! RRRRR    c @ @ |..",
    "..|    RRR     c     |..",
    "..| ! ! R      c @ @ |..",
    "..|                  |..",
    "..|+|    VVVVVV    |+|..",
    "..|&|  B        B  |&|..",
    "..|--+------+--|--+--|..",
    "..|cc cc||cc cc|*= =*|..",
    "..|     ||     |-| |-|..",
    "..|OOOOO||OOOOO|*= =*|4.",
    "..|------------|-----|..",
    "........................"
  ],

The capital r is the damage. So to do this for localized areas like small effects would be a good start. For larger effects the whole tile should be effected with residuals being radiated outward.

I am looking at this mapgen.cpp/h is there any good examples like fire damage for example that I can use to start working with this? I am going to keep looking though.

Thanks again for the thoughts.

1 Like

I don’t think doing specific map upgrades for each location is feasible. You want to do something like the following as part of a mapgen_update JSON:
"explosion": [ { "x": 22, "y": 5, "power": 500, "flags": "FIRE" } ]

and then write the C++ code to parse that into placing a power 500 explosion at location (22, 5) and having the explosion code already in the game work out what it means, and having that effect happen with the mapgen_update JSON happens.

I’d definitely keep any initial implementation in the sub-megaton range, just for the sake of manageable scales, and as noted, those weapons are actually uncommon in modern nuclear arsenals, which prefer more numerous smaller warheads.

FWIW, as a player I’d definitely like a quick cam-snap to the point of impact to see the initial blast, just for cinematic effect - even tho there’s no practical game value to it. :smiley:

1 Like

I would love that, even for a 155mm round it would be cool.

Image a side view of the location with like 10-100 tiles distance.

         \\ //
         \\_//
          | |
          | |
          \ /




   **
  ****           /--------\
 ******         /          \
  ****         /            \
   ||          |    ___  _  |
   ||          |    | | |_| |
   ||          |    | |     |


Then BOOM!!!






         
     \    _/                         
    \_\ _/                      
       \                        \
       ||               ___  _  |
       ||               | | |_| |
       ||          |    | |     |

Looks like a bunch of fun.

I am looking at the explosion code and it should be what I want. I have a bunch of stuff to do this week so I likely will not get to work on it again till Friday-weekend.

For my understanding though, it does what I think right. It creates a localized explosion that deforms the tile, so things on the tile take damage based on the input power level?

I will play with it when I get some time so if it does then it is what I want for this.