[Missle damage rework] Procedural explosion damage algorithm: an attempt

    Thalanor

    CEO Snataris Colonial Fleetyards
    Joined
    Sep 10, 2013
    Messages
    818
    Reaction score
    708
    • Master Builder Bronze
    • Thinking Positive
    • Legacy Citizen 3
    Hi there,
    without alot of extra talk, I'd like to suggest a new algorithm for missile damage calculation. It assumes that the game engine supports a halfway efficient retrieval of a block's neighbours (both adjacent and diagonal neighbours).

    Simply put: the goal is to achieve explosion "holes" that are a) procedurally (randomly) generated each time instead of smooth spheres, b) look halfway realistic and "rough", like you would expect a hole in the side of a battleship to look like, and c) destroy exactly as many blocks worth of EHP as the missile damage. Admittedly this system would not synergize with preset missile damage radius maximums except using them as hard-cap for maximum spread of block destruction (like it is the case now).

    Update: Note that it would performance-wise perhaps be more feasible to just precompute 10-20 different explosions and then choose one each time and go through the blocks in the list produced by the algorithm in exact order from top to bottom until the damage is "used up". A block list produced by the algorithm makes for a valid explosion when cut off at an arbitrary point, too, because blocks are added to the list roughly from the inside out.

    Types are only rough suggestions, I don't know how things are modeled exactly.
    Code:
    explosionDamage(Missile missile) {
    blocksToKill <-- missile.getBlockInPosition();
    double damageLeftover = missile.damage - blocksToKill.get(0).hp
    boolean diagonal = true;
    while (damageLeftover > 0) { //continue causing havoc
    blockNeighbours = selectNeighboursOf(blocksToKill, diagonal)
    diagonal = !diagonal;
    randomlyDeselect25%(blockNeighbours)
    foreach block in blockNeighbours: {
      damageLeftover -= block.effectiveHealth;
      blocksToKill.add(block);
      if (damageLeftover <= 0) break;
    }
    }
    }

    A: Any "hole" in the growing blocksToKill list (shown in white) will be considered for "filling it up" with a chance of 75% every single phase. As such, roughness almost only occurs in the very outmost borders of the thing, as well as influencing the general shape of the growing crater.

    Adjustable to the max!
    - Fraction of blocks deleted from candidate list each "phase". 25% works really well I think.
    - Ability to enforce certain patterns (like shrapnel weapon effects) by chaining multiple phases with very low retention rate after short numbers of phases with more average settings, or making a more clustered retention selection in some phases to force more sharply distorted non-cubes, or by adding single random additional outlier blocks not connected to the current list of blocks
    - Would technically allow an entire rework of how area damage is handled for the explosive weapon effect on cannons, too!
    Also, at no point are trigonometric functions needed. Using the same random seed, the procedural generation could take place in exactly the same way in all clients.
     
    Last edited:
    Joined
    Jul 21, 2013
    Messages
    2,932
    Reaction score
    460
    • Hardware Store
    I like it, the question is weither or not this algorithm is viable performance-wise.
    Also what exactly is the criteria to stop repeating the last 3 steps? selected block-count? sum of the HP of all selected blocks? missile-blast-radius?
     

    Thalanor

    CEO Snataris Colonial Fleetyards
    Joined
    Sep 10, 2013
    Messages
    818
    Reaction score
    708
    • Master Builder Bronze
    • Thinking Positive
    • Legacy Citizen 3
    Total EHP of blocks destroyed > missile damage is the criterion. There would no longer be a radius setting for missiles (optional part of the suggestion though).

    The efficiency of the algorithm can't be much worse than the current one if block neighbour retrieval can be done relatively fast. The current algorithm must somehow be able to step-wise select blocks in some way, too. Especially the complete absence of trigonometric functions is a huge performance gain. As funny as it sounds, the rough "circleness" is estabilished by the alternating adjacent-only / diagonals-too neighbour selection.
     

    Lancake

    Head of Testing
    Joined
    Aug 20, 2013
    Messages
    794
    Reaction score
    560
    • Schine
    • Tester
    Like megacrafter said, performance wise this is probably not a viable system. There's a reason why missile damage is divided in 6 stages and that's performance.
    Don't get me wrong, I would love this sort of system, especially the listed damage equals actual block damage aspect. I have my own ideas about how a new missile system would look like but again, it's all about the performance.

    100 groups of the uncapped punchthrough system could destroy 40 000 blocks per second, this is so bad that it would crash everyone in your sector and yourself. Your method is pretty much the same but in a radial way. A few big missiles hitting at the same time would possibly lag or freeze your PC.
     
    Joined
    Jul 21, 2013
    Messages
    2,932
    Reaction score
    460
    • Hardware Store
    I could imagine this as a viable method for "incinerating" weaponry, in which case each iteration is done with some time in-between.
     

    Thalanor

    CEO Snataris Colonial Fleetyards
    Joined
    Sep 10, 2013
    Messages
    818
    Reaction score
    708
    • Master Builder Bronze
    • Thinking Positive
    • Legacy Citizen 3
    Actually yes, it could work as a "plasma burn" stepwise algorithm indeed (as well as cannon explosive damage, although with a radius limiter here). Even missiles could have non-instantaneous destruction calculation (there is an update delay already anways).
     

    jayman38

    Precentor-Primus, pro-tempore
    Joined
    Jul 13, 2014
    Messages
    2,518
    Reaction score
    787
    • Purchased!
    • Thinking Positive
    • Legacy Citizen 4
    I do miss playing Scorch3D sometimes, and would enjoy seeing a procedural damage effect.

    Idea for linear explosive damage
    1. Use damage against impacted block.
    2. Divide remaining damage by 26.
    3. Wait a tick and Goto 1 for each surrounding block. (If there is nothing there, then the damage is wasted, to simulate the difference between an explosion in an enclosed space and an explosion in an open area which will naturally do less damage.)

    This spreads calculations out over multiple ticks, with more calculations in later ticks, and makes the explosion look better over time. (especially when we have a good explosion visual effect in place.)

    Additional idea to make it look more procedural: On step 3, have a random chance (or sequential chance based on procedural "seed") to simply skip that particular block. The block might still be destroyed in a later tick as a result of the splash effects from an adjacent block being destroyed.
    Furthermore, if a block is left in the middle of an explosion, it will add to the effect of debris from the explosion. That will look even better if break-off is enabled.
     
    Joined
    Jun 20, 2013
    Messages
    2,827
    Reaction score
    1,181
    • Video Genius
    • Legacy Citizen 4
    • Top Forum Contributor
    NeonSturm what do you say? can't you have some kind of fuction that would make this less performance craving? :p
     

    Thalanor

    CEO Snataris Colonial Fleetyards
    Joined
    Sep 10, 2013
    Messages
    818
    Reaction score
    708
    • Master Builder Bronze
    • Thinking Positive
    • Legacy Citizen 3
    Maybe it would be possible to just pre-calculate a number of differently seeded block lists, and for each explosion choose one at random and iterate over the block list until the missile damage is used up. The algorithm adds blocks to the list in an inside-first-outside-last manner, so this would in theory be doable.

    Although admittedly, the kind of radii currently in the game would not be feasible anymore one way or the other. An 58-radius crater just isn't going to happen, and would be better modeled as a sort of shrapnel system with multiple smaller delayed explosions.
     
    Last edited:
    Joined
    Aug 23, 2014
    Messages
    427
    Reaction score
    137
    • Purchased!
    Sounds cool, i just have one problem, explosions aren't really that random. Certain materials will give way before others.

    What i think needs to happen is that the missile needs to penetrate into the surface of the target a certain distance first, them explode. The explosion would then take the path of least resistance in every direction until either it lacks the energy to do additional damage, or it loses pressure by blowing a large enough hole out the side of the ship. The fact that fewer surface blocks would get destroyed would create the effect of jagged edges. It would be nice too if wedges and tetras weighed proportionally less and not only had less hp, but larger blocks would become them upon being damaged.
     

    NeonSturm

    StormMaker
    Joined
    Dec 31, 2013
    Messages
    5,110
    Reaction score
    617
    • Wired for Logic
    • Thinking Positive
    • Legacy Citizen 5
    NeonSturm what do you say? can't you have some kind of fuction that would make this less performance craving? :p
    Perhaps you could use decentralized networking of (EDIT: I meant calculations from) clients :)
    Or implement it in a way which makes stream-prozessing over multiple threads possible.

    The greatest source of lag in this algorithm _may_ be the random memory access.
    > If you can enforce all data being kept in the L1 cache of your CPU, it should be pretty fast.
    > > You can do this by limiting the dependence of generated data on far-away blocks.
     
    Last edited:
    Joined
    Jun 20, 2013
    Messages
    2,827
    Reaction score
    1,181
    • Video Genius
    • Legacy Citizen 4
    • Top Forum Contributor
    Perhaps you could use decentralized networking of clients :)
    Or implement it in a way which makes stream-prozessing over multiple threads possible.

    The greatest source of lag in this algorithm _may_ be the random memory access.
    > If you can enforce all data being kept in the L1 cache of your CPU, it should be pretty fast.
    > > You can do this by limiting the dependence of generated data on far-away blocks.
    :D