Skip to content
This repository was archived by the owner on Aug 31, 2026. It is now read-only.

Commit 0dad292

Browse files
committed
feat: a beam below the intensity threshold is absorbed, not passed through
- the threshold sits above the affordability line of metal - refused on price alone, a faint beam went clean through the plate - the probe reports both columns, so neither is read off a depth - each armour scenario gets its own lane: a round outlives its own wall
1 parent 368684f commit 0dad292

3 files changed

Lines changed: 130 additions & 66 deletions

File tree

‎src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java‎

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -433,14 +433,20 @@ public class ARConfiguration {
433433
* threshold of `perStage x ablation / referenceArea` that each block sets for itself. A faint beam
434434
* therefore never accumulates, and the battleship is safe without this knob.</p>
435435
*
436-
* <p>What the knob still buys, at a value ABOVE that affordability line, is a gate a pack can
437-
* raise deliberately, and the statement that a sub-threshold beam's energy is ABSORBED rather than
438-
* carried on to whatever is behind the plate. Below that line it is inert — it can only refuse
439-
* beams the pricing was going to refuse anyway. Set to zero so that it changes nothing until
440-
* somebody rules on where the line should be.</p>
436+
* <p>What the knob buys, at a value ABOVE that affordability line, is the thing the pricing does
437+
* NOT do: a sub-threshold beam's energy is ABSORBED. Without it a beam too weak to mark a plate
438+
* does not warm it — it passes clean through with everything it arrived with, a free x-ray of the
439+
* hull. That, rather than the battleship, is why the threshold is set.</p>
440+
*
441+
* <p><b>The default sits above the affordability line of METAL.</b> The line is
442+
* `perStage x ablation / referenceArea`, which each block sets for itself: with the shipped table
443+
* that is of order 8 000 for stone and 38 500 for an iron block. At 50 000 a small emitter does
444+
* nothing whatever to a metal hull, however long it is held, and its energy stays in the plate —
445+
* which is the qualitative gap between a big emitter and a small one, and the reason a pulsed
446+
* laser is worth building. Zero disables it and restores the x-ray.</p>
441447
*/
442448
@ConfigProperty(needsSync = true)
443-
public double beamAblationIntensityThreshold = 0.0;
449+
public double beamAblationIntensityThreshold = 50000.0;
444450
/**
445451
* How glancing a hit has to be before a solid round skips off METAL instead of digging in, as the
446452
* angle between the round and the surface normal in degrees: 0 is square-on, 90 is a pure graze.
@@ -784,7 +790,7 @@ public static void loadPreInit() {
784790
arConfig.ricochetIncidenceDegrees = config.get(WEAPONS, "ricochetIncidenceDegrees", 65.0, "How glancing a hit must be before a solid round skips off METAL rather than digging in, in degrees from the surface normal: 0 is square-on, 90 a pure graze. Only metal deflects, so a round never skips off a plank wall. 90 disables ricochet", 0.0, 90.0).getDouble();
785791
arConfig.ricochetRestitution = config.get(WEAPONS, "ricochetRestitution", 0.75, "How much of its speed a ricocheting round keeps. Below 1 a bounce costs something, which is what stops a round skipping between two plates forever", 0.0, 1.0).getDouble();
786792
arConfig.ablationResistanceFactor = config.get(WEAPONS, "ablationResistanceFactor", 20.0, "How much dearer a block is to boil away than to push through, when nothing has written it its own ablation row. Both are energy per unit volume removed; they are nowhere near the same magnitude, which is why a laser buys precision rather than digging power. 1.0 makes a beam dig exactly like a slug", 0.01, 1000.0).getDouble();
787-
arConfig.beamAblationIntensityThreshold = config.get(WEAPONS, "beamAblationIntensityThreshold", 0.0, "Energy per unit of a beam's cross-section below which it does not drill at all, its energy being absorbed as heat rather than carried onward. OFF by default: a stage is bought whole or not at all, so affordability is already an intensity threshold each block sets for itself, and a faint beam never accumulates. Raise this above that line only to gate beams the pricing would otherwise let through", 0.0, Double.MAX_VALUE).getDouble();
793+
arConfig.beamAblationIntensityThreshold = config.get(WEAPONS, "beamAblationIntensityThreshold", 50000.0, "Energy per unit of a beam's cross-section below which it removes nothing and its energy is absorbed as heat instead of being carried onward. The default sits above the affordability line of metal (order 38500 for an iron block), so a small emitter does nothing to a metal hull however long it is held. 0 disables it, and a sub-threshold beam then passes clean through the plate with everything it arrived with", 0.0, Double.MAX_VALUE).getDouble();
788794
arConfig.maxShotsPerWorld = config.get(WEAPONS, "maxShotsPerWorld", 256, "How many shots one world may have in flight at once. Further fire is refused until some land; nothing already in flight is ever dropped to make room", 1, Integer.MAX_VALUE).getInt();
789795
arConfig.shotVisibilityRadius = config.get(WEAPONS, "shotVisibilityRadius", 256, "How near a player the path of a fired round must pass before that player is told about it and can see it drawn, in blocks. 0 disables shot replication entirely — the mechanic still works, nothing is drawn", 0, Integer.MAX_VALUE).getInt();
790796
arConfig.enableFireControlSensor = config.get(WEAPONS, "enableFireControlSensor", true, "Whether fire-control sensors search for targets. Off, a sensor acquires nothing, publishes nothing and draws no power: batteries are pointed by hand, as they were before sensors existed").getBoolean();

‎src/main/java/zmaster587/advancedRocketry/command/test/TestProbeCommand.java‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,10 @@ private void handleDamage(MinecraftServer server, ICommandSender sender, String[
12841284
info.put("stage", zmaster587.advancedRocketry.damage.DamageState.getStage(world, pos));
12851285
info.put("maxStage", zmaster587.advancedRocketry.damage.DamageState.getMaxStage(world, pos));
12861286
info.put("stageCost", zmaster587.advancedRocketry.damage.StructureDamageEngine.stageCost(world, pos));
1287+
// What the SAME stage costs a beam: the ablation column, so a test can see which column
1288+
// it is being charged from rather than inferring it from a depth.
1289+
info.put("stageCostBeam", zmaster587.advancedRocketry.damage.StructureDamageEngine.stageCost(
1290+
world, pos, 1.0D, zmaster587.advancedRocketry.api.damage.ImpactKind.BEAM));
12871291
info.put("block", String.valueOf(world.getBlockState(pos).getBlock().getRegistryName()));
12881292
String destroyed = zmaster587.advancedRocketry.damage.BlockDamageSavedData.get(world)
12891293
.getDestroyedBlockName(pos);

0 commit comments

Comments
 (0)