Add Iron Coast II Black Tide eight-mission campaign
This commit is contained in:
1 parent
a08b932beb
commit
71cb7cdba3
4492 files changed
+164577
-45
No files matched your search
@@ -0,0 +1,62 @@
|
||||
# Depth Charge 1.0.0
|
||||
|
||||
Enable **Depth Charge** in Mods, apply at the main menu, then buy it in the shop
|
||||
for **525,000 credits**. It is an independent API 1 mod without dependencies or
|
||||
overrides. Maximum one; resale returns 262,500 credits. It occupies a normal
|
||||
inventory slot and preserves other equipment.
|
||||
|
||||
This is a **selectable, reusable ground/naval special weapon**. Choose it in
|
||||
Inventory or with Alt/Shift, then hold Ctrl to launch. Space remains the owned
|
||||
mega-bomb control. It does not consume charges or auto-attack merely because it
|
||||
is equipped. Always-equipped forward guns remain available alongside it.
|
||||
|
||||
The native straight projectile travels six logical pixels per simulation tick.
|
||||
A real ground-enemy collision deals 72 primary damage and starts one local
|
||||
ground-blast effect. At most three other living ground enemies can receive
|
||||
collateral damage: 36 damage within 16 pixels of the primary enemy's center,
|
||||
or 20 damage between 16 and 36 pixels inclusive. The closest neighbors are
|
||||
selected first, with stable entity order breaking ties. Aircraft, offscreen
|
||||
enemies, repeated targets and centers outside that radius are excluded. If the
|
||||
primary target dies, its contact still triggers the local blast correctly.
|
||||
|
||||
The deliberate 48-tick cooldown is about 2.06 seconds at 70/3 Hz. The charge does
|
||||
not home or detonate automatically in empty space. Slow travel makes moving
|
||||
ground targets an aiming challenge; there is no screen-wide damage command.
|
||||
Destructible terrain receives native primary damage, but cannot trigger scripted
|
||||
collateral because the public snapshot contains enemies rather than terrain
|
||||
cells. Enemy contacts emit impact audio; a miss produces only the launch sound
|
||||
and projectile. The normal native terrain destruction effects remain available.
|
||||
|
||||
SD equipment/projectile canvases are 16×16 and 8×12; detailed HD variants are
|
||||
64×64 and 32×48. Options selects SD or HD artwork without changing logical
|
||||
placement or damage. Both are single aligned frames with transparent margins.
|
||||
[Artwork provenance](art-provenance.json) records unchanged generated masters,
|
||||
prompts, final PNG hashes and the Rust preparation recipe. All new images, WAVs,
|
||||
source masters and recipes are included; decoded original style references are
|
||||
kept outside the mod.
|
||||
|
||||
`python3 generate_audio.py` reproduces the mechanical launch and low naval impact
|
||||
from deterministic synthesis without external recordings. `prepare_art.rs`
|
||||
rebuilds SD/HD fitting from the included source masters. The companion Railburst
|
||||
package's [review helper](../iron_coast_railburst/validation/review.py) is a developer
|
||||
tool for both packages and is not a gameplay dependency.
|
||||
|
||||
From the RustRaptor directory:
|
||||
|
||||
```sh
|
||||
cargo test --locked --no-default-features --test iron_coast_stage2_weapons
|
||||
cargo run --locked --no-default-features -- --data data --mods mods \
|
||||
--validate-mods iron_coast_depth_charge
|
||||
IRON_COAST_STAGE2_BALANCE_REPORT=/tmp/stage2-balance.json \
|
||||
cargo test --locked --no-default-features --test iron_coast_stage2_weapons \
|
||||
real_catalog_700_tick_balance_and_coexistence_report -- --ignored --nocapture
|
||||
```
|
||||
|
||||
[validation/balance.json](validation/balance.json) records the actual controlled
|
||||
700-tick damage observations supporting this price and role. Portable checks
|
||||
cover ground filtering, inner/outer falloff, the finite neighbor cap, misses,
|
||||
kills, cooldown, independent activation, coexistence, half-price resale, full
|
||||
inventory preservation, deterministic state/RNG continuation and whole-tick
|
||||
rollback. [validation/review.json](validation/review.json) distinguishes public
|
||||
decoder/blitter/mixer captures from live desktop review. Read the [API](../../docs/modding-api.md)
|
||||
for save pins and script execution limits.
|
||||
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"tool": "built-in image_gen through imagegen skill",
|
||||
"skill": "/home/quintine/.codex/skills/.system/imagegen/SKILL.md",
|
||||
"style_reference_catalog_ids": [
|
||||
"102b6",
|
||||
"101cb"
|
||||
],
|
||||
"style_reference_delivery": "Original catalog inspected separately; decoded originals are not included in this mod. The generated artwork is newly authored.",
|
||||
"source_records": [
|
||||
"art/generation-equipment-v1.json",
|
||||
"art/generation-projectile-v1.json"
|
||||
],
|
||||
"prompt_records": "prompts.json",
|
||||
"conversion_recipe": "prepare_art.rs",
|
||||
"conversion": "Fit alpha>=128 source bounds preserving aspect into one logical pixel margin; SD Triangle reduction and HD4x Lanczos3; binary final alpha128. Raw masters remain byte-identical to builtin outputs. Faint master glow outside the fitting bounds is not a separate in-game effect.",
|
||||
"canvases": {
|
||||
"equipment_sd": [
|
||||
16,
|
||||
16
|
||||
],
|
||||
"equipment_hd": [
|
||||
64,
|
||||
64
|
||||
],
|
||||
"projectile_sd": [
|
||||
8,
|
||||
12
|
||||
],
|
||||
"projectile_hd": [
|
||||
32,
|
||||
48
|
||||
]
|
||||
},
|
||||
"animation_frames": 1,
|
||||
"palette": "Engine maps ordinary PNG artwork to original palette0..239; no reserved palette effects requested.",
|
||||
"audio_recipe": "generate_audio.py",
|
||||
"audio_provenance": "audio/provenance.json",
|
||||
"outputs": [
|
||||
{
|
||||
"path": "art/equipment-generated-source-v1.png",
|
||||
"sha256": "669202bb78951419c9a1f61070be5dba7a55d8bfe096a071ae9cde86a8e26d3a"
|
||||
},
|
||||
{
|
||||
"path": "art/equipment-hd.png",
|
||||
"sha256": "b906ee08176c1fe429d61fcb22fe0ea06a513d11efb063def6639809466274ea"
|
||||
},
|
||||
{
|
||||
"path": "art/equipment-sd.png",
|
||||
"sha256": "61a9a9edc3fdb257e7f82e70c61d1fd3688728cd9c65cadf2b2e50e82fb789fd"
|
||||
},
|
||||
{
|
||||
"path": "art/projectile-generated-source-v1.png",
|
||||
"sha256": "0bc76b678c0d2db073ccf76ba2162465b3beb7fd78d505d875c95c594daeb29d"
|
||||
},
|
||||
{
|
||||
"path": "art/projectile-hd.png",
|
||||
"sha256": "1fb0ef6030151d68a477546711f8af120eb2563541d117147c6c2ee4f42f730d"
|
||||
},
|
||||
{
|
||||
"path": "art/projectile-sd.png",
|
||||
"sha256": "80a98973fa5e887bec6d90e603b50cef693f7ea69d00b3b8608569a1e59e0776"
|
||||
}
|
||||
],
|
||||
"recipe_hashes": {
|
||||
"prepare_art.rs": "bd1d0514317e5063989f2371b9ca9fd71756cb502b0066d9932f6f39031de3f6",
|
||||
"generate_audio.py": "a554a3a0e2b8f5432705fe32006c87998984b6e27430ac5a77b163c313760fce"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 912 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 610 B |
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"tool": "built-in image_gen",
|
||||
"builtin_original_output_path": "/home/quintine/.codex/generated_images/01a129a5-0efd-7c61-8556-922e09c8ea6c/exec-584bb594-5382-4b01-95ac-a78ce6f08c45.png",
|
||||
"local_raw_copy": "equipment-generated-source-v1.png",
|
||||
"raw_sha256": "669202bb78951419c9a1f61070be5dba7a55d8bfe096a071ae9cde86a8e26d3a",
|
||||
"copy_sha256": "669202bb78951419c9a1f61070be5dba7a55d8bfe096a071ae9cde86a8e26d3a",
|
||||
"exact_byte_equality": true,
|
||||
"prompt_file": "prompt-equipment-v1.txt",
|
||||
"prompt_sha256": "3ec33270866c302c452984e3dae48110f2b5438703b90a81dcf27bb3e06f31cb",
|
||||
"gate_lease_id": "c2377ab5-8490-4d0c-8470-8bb44a22ff8f",
|
||||
"gate_outcome": "success",
|
||||
"created_utc": "2026-10-11T08:19:49.376523+00:00"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"tool": "built-in image_gen",
|
||||
"builtin_original_output_path": "/home/quintine/.codex/generated_images/01a129a5-0efd-7c61-8556-922e09c8ea6c/exec-4c2fdbca-d17c-4334-893e-963638433a60.png",
|
||||
"local_raw_copy": "projectile-generated-source-v1.png",
|
||||
"raw_sha256": "0bc76b678c0d2db073ccf76ba2162465b3beb7fd78d505d875c95c594daeb29d",
|
||||
"copy_sha256": "0bc76b678c0d2db073ccf76ba2162465b3beb7fd78d505d875c95c594daeb29d",
|
||||
"exact_byte_equality": true,
|
||||
"prompt_file": "prompt-projectile-v1.txt",
|
||||
"prompt_sha256": "1d314f5a738e58139d69fb67aa372022f32fa40ca32399953a67daf36b58cc46",
|
||||
"gate_lease_id": "aeddcd06-2ad8-4327-b176-13d542e243ec",
|
||||
"gate_outcome": "success",
|
||||
"created_utc": "2026-10-11T08:20:28.206524+00:00"
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 894 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 274 B |
@@ -0,0 +1 @@
|
||||
Use case: stylized-concept. Asset type: a single new HD equipment sprite for the shop/inventory of a Raptor-style military science-fiction vertical shooter. Generate a Depth Charge launcher module: compact dark gunmetal armored double cradle holding two stout gray-blue naval charges side by side, their rounded copper-gray noses pointing exactly UP, two small burnt-orange safety bands and dark aft fins. Squat robust naval ordnance silhouette, readable top-down orthographic overhead view. Muted steel, deep navy-blue enamel, tiny orange safety accents, warm upper-left metal highlights, precise dark recesses. Match chunky industrial1990s military shooter readability with refined HD metal panels and bolts. Logical16x16 and64x64HD. Exactly one complete centered equipment assembly on genuinely transparent square canvas, minimum15percent transparent margin all sides, central65percent occupancy. No ship, water, ground, scenery, text, border, frame, floor, cast shadow, outside glow, separate loose charges or extra objects. Newly authored naval equipment.
|
||||
@@ -0,0 +1 @@
|
||||
Use case: stylized-concept. Asset type: one new transparent naval depth-charge projectile sprite for a Raptor-style military science-fiction vertical shooter. Exactly one stout gray-blue metallic cylindrical charge traveling exactly UP, rounded copper-steel nose at top, a small burnt-orange safety band around the middle, dark navy barrel and three short robust aft stabilizer fins at bottom. Top-down orthographic overhead view; compact straight symmetrical body, width:height about2:3, no perspective or rotation. Logical8x12pixels and32x48HD. Crisp chunky silhouette readable in SD with refined small metal seams forHD, subdued1990s military shooter palette and upper-left lighting. One full object centered on a genuinely transparent square canvas with at least15percent clear margin all sides. No weapon launcher, aircraft, water, floor, smoke, flame, glow, shadow, text, border, frame, debris, additional objects or an explosion. Keep fins short and legible.
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"tool": "original procedural Python synthesis",
|
||||
"recipe": "generate_audio.py",
|
||||
"source_recordings": [],
|
||||
"deterministic_seed": "0xdc042681",
|
||||
"outputs": [
|
||||
{
|
||||
"file": "audio/fire.wav",
|
||||
"sha256": "810ac71ce38d2012b6145baa8cb54f39d8eb4807e6c8b05528ad83d8123ff510",
|
||||
"rate": 22050,
|
||||
"channels": 1,
|
||||
"bits": 16,
|
||||
"frames": 4630,
|
||||
"duration_seconds": 0.20997732426303856,
|
||||
"peak": 15254,
|
||||
"rms": 2870.510735780875,
|
||||
"dc_mean": -13.693304535637148,
|
||||
"clipped_samples": 0
|
||||
},
|
||||
{
|
||||
"file": "audio/impact.wav",
|
||||
"sha256": "aef495acd4c70c4d7dfe0868471a769624e23636659c2580fa867355cffc894a",
|
||||
"rate": 22050,
|
||||
"channels": 1,
|
||||
"bits": 16,
|
||||
"frames": 10143,
|
||||
"duration_seconds": 0.46,
|
||||
"peak": 17180,
|
||||
"rms": 3110.238630183446,
|
||||
"dc_mean": 2.850142955733018,
|
||||
"clipped_samples": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"weapons": [
|
||||
{
|
||||
"id": "iron_coast_depth_charge:projectile",
|
||||
"name": "Depth Charge Projectile",
|
||||
"damage": 72,
|
||||
"speed": 6,
|
||||
"cooldown": 48,
|
||||
"behavior": "straight",
|
||||
"target": "ground",
|
||||
"offsets": [
|
||||
[
|
||||
0,
|
||||
-4
|
||||
]
|
||||
],
|
||||
"art": {
|
||||
"png": "art/projectile-sd.png",
|
||||
"hd_png": "art/projectile-hd.png",
|
||||
"logical_width": 8,
|
||||
"logical_height": 12,
|
||||
"nearest": true
|
||||
},
|
||||
"script": "scripts/weapon.rhai"
|
||||
}
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"id": "iron_coast_depth_charge:equipment",
|
||||
"name": "Depth Charge",
|
||||
"price": 525000,
|
||||
"max_count": 1,
|
||||
"initial_count": 1,
|
||||
"weapon": "iron_coast_depth_charge:projectile",
|
||||
"special": true,
|
||||
"consumable": false,
|
||||
"art": {
|
||||
"png": "art/equipment-sd.png",
|
||||
"hd_png": "art/equipment-hd.png",
|
||||
"logical_width": 16,
|
||||
"logical_height": 16,
|
||||
"nearest": true
|
||||
},
|
||||
"description": "Ground/naval blast, 36px radius. Selectable reusable ground/naval special. Ctrl launches a slow charge; a real ground hit deals 72 damage and splashes at most three other ground enemies within 36 pixels (36 inner / 20 outer). Deliberate 2.06-second cadence; no air damage or ammunition consumed. Alt/Shift selects weapons; Space drops mega bombs."
|
||||
}
|
||||
],
|
||||
"sounds": [
|
||||
{
|
||||
"id": "iron_coast_depth_charge:fire",
|
||||
"name": "Depth Charge Fire",
|
||||
"file": "audio/fire.wav",
|
||||
"volume": 88,
|
||||
"pan": 127,
|
||||
"pitch": 128,
|
||||
"priority": 1
|
||||
},
|
||||
{
|
||||
"id": "iron_coast_depth_charge:impact",
|
||||
"name": "Depth Charge Impact",
|
||||
"file": "audio/impact.wav",
|
||||
"volume": 82,
|
||||
"pan": 127,
|
||||
"pitch": 128,
|
||||
"priority": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Reproduce original deterministic PCM sound effects; no external recordings."""
|
||||
import math, struct, wave, json, hashlib
|
||||
from pathlib import Path
|
||||
PACKAGE = 'iron_coast_depth_charge'
|
||||
RATE = 22050
|
||||
|
||||
def render(kind):
|
||||
rail = PACKAGE.endswith("railburst")
|
||||
duration = (0.16 if kind == "fire" else 0.23) if rail else (0.21 if kind == "fire" else 0.46)
|
||||
count = int(RATE * duration)
|
||||
seed = 0x71AC092D if rail else 0xDC042681
|
||||
phase = 0.0
|
||||
samples = []
|
||||
for n in range(count):
|
||||
t = n / RATE
|
||||
progress = n / count
|
||||
seed ^= (seed << 13) & 0xffffffff
|
||||
seed ^= seed >> 17
|
||||
seed ^= (seed << 5) & 0xffffffff
|
||||
seed &= 0xffffffff
|
||||
noise = seed / 2147483648.0 - 1.0
|
||||
if rail:
|
||||
frequency = (2100 * math.exp(-22*t) + 280) if kind == "fire" else (780 * math.exp(-14*t) + 95)
|
||||
tone = 0.30*math.sin(phase) + 0.18*math.sin(phase*1.993) + noise*(0.44 if kind=="fire" else 0.34)
|
||||
envelope = math.exp(-(32 if kind=="fire" else 19)*t)
|
||||
else:
|
||||
frequency = (175 * math.exp(-10*t) + 65) if kind=="fire" else (98*math.exp(-7*t)+42)
|
||||
tone = math.sin(phase)*0.53 + math.sin(phase*1.47)*0.10 + noise*(0.26 if kind=="fire" else 0.35)*math.exp(-6*t)
|
||||
envelope = math.exp(-(20 if kind=="fire" else 9)*t)
|
||||
phase += 2*math.pi*frequency/RATE
|
||||
attack = min(1.0, n/(RATE*0.002))
|
||||
tail = min(1.0, (count-n)/(RATE*0.015))
|
||||
samples.append(round(max(-1.0,min(1.0,tone*envelope*attack*tail))*22000))
|
||||
return samples
|
||||
|
||||
if __name__ == "__main__":
|
||||
root=Path(__file__).resolve().parent
|
||||
rows=[]
|
||||
for kind in ["fire","impact"]:
|
||||
samples=render(kind)
|
||||
path=root/"audio"/(kind+".wav")
|
||||
with wave.open(str(path),"wb") as output:
|
||||
output.setparams((1,2,RATE,0,"NONE","not compressed"))
|
||||
output.writeframes(struct.pack("<"+"h"*len(samples),*samples))
|
||||
rows.append({"file":str(path.relative_to(root)),"sha256":hashlib.sha256(path.read_bytes()).hexdigest(),"rate":RATE,"channels":1,"bits":16,"frames":len(samples),"duration_seconds":len(samples)/RATE,"peak":max(abs(x) for x in samples),"rms":math.sqrt(sum(x*x for x in samples)/len(samples)),"dc_mean":sum(samples)/len(samples),"clipped_samples":sum(abs(x)>=32767 for x in samples)})
|
||||
(root/"audio"/"provenance.json").write_text(json.dumps({"tool":"original procedural Python synthesis","recipe":"generate_audio.py","source_recordings":[],"deterministic_seed":hex(0x71AC092D if PACKAGE.endswith("railburst") else 0xDC042681),"outputs":rows},indent=2)+"\n")
|
||||
@@ -0,0 +1,7 @@
|
||||
id = "iron_coast_depth_charge"
|
||||
name = "Depth Charge"
|
||||
version = "1.0.0"
|
||||
api_version = 1
|
||||
description = "Independent Iron Coast II selectable upgrade with SD/HD artwork and procedural fire/impact audio."
|
||||
content = "content.json"
|
||||
scripts = ["scripts/weapon.rhai"]
|
||||
@@ -0,0 +1,76 @@
|
||||
const SHOT_W: u32 = 8;
|
||||
const SHOT_H: u32 = 12;
|
||||
// Fit untouched generated masters to shared logical canvases and four-times HD.
|
||||
// Compile with this project's pinned image crate; see README for reproduction.
|
||||
use image::{Rgba, RgbaImage, imageops};
|
||||
use std::{env, fs, path::Path};
|
||||
fn fit(source: &RgbaImage, w: u32, h: u32, scale: u32) -> RgbaImage {
|
||||
let mut bounds = (source.width(), source.height(), 0, 0);
|
||||
for (x, y, p) in source.enumerate_pixels() {
|
||||
if p[3] >= 128 {
|
||||
bounds.0 = bounds.0.min(x);
|
||||
bounds.1 = bounds.1.min(y);
|
||||
bounds.2 = bounds.2.max(x + 1);
|
||||
bounds.3 = bounds.3.max(y + 1);
|
||||
}
|
||||
}
|
||||
assert!(
|
||||
bounds.2 > bounds.0 && bounds.3 > bounds.1,
|
||||
"no meaningful source alpha"
|
||||
);
|
||||
let crop = imageops::crop_imm(
|
||||
source,
|
||||
bounds.0,
|
||||
bounds.1,
|
||||
bounds.2 - bounds.0,
|
||||
bounds.3 - bounds.1,
|
||||
)
|
||||
.to_image();
|
||||
// Exactly one logical pixel of clear margin, shared across SD and HD.
|
||||
let factor = ((w - 2) as f64 / crop.width() as f64).min((h - 2) as f64 / crop.height() as f64);
|
||||
let nw = (crop.width() as f64 * factor).round().max(1.) as u32;
|
||||
let nh = (crop.height() as f64 * factor).round().max(1.) as u32;
|
||||
let filter = if scale == 1 {
|
||||
imageops::FilterType::Triangle
|
||||
} else {
|
||||
imageops::FilterType::Lanczos3
|
||||
};
|
||||
let mut scaled = imageops::resize(&crop, nw * scale, nh * scale, filter);
|
||||
for p in scaled.pixels_mut() {
|
||||
if p[3] < 128 {
|
||||
*p = Rgba([0, 0, 0, 0]);
|
||||
} else {
|
||||
p[3] = 255;
|
||||
}
|
||||
}
|
||||
let mut out = RgbaImage::new(w * scale, h * scale);
|
||||
imageops::overlay(
|
||||
&mut out,
|
||||
&scaled,
|
||||
((w * scale - nw * scale) / 2) as i64,
|
||||
((h * scale - nh * scale) / 2) as i64,
|
||||
);
|
||||
out
|
||||
}
|
||||
fn main() {
|
||||
let args: Vec<_> = env::args().collect();
|
||||
assert_eq!(args.len(), 2, "usage: prepare_art PACKAGE_DIRECTORY");
|
||||
let root = Path::new(&args[1]);
|
||||
for (kind, w, h) in [("equipment", 16, 16), ("projectile", SHOT_W, SHOT_H)] {
|
||||
let source = image::open(root.join(format!("art/{kind}-generated-source-v1.png")))
|
||||
.unwrap()
|
||||
.into_rgba8();
|
||||
for (mode, scale) in [("sd", 1), ("hd", 4)] {
|
||||
let image = fit(&source, w, h, scale);
|
||||
let path = root.join(format!("art/{kind}-{mode}.png"));
|
||||
image.save(&path).unwrap();
|
||||
println!("{} {}x{}", path.display(), image.width(), image.height());
|
||||
}
|
||||
}
|
||||
assert!(
|
||||
fs::metadata(root.join("art/equipment-hd.png"))
|
||||
.unwrap()
|
||||
.len()
|
||||
> 0
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"use_case": "stylized-concept",
|
||||
"tool": "built-in image_gen",
|
||||
"skill": "/home/quintine/.codex/skills/.system/imagegen/SKILL.md",
|
||||
"style_reference_ids": [
|
||||
"102b6",
|
||||
"101cb"
|
||||
],
|
||||
"reference_role": "Original catalog was inspected for classic palette, silhouette and scale; no decoded reference is included in this mod. New generation uses the prepared textual art direction.",
|
||||
"prompts": {
|
||||
"equipment": "Use case: stylized-concept. Asset type: a single new HD equipment sprite for the shop/inventory of a Raptor-style military science-fiction vertical shooter. Generate a Depth Charge launcher module: compact dark gunmetal armored double cradle holding two stout gray-blue naval charges side by side, their rounded copper-gray noses pointing exactly UP, two small burnt-orange safety bands and dark aft fins. Squat robust naval ordnance silhouette, readable top-down orthographic overhead view. Muted steel, deep navy-blue enamel, tiny orange safety accents, warm upper-left metal highlights, precise dark recesses. Match chunky industrial1990s military shooter readability with refined HD metal panels and bolts. Logical16x16 and64x64HD. Exactly one complete centered equipment assembly on genuinely transparent square canvas, minimum15percent transparent margin all sides, central65percent occupancy. No ship, water, ground, scenery, text, border, frame, floor, cast shadow, outside glow, separate loose charges or extra objects. Newly authored naval equipment.",
|
||||
"projectile": "Use case: stylized-concept. Asset type: one new transparent naval depth-charge projectile sprite for a Raptor-style military science-fiction vertical shooter. Exactly one stout gray-blue metallic cylindrical charge traveling exactly UP, rounded copper-steel nose at top, a small burnt-orange safety band around the middle, dark navy barrel and three short robust aft stabilizer fins at bottom. Top-down orthographic overhead view; compact straight symmetrical body, width:height about2:3, no perspective or rotation. Logical8x12pixels and32x48HD. Crisp chunky silhouette readable in SD with refined small metal seams forHD, subdued1990s military shooter palette and upper-left lighting. One full object centered on a genuinely transparent square canvas with at least15percent clear margin all sides. No weapon launcher, aircraft, water, floor, smoke, flame, glow, shadow, text, border, frame, debris, additional objects or an explosion. Keep fins short and legible."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Damage is collision-triggered. Empty space, aircraft and inactive equipment
|
||||
// never start a blast. Native targeting handles the primary ground collision.
|
||||
fn on_fire(event, state, random) {
|
||||
if event.hostile { return #{commands: [], state: state}; }
|
||||
let shots = if state.contains("shots") { state.shots % 100000 + 1 } else { 1 };
|
||||
let hits = if state.contains("hits") { state.hits } else { 0 };
|
||||
#{commands: [#{op: "play_sound", sound: "iron_coast_depth_charge:fire"}],
|
||||
state: #{shots: shots, hits: hits}}
|
||||
}
|
||||
|
||||
fn on_hit(event, state, random) {
|
||||
let shots = if state.contains("shots") { state.shots } else { 0 };
|
||||
let hits = if state.contains("hits") { state.hits % 100000 + 1 } else { 1 };
|
||||
let center_x = event.x;
|
||||
let center_y = event.y;
|
||||
for enemy in event.entities {
|
||||
if enemy.entity == event.entity {
|
||||
center_x = enemy.x + enemy.width / 2;
|
||||
center_y = enemy.y + enemy.height / 2;
|
||||
}
|
||||
}
|
||||
let commands = [#{op: "play_sound", sound: "iron_coast_depth_charge:impact"},
|
||||
#{op: "effect", kind: "ground_blast", x: center_x, y: center_y}];
|
||||
let struck = [event.entity];
|
||||
for neighbor in 0..3 {
|
||||
let chosen = #{};
|
||||
let nearest = 1000000;
|
||||
for enemy in event.entities {
|
||||
let cx = enemy.x + enemy.width / 2;
|
||||
let cy = enemy.y + enemy.height / 2;
|
||||
if !enemy.ground || enemy.health <= 0 || struck.contains(enemy.entity)
|
||||
|| cx < 0 || cx >= 320 || cy < 0 || cy >= 200 { continue; }
|
||||
let dx = cx - center_x;
|
||||
let dy = cy - center_y;
|
||||
let distance = dx * dx + dy * dy;
|
||||
if distance <= 36 * 36 && distance < nearest {
|
||||
chosen = #{entity: enemy.entity};
|
||||
nearest = distance;
|
||||
}
|
||||
}
|
||||
if !chosen.contains("entity") { break; }
|
||||
let damage = if nearest <= 16 * 16 { 36 } else { 20 };
|
||||
commands.push(#{op: "damage", entity: chosen.entity, amount: damage});
|
||||
struck.push(chosen.entity);
|
||||
hits = hits % 100000 + 1;
|
||||
}
|
||||
#{commands: commands, state: #{shots: shots, hits: hits}}
|
||||
}
|
||||
@@ -0,0 +1,901 @@
|
||||
{
|
||||
"difficulty": 2,
|
||||
"fixture_health": 100000,
|
||||
"rate": "70/3 Hz",
|
||||
"rows": [
|
||||
{
|
||||
"damage": [
|
||||
1344
|
||||
],
|
||||
"group_dps": 44.8,
|
||||
"item": "iron_coast_railburst:equipment",
|
||||
"price": 685000,
|
||||
"scene": "aligned_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1344
|
||||
],
|
||||
"group_dps": 44.8,
|
||||
"item": "iron_coast_railburst:equipment",
|
||||
"price": 685000,
|
||||
"scene": "aligned_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "iron_coast_railburst:equipment",
|
||||
"price": 685000,
|
||||
"scene": "off_axis_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "iron_coast_railburst:equipment",
|
||||
"price": 685000,
|
||||
"scene": "off_axis_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1344,
|
||||
1024,
|
||||
704,
|
||||
0
|
||||
],
|
||||
"group_dps": 102.4,
|
||||
"item": "iron_coast_railburst:equipment",
|
||||
"price": 685000,
|
||||
"scene": "aligned_column",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1344,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"group_dps": 44.8,
|
||||
"item": "iron_coast_railburst:equipment",
|
||||
"price": 685000,
|
||||
"scene": "ground_cluster",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
2038
|
||||
],
|
||||
"group_dps": 67.93333333333334,
|
||||
"item": "iron_coast_railburst:equipment",
|
||||
"price": 685000,
|
||||
"scene": "aligned_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
2038
|
||||
],
|
||||
"group_dps": 67.93333333333334,
|
||||
"item": "iron_coast_railburst:equipment",
|
||||
"price": 685000,
|
||||
"scene": "aligned_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "iron_coast_railburst:equipment",
|
||||
"price": 685000,
|
||||
"scene": "off_axis_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "iron_coast_railburst:equipment",
|
||||
"price": 685000,
|
||||
"scene": "off_axis_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
2040,
|
||||
1024,
|
||||
704,
|
||||
0
|
||||
],
|
||||
"group_dps": 125.6,
|
||||
"item": "iron_coast_railburst:equipment",
|
||||
"price": 685000,
|
||||
"scene": "aligned_column",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
2038,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"group_dps": 67.93333333333334,
|
||||
"item": "iron_coast_railburst:equipment",
|
||||
"price": 685000,
|
||||
"scene": "ground_cluster",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "iron_coast_depth_charge:equipment",
|
||||
"price": 525000,
|
||||
"scene": "aligned_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1080
|
||||
],
|
||||
"group_dps": 36.0,
|
||||
"item": "iron_coast_depth_charge:equipment",
|
||||
"price": 525000,
|
||||
"scene": "aligned_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "iron_coast_depth_charge:equipment",
|
||||
"price": 525000,
|
||||
"scene": "off_axis_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "iron_coast_depth_charge:equipment",
|
||||
"price": 525000,
|
||||
"scene": "off_axis_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1080,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"group_dps": 36.0,
|
||||
"item": "iron_coast_depth_charge:equipment",
|
||||
"price": 525000,
|
||||
"scene": "aligned_column",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1080,
|
||||
540,
|
||||
300,
|
||||
300,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"group_dps": 74.0,
|
||||
"item": "iron_coast_depth_charge:equipment",
|
||||
"price": 525000,
|
||||
"scene": "ground_cluster",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
694
|
||||
],
|
||||
"group_dps": 23.133333333333333,
|
||||
"item": "iron_coast_depth_charge:equipment",
|
||||
"price": 525000,
|
||||
"scene": "aligned_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1774
|
||||
],
|
||||
"group_dps": 59.13333333333333,
|
||||
"item": "iron_coast_depth_charge:equipment",
|
||||
"price": 525000,
|
||||
"scene": "aligned_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "iron_coast_depth_charge:equipment",
|
||||
"price": 525000,
|
||||
"scene": "off_axis_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "iron_coast_depth_charge:equipment",
|
||||
"price": 525000,
|
||||
"scene": "off_axis_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1776,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"group_dps": 59.2,
|
||||
"item": "iron_coast_depth_charge:equipment",
|
||||
"price": 525000,
|
||||
"scene": "aligned_column",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1774,
|
||||
540,
|
||||
300,
|
||||
300,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"group_dps": 97.13333333333334,
|
||||
"item": "iron_coast_depth_charge:equipment",
|
||||
"price": 525000,
|
||||
"scene": "ground_cluster",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
800
|
||||
],
|
||||
"group_dps": 26.666666666666668,
|
||||
"item": "ion_lance:equipment",
|
||||
"price": 425000,
|
||||
"scene": "aligned_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
800
|
||||
],
|
||||
"group_dps": 26.666666666666668,
|
||||
"item": "ion_lance:equipment",
|
||||
"price": 425000,
|
||||
"scene": "aligned_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "ion_lance:equipment",
|
||||
"price": 425000,
|
||||
"scene": "off_axis_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "ion_lance:equipment",
|
||||
"price": 425000,
|
||||
"scene": "off_axis_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
800,
|
||||
800,
|
||||
800,
|
||||
800
|
||||
],
|
||||
"group_dps": 106.66666666666667,
|
||||
"item": "ion_lance:equipment",
|
||||
"price": 425000,
|
||||
"scene": "aligned_column",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
800,
|
||||
800,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
800
|
||||
],
|
||||
"group_dps": 80.0,
|
||||
"item": "ion_lance:equipment",
|
||||
"price": 425000,
|
||||
"scene": "ground_cluster",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1494
|
||||
],
|
||||
"group_dps": 49.8,
|
||||
"item": "ion_lance:equipment",
|
||||
"price": 425000,
|
||||
"scene": "aligned_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1494
|
||||
],
|
||||
"group_dps": 49.8,
|
||||
"item": "ion_lance:equipment",
|
||||
"price": 425000,
|
||||
"scene": "aligned_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "ion_lance:equipment",
|
||||
"price": 425000,
|
||||
"scene": "off_axis_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "ion_lance:equipment",
|
||||
"price": 425000,
|
||||
"scene": "off_axis_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1496,
|
||||
800,
|
||||
800,
|
||||
800
|
||||
],
|
||||
"group_dps": 129.86666666666667,
|
||||
"item": "ion_lance:equipment",
|
||||
"price": 425000,
|
||||
"scene": "aligned_column",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1494,
|
||||
800,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
800
|
||||
],
|
||||
"group_dps": 103.13333333333334,
|
||||
"item": "ion_lance:equipment",
|
||||
"price": 425000,
|
||||
"scene": "ground_cluster",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1248
|
||||
],
|
||||
"group_dps": 41.6,
|
||||
"item": "lightning_cannon:equipment",
|
||||
"price": 825000,
|
||||
"scene": "aligned_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1248
|
||||
],
|
||||
"group_dps": 41.6,
|
||||
"item": "lightning_cannon:equipment",
|
||||
"price": 825000,
|
||||
"scene": "aligned_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "lightning_cannon:equipment",
|
||||
"price": 825000,
|
||||
"scene": "off_axis_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "lightning_cannon:equipment",
|
||||
"price": 825000,
|
||||
"scene": "off_axis_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1248,
|
||||
780,
|
||||
468,
|
||||
312
|
||||
],
|
||||
"group_dps": 93.6,
|
||||
"item": "lightning_cannon:equipment",
|
||||
"price": 825000,
|
||||
"scene": "aligned_column",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1248,
|
||||
468,
|
||||
312,
|
||||
0,
|
||||
0,
|
||||
780
|
||||
],
|
||||
"group_dps": 93.6,
|
||||
"item": "lightning_cannon:equipment",
|
||||
"price": 825000,
|
||||
"scene": "ground_cluster",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1942
|
||||
],
|
||||
"group_dps": 64.73333333333333,
|
||||
"item": "lightning_cannon:equipment",
|
||||
"price": 825000,
|
||||
"scene": "aligned_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1942
|
||||
],
|
||||
"group_dps": 64.73333333333333,
|
||||
"item": "lightning_cannon:equipment",
|
||||
"price": 825000,
|
||||
"scene": "aligned_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "lightning_cannon:equipment",
|
||||
"price": 825000,
|
||||
"scene": "off_axis_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "lightning_cannon:equipment",
|
||||
"price": 825000,
|
||||
"scene": "off_axis_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1944,
|
||||
780,
|
||||
468,
|
||||
312
|
||||
],
|
||||
"group_dps": 116.8,
|
||||
"item": "lightning_cannon:equipment",
|
||||
"price": 825000,
|
||||
"scene": "aligned_column",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
1942,
|
||||
468,
|
||||
312,
|
||||
0,
|
||||
0,
|
||||
780
|
||||
],
|
||||
"group_dps": 116.73333333333333,
|
||||
"item": "lightning_cannon:equipment",
|
||||
"price": 825000,
|
||||
"scene": "ground_cluster",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": true
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
694
|
||||
],
|
||||
"group_dps": 23.133333333333333,
|
||||
"item": "base:forward_guns",
|
||||
"price": 12000,
|
||||
"scene": "aligned_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
694
|
||||
],
|
||||
"group_dps": 23.133333333333333,
|
||||
"item": "base:forward_guns",
|
||||
"price": 12000,
|
||||
"scene": "aligned_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "base:forward_guns",
|
||||
"price": 12000,
|
||||
"scene": "off_axis_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "base:forward_guns",
|
||||
"price": 12000,
|
||||
"scene": "off_axis_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
696,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"group_dps": 23.2,
|
||||
"item": "base:forward_guns",
|
||||
"price": 12000,
|
||||
"scene": "aligned_column",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
694,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"group_dps": 23.133333333333333,
|
||||
"item": "base:forward_guns",
|
||||
"price": 12000,
|
||||
"scene": "ground_cluster",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
2400
|
||||
],
|
||||
"group_dps": 80.0,
|
||||
"item": "base:death_ray",
|
||||
"price": 950000,
|
||||
"scene": "aligned_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
2400
|
||||
],
|
||||
"group_dps": 80.0,
|
||||
"item": "base:death_ray",
|
||||
"price": 950000,
|
||||
"scene": "aligned_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "base:death_ray",
|
||||
"price": 950000,
|
||||
"scene": "off_axis_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "base:death_ray",
|
||||
"price": 950000,
|
||||
"scene": "off_axis_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
2400,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"group_dps": 80.0,
|
||||
"item": "base:death_ray",
|
||||
"price": 950000,
|
||||
"scene": "aligned_column",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
2400,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"group_dps": 80.0,
|
||||
"item": "base:death_ray",
|
||||
"price": 950000,
|
||||
"scene": "ground_cluster",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
8000
|
||||
],
|
||||
"group_dps": 266.6666666666667,
|
||||
"item": "base:forward_laser",
|
||||
"price": 1750000,
|
||||
"scene": "aligned_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
8000
|
||||
],
|
||||
"group_dps": 266.6666666666667,
|
||||
"item": "base:forward_laser",
|
||||
"price": 1750000,
|
||||
"scene": "aligned_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "base:forward_laser",
|
||||
"price": 1750000,
|
||||
"scene": "off_axis_air",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
0
|
||||
],
|
||||
"group_dps": 0.0,
|
||||
"item": "base:forward_laser",
|
||||
"price": 1750000,
|
||||
"scene": "off_axis_ground",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
8000,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"group_dps": 266.6666666666667,
|
||||
"item": "base:forward_laser",
|
||||
"price": 1750000,
|
||||
"scene": "aligned_column",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
},
|
||||
{
|
||||
"damage": [
|
||||
8000,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"group_dps": 266.6666666666667,
|
||||
"item": "base:forward_laser",
|
||||
"price": 1750000,
|
||||
"scene": "ground_cluster",
|
||||
"seconds": 30,
|
||||
"ticks": 700,
|
||||
"with_forward_guns": false
|
||||
}
|
||||
],
|
||||
"target_size": [
|
||||
32,
|
||||
32
|
||||
],
|
||||
"package": "iron_coast_depth_charge",
|
||||
"final_price": 525000,
|
||||
"resale_price": 262500,
|
||||
"pricing_reason": "36 ground single-target DPS and74 finite mixed-cluster ground DPS, zero air/off-axis damage, 48-tick slow cadence. Above425,000 Ion Lance26.67 single and285,000 Seeker Swarm23.4 single for local ground utility, but slower and ground-only. Below825,000 Lightning Cannon41.6 air/ground single and93.6 chain,950,000 Death Ray80 single,1,750,000 Forward Laser266.67. Forward guns add normal primary damage, not unbounded splash.",
|
||||
"observation": "Actual World::step700ticks; deterministic stationary32x32 health100000 fixtures, ground scroll canceled after normal collision pass. Native original and new weapons unmodified. Forward-gun combination separately observed. Does not measure campaign difficulty or moving-target accuracy.",
|
||||
"source_input_hashes": {
|
||||
"mod.toml": "b0acc9149813522720ca6fc1e246a5a383e8641c89f7623558a6a5baa0e2d892",
|
||||
"content.json": "1806d8451b6734096609c2188e42e002de9c82d7ac19361f51a329fe066ca07e",
|
||||
"scripts/weapon.rhai": "23eb0d61ce768e6d8392b394c9274deee7ac5624915c4d3bae40e2050fef4d66"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
{
|
||||
"package": "iron_coast_depth_charge",
|
||||
"portable_tests": {
|
||||
"file": "tests/iron_coast_stage2_weapons.rs",
|
||||
"passed": 9,
|
||||
"balance_integration_passed": 1,
|
||||
"cases": [
|
||||
"independent activation and coexistence",
|
||||
"shop half-price resale and duplicate rejection",
|
||||
"rail aligned contact finite penetration",
|
||||
"depth contact-only ground radius/falloff/cap",
|
||||
"unselected/idle/misses without explosions",
|
||||
"serialized state/RNG continuation and invalid-command rollback",
|
||||
"explicit cooldown/reusable inventory",
|
||||
"lethal primary contact continuation",
|
||||
"full-slot inventory preservation",
|
||||
"disable/re-enable saved equipment, exact mod pins and script state preserved without altering save"
|
||||
]
|
||||
},
|
||||
"native_decoder_blitter_audio": {
|
||||
"assets": [
|
||||
{
|
||||
"all_scales": [
|
||||
{
|
||||
"height": 16,
|
||||
"painted": 147,
|
||||
"scale": 1,
|
||||
"width": 16
|
||||
},
|
||||
{
|
||||
"height": 32,
|
||||
"painted": 588,
|
||||
"scale": 2,
|
||||
"width": 32
|
||||
},
|
||||
{
|
||||
"height": 48,
|
||||
"painted": 1323,
|
||||
"scale": 3,
|
||||
"width": 48
|
||||
},
|
||||
{
|
||||
"height": 64,
|
||||
"painted": 2352,
|
||||
"scale": 4,
|
||||
"width": 64
|
||||
}
|
||||
],
|
||||
"clear_corner_alpha": true,
|
||||
"frame": 0,
|
||||
"frames": 1,
|
||||
"hd": false,
|
||||
"kind": "equipment",
|
||||
"logical_canvas": [
|
||||
16,
|
||||
16
|
||||
],
|
||||
"ordinary_palette_only": true,
|
||||
"owner": "iron_coast_depth_charge",
|
||||
"physical_canvas": [
|
||||
16,
|
||||
16
|
||||
]
|
||||
},
|
||||
{
|
||||
"all_scales": [
|
||||
{
|
||||
"height": 16,
|
||||
"painted": 141,
|
||||
"scale": 1,
|
||||
"width": 16
|
||||
},
|
||||
{
|
||||
"height": 32,
|
||||
"painted": 561,
|
||||
"scale": 2,
|
||||
"width": 32
|
||||
},
|
||||
{
|
||||
"height": 48,
|
||||
"painted": 1252,
|
||||
"scale": 3,
|
||||
"width": 48
|
||||
},
|
||||
{
|
||||
"height": 64,
|
||||
"painted": 2236,
|
||||
"scale": 4,
|
||||
"width": 64
|
||||
}
|
||||
],
|
||||
"clear_corner_alpha": true,
|
||||
"frame": 0,
|
||||
"frames": 1,
|
||||
"hd": true,
|
||||
"kind": "equipment",
|
||||
"logical_canvas": [
|
||||
16,
|
||||
16
|
||||
],
|
||||
"ordinary_palette_only": true,
|
||||
"owner": "iron_coast_depth_charge",
|
||||
"physical_canvas": [
|
||||
64,
|
||||
64
|
||||
]
|
||||
},
|
||||
{
|
||||
"all_scales": [
|
||||
{
|
||||
"height": 12,
|
||||
"painted": 34,
|
||||
"scale": 1,
|
||||
"width": 8
|
||||
},
|
||||
{
|
||||
"height": 24,
|
||||
"painted": 136,
|
||||
"scale": 2,
|
||||
"width": 16
|
||||
},
|
||||
{
|
||||
"height": 36,
|
||||
"painted": 306,
|
||||
"scale": 3,
|
||||
"width": 24
|
||||
},
|
||||
{
|
||||
"height": 48,
|
||||
"painted": 544,
|
||||
"scale": 4,
|
||||
"width": 32
|
||||
}
|
||||
],
|
||||
"clear_corner_alpha": true,
|
||||
"frame": 0,
|
||||
"frames": 1,
|
||||
"hd": false,
|
||||
"kind": "projectile",
|
||||
"logical_canvas": [
|
||||
8,
|
||||
12
|
||||
],
|
||||
"ordinary_palette_only": true,
|
||||
"owner": "iron_coast_depth_charge",
|
||||
"physical_canvas": [
|
||||
8,
|
||||
12
|
||||
]
|
||||
},
|
||||
{
|
||||
"all_scales": [
|
||||
{
|
||||
"height": 12,
|
||||
"painted": 28,
|
||||
"scale": 1,
|
||||
"width": 8
|
||||
},
|
||||
{
|
||||
"height": 24,
|
||||
"painted": 110,
|
||||
"scale": 2,
|
||||
"width": 16
|
||||
},
|
||||
{
|
||||
"height": 36,
|
||||
"painted": 248,
|
||||
"scale": 3,
|
||||
"width": 24
|
||||
},
|
||||
{
|
||||
"height": 48,
|
||||
"painted": 444,
|
||||
"scale": 4,
|
||||
"width": 32
|
||||
}
|
||||
],
|
||||
"clear_corner_alpha": true,
|
||||
"frame": 0,
|
||||
"frames": 1,
|
||||
"hd": true,
|
||||
"kind": "projectile",
|
||||
"logical_canvas": [
|
||||
8,
|
||||
12
|
||||
],
|
||||
"ordinary_palette_only": true,
|
||||
"owner": "iron_coast_depth_charge",
|
||||
"physical_canvas": [
|
||||
32,
|
||||
48
|
||||
]
|
||||
}
|
||||
],
|
||||
"audio": [
|
||||
{
|
||||
"capture": "iron_coast_depth_charge-fire-mixed.wav",
|
||||
"decoded_samples": 4630,
|
||||
"decoder": "SoundBank::mod_sample",
|
||||
"id": "iron_coast_depth_charge:fire",
|
||||
"mixed_channels": 2,
|
||||
"mixed_rate": 44100,
|
||||
"mixer": "Mixer::sample through SoundBank::queue_mod",
|
||||
"nonzero_output_samples": 11448,
|
||||
"peak": 2688,
|
||||
"source_rate": 22050
|
||||
},
|
||||
{
|
||||
"capture": "iron_coast_depth_charge-impact-mixed.wav",
|
||||
"decoded_samples": 10143,
|
||||
"decoder": "SoundBank::mod_sample",
|
||||
"id": "iron_coast_depth_charge:impact",
|
||||
"mixed_channels": 2,
|
||||
"mixed_rate": 44100,
|
||||
"mixer": "Mixer::sample through SoundBank::queue_mod",
|
||||
"nonzero_output_samples": 27200,
|
||||
"peak": 3200,
|
||||
"source_rate": 22050
|
||||
}
|
||||
],
|
||||
"scope": "Public PNG decoder, same Host art normalization, indexed Canvas blitter and actual SoundBank/Mixer. Synthetic backgrounds; no live desktop/gameplay claim."
|
||||
},
|
||||
"visual_inspection": "Inspected original style references separately, all four raw masters and actual indexed SD/HD gallery at logical and4x canvases. Readable compact silhouettes, neutral metal with cyan rail/orange charge roles, transparent borders. SD colors intentionally simplified by reduction; no reserved palette effects. Captures use synthetic palette backgrounds, not a live mission or actual shop pane.",
|
||||
"limitations": [
|
||||
"Private desktop Host/shop screenshots are delegated to root integration review.",
|
||||
"Native point collision may skip exceptionally tiny targets for the speed16 rail shot.",
|
||||
"Terrain cells receive native primary damage but are not available as scripted penetration/splash snapshots."
|
||||
],
|
||||
"evidence_gallery_sha256": "c1b5d6ad1d286eb17fab1067143222a6071dff5e70a35d904757275767ec5a26",
|
||||
"reproduction_byte_equality": {
|
||||
"art/equipment-sd.png": true,
|
||||
"art/equipment-hd.png": true,
|
||||
"art/projectile-sd.png": true,
|
||||
"art/projectile-hd.png": true,
|
||||
"audio/fire.wav": true,
|
||||
"audio/impact.wav": true
|
||||
},
|
||||
"native_build_bindings": {
|
||||
"libraries": {
|
||||
"raptor_replica": {
|
||||
"path": "/home/quintine/Projects/RaptorReplica/RustRaptor/target/debug/libraptor_replica.rlib",
|
||||
"sha256": "4fd737d3c6c808fd5de1ecfc1f9a41b0ef37e82dc1a186f005b8dc9c2360ccd5"
|
||||
},
|
||||
"image": {
|
||||
"path": "/home/quintine/Projects/RaptorReplica/RustRaptor/target/debug/deps/libimage-25e356663b4aa6b0.rlib",
|
||||
"sha256": "ea709066ea4c8c625efe3bf7f3741d7a68abfb7ef4b304837f1f0da20e5e2d58"
|
||||
},
|
||||
"serde_json": {
|
||||
"path": "/home/quintine/Projects/RaptorReplica/RustRaptor/target/debug/deps/libserde_json-1d17875658175ae0.rlib",
|
||||
"sha256": "e463d4b704418cc5a168d73818662f7a801a77d96e8ef3d6a121e90375e4532f"
|
||||
}
|
||||
},
|
||||
"review_source_sha256": "32c4e836b7a01d159251427b2203dcf0d40f43bebef1def2f13a571e845d8ca3",
|
||||
"validation_cases": [
|
||||
{
|
||||
"enabled": [
|
||||
"iron_coast_railburst"
|
||||
],
|
||||
"stdout": "Validated 1 mods; 0 override(s)",
|
||||
"stderr": "",
|
||||
"exit_code": 0
|
||||
},
|
||||
{
|
||||
"enabled": [
|
||||
"iron_coast_depth_charge"
|
||||
],
|
||||
"stdout": "Validated 1 mods; 0 override(s)",
|
||||
"stderr": "",
|
||||
"exit_code": 0
|
||||
},
|
||||
{
|
||||
"enabled": [
|
||||
"iron_coast_railburst",
|
||||
"iron_coast_depth_charge"
|
||||
],
|
||||
"stdout": "Validated 2 mods; 0 override(s)",
|
||||
"stderr": "",
|
||||
"exit_code": 0
|
||||
}
|
||||
],
|
||||
"scope": "Frozen package copies; public asset, indexed Canvas and audio APIs; no live desktop or pilot mutations."
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user