Einstein-Engines icon indicating copy to clipboard operation
Einstein-Engines copied to clipboard

The Lightning-Factor

Open WarMechanic opened this issue 7 months ago • 3 comments

Description

So, the lightning system in the current back-end is actually a little bit smelly. Different levels of charge are determined by prototypes, and lightning targeting is hard fixated on ground rods. You can technically generate infinite power with a fork, a microwave, and a tesla coil, as tesla coils generate flat amounts of charge.

Another problem, is VM's obligation to emulate lightning effects rather than use a (eventually) cleaner lightning system due to a mixed-bag combination of the above described. I'm hoping that lightning changes could be used in the future to make any of the following possible:

  • Emperor Palpatine glimmerloose
  • Psionic slave power plants
  • Psionically induced EMP

This PR aims to improve the lightning system by first grounding it in reality. Lightning has an established charge that is absorbed by entities as it bounces, as well as implementing lightning forking behaviours. To accomplish this, lightning now pre-calculates a path before executing any effects (otherwise you would encounter anomalies like charge simply vanishing). Lightning has been made more unpredictable by swapping targeting priorities for probability weightings. If you have live sparks near machinery, you are probably doing something wrong.

This PR isn't done yet, I have yet to adjust the effects based on charge although the concept is implemented. Everything should eventually be overrideable with code, and even ignore the discharge system altogether.


TODO

Must-have

  • [x] Rework the lightning system so behaviour may be configured in-code rather than in-prototype. Must be VM approved if Noospheric Chain-Lightning has even a slim chance of existing.
    • [x] Function parameters should be able to parse functions for dynamic behaviour.
  • [X] Adjust lightning targeting to use probability weightings, rather than a hard targeting priority.
    • [x] Adjust LightningTarget on prototypes to use new probability weightings.
    • [x] Balance grounding rods / tesla coils.
  • [X] Implements forking lightning.
  • [X] Implements the concept of lightning charge.
    • [X] Allow tesla coils to generate power based on incoming charge, multiplied by some efficiency multiplier.
    • [x] Scale lightning damage from a function of charge
  • [x] Remove the electrified component from lightning prototypes, and use events to determine electrocute effects
  • [x] Separate exploding behaviours from LightningTarget and have it trigger an explosive component instead (or something else?)
  • [x] Test before review if a tesla can destroy a station without throwing a compiler error.
  • [x] Fix electrocute parsing damage as an INTEGER
  • [x] Make lightning functions available on Shared

Nice

  • [ ] Make sure the code is not shit.
  • [X] Lightning can now be configured to disable looping (lightning chaining between two targets)
  • [X] Fix lightning ball sprites being unshaded.
  • [ ] Add construction and machine boards for Tesla coils and Grounding rods

The future

  • [ ] Translate lightning charge to overvolt behaviours in a future overvoltage system.
  • [ ] Create a Static Discharger infrastructure that releases excess voltage in the form of dangerous lightning.
  • [ ] Find a connection between this lightning refactor and my other EMP overhaul.
  • [ ] Extend LightningTarget!
    • [ ] Allow metallic items to contribute to a player's lightning susceptibility.
    • [ ] Combine a shotgun and a tesla gun for fun.
  • [ ] Remake the Tesla Gun as a traitor item that anchors to the station power grid. Must use the half-life tau cannon sound or its dead to me.

Technical Details

Code changes from most complex to least complex

  • C.S/.../LightningSystem.cs is the big fish here, and is hardly recognisable from its original incarnation:

    • LightningSystem functions now use a 'charge' variable which can be used to calculate factors like damage.
    • A new LightningContext struct is used by LightningSystem which encapsulates the data of any given lightning bolt. LightningContext contains a list of every LightningArc that pertains to it, and iterates through them to execute lightning effects like creating a beam from one entity to another and dealing damage. LightningContexts are stored in a dictionary with a unique index, which functions like an array that effectively can expand infinitely.
    • LightningSystem has been reworked to support forking arcs, which requires each lightning step to be depth wise. Previously recursive behaviour wouldn't work as the lightning would continuously fork until it ran out of arcs, creating a chain. LightningArcs are a new type which are fed into a priority queue system and dequeued based on lowest arc depth. When the priority queue is empty, it immediately triggers lightning effects and cleans the LightningContext dictionary.
    • As an extension of the above, the entire path of any given lightning bolt is now calculated before any effects take place. This is useful for ensuring charge consistency such that a fired lightning bolt will not net positive charge after bouncing into tesla coils. Every time lightning arcs, an equal portion of charge is subtracted as a 'discharge' variable and used for damage calculations. The total charge may be modified afterwards by LightningTarget which reduces effect on subsequent targets.
    • Random target selection used by LightningSystem functions use a weighted probability dictionary rather than a sorted list. This makes lightning behaviour much more random, but still permits control over the general likelihood of one thing being targeted over another. This was done to make lightning more spectacular.
    • ShootLightning and ShootRandomLightning have been updated to support parsing of functions rather than values. This is extremely useful for dynamic/random behaviours.
    • HitByLightningEvent was renamed to LightningEffectEvent, and added LightningStageEvent. Some of the file diffs will mention this name change.
  • C.S/.../LightningTargetSystem.cs is adjacent and responsible for creating targets for lightning to arc toward.

    • LightningArcResistance has been extended into LightningArcReduction, LightningChargeReduction, LightningChargeMultiplier to encompass new lightning interactions.
    • Now uses ElectrocutionSystem to conditionally deal damage and apply the paralysed status effect, rather than relying on prototype physics collisions.
    • Communicates with the Explosive component to conditionally trigger it when struck by lightning.
  • C.S/.../LightningTargetComponent.cs has changes which reflect the above system changes. Additionally, all redundany explosive-related-vars have been culled as they should be used in Explosive.

  • C.S/.../ElectrocutionSystem.cs had some questionable logic fixed where some functions would return false depending on input parameters. Essentially, the effect of damage and stunning is independent. This allows machines to take damage from electrocute (finally putting electronic shock vulnerability to use!)

    • Also allowed parsing a damage specifier instead of an INT (???) for damage. This gives breathing room for creative reuse of the lightning system, like dealing cold or psychic damage. Instances of int were replaced with FixedPoint2.
  • C.Sh/.../ElectrocutionSystem.cs had an int changed to a DamageSpecifier.

Beyond the core logic, users of the LightningSystem were also changed to various degrees:

  • C.S/.../LightningArcShooterSystem.cs has been updated to use the new function parsing functionality that LightningSystem provides. Instead of shooting a random number of lightning bolts with a flat number of arcs, the system tallies a random number of bolts and a random number of arcs to fire. With extremely good(?) luck, you could roll 4 bolts each with only 1 arc. With quantum bad(?) luck, you could roll a singular bolt that extends a 16 arc long chain from tesla containment all the way to the Engineering substation, which proceeds to cut emitter power which then looses the tesla.

  • C.S/.../LightningArcShooterComponent.cs has variable changes that reflect the system changes.

  • C.S/.../TeslaCoilSystem.cs now uses discharge from LightningSystem rather than generating a flat amount of charge whenever hit by lightning. Also renamed HitByLightningEvent.

  • C.S/.../TeslaCoilComponent.cs has ditto.

  • C.S/.../ElectricalAnomalySystem.cs had ShootRandomLightning updated.

  • C.S/.../MicrowaveSystem.cs had ShootRandomLightning updated.

  • C.S/.../GlimmerReactiveSystem.cs had ShootRandomLightning updated.

  • C.S/.../LightningSparkingSystem.cs had HitByLightningEvent renamed.

For unique prototype changes

  • Resources/Prototypes/Entities/Effects/lightning.yml had every instance of Electrified removed, since LightningSystem uses ElectrocutionSystem instead.

  • Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml was updated to accomodate new changes to LightningArcShooter, and also fixed a bug where shader: unshaded was not put in the correct location.

  • Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml Tesla coils get a target weighting of 200, and now have the ShockAbsorber damage modifier that zeroes incoming shock damage. Grounding rods get a target weighting of 400 and also have ShockAbsorber.

Every other prototype change from hereon is simply configuring either Explosive or LightningTarget components.

  • Resources/Prototypes/Entities/Mobs/base.yml Mobs get a weighting of 10.

  • Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml Airlocks get a weighting of 10.

  • Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml Lights get a weight of 2.

  • Resources/Prototypes/Entities/Structures/Machines/Computers/base_structurecomputers.yml Computers get a small explosion, and get a weight of 10.

  • Resources/Prototypes/Entities/Structures/Machines/base_structuremachines.yml Machines get a small explosion, and get a weight of 20.

  • Resources/Prototypes/Entities/Structures/Power/apc.yml APCs have a moderate explosion, and get a weight of 25.

  • Resources/Prototypes/Entities/Structures/Power/smes.yml SMESes have a moderate explosion, and get a weight of 75.

  • Resources/Prototypes/Entities/Structures/Power/substation.yml Both substations maintain their large explosion, and get a weight of 50.


Media

Example Media Embed


Changelog

:cl:

  • tweak: Lightning has undergone a rework, allowing lightning to fork and act more randomly.

WarMechanic avatar Jul 12 '24 15:07 WarMechanic