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,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_railburst",
|
||||
"final_price": 685000,
|
||||
"resale_price": 342500,
|
||||
"pricing_reason": "44.8 single air/ground DPS and102.4 finite three-target aligned-column DPS, zero off-axis damage. Higher single-target throughput than425,000 Ion Lance26.67, but tighter initial acquisition and finite penetration compared with825,000 Lightning Cannon41.6 single/93.6 chain and wider acquisition. Below950,000 Death Ray80 single and1,750,000 Forward Laser266.67. Ion Lance can exceed this finite penetration against four or more perfectly stacked targets; this is a different aiming/cadence choice, not an upgrade over every role.",
|
||||
"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": "e22f6dd8e8aaeb7fe1549cdddc2be28fcda71a16f9285c975701e77a009faf84",
|
||||
"content.json": "de70d59f723cce78ca4b59a3ecce704ce877517d91d83a06526daed7f42d4484",
|
||||
"scripts/weapon.rhai": "209ae40d88b03bda4802c1970852d791f84b48986990d70c0e3dbcf502ba5b9b"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
//! Read-only public engine asset/audio review for both independent Stage 2 mods.
|
||||
//! Writes captures only to the caller's evidence directory, never to game data.
|
||||
use image::{RgbaImage, imageops};
|
||||
use raptor_replica::{
|
||||
assets::{Catalog, Sprite, TRANSPARENT},
|
||||
audio::Mixer,
|
||||
content::{ContentId, Registry, art_sprite_variant},
|
||||
modding::{self, ActiveMods},
|
||||
render::{Canvas, nearest},
|
||||
sound::{SoundBank, encode_capture},
|
||||
};
|
||||
use serde_json::json;
|
||||
use std::{env, fs, path::Path};
|
||||
fn normalized(sprite: &Sprite, w: usize, h: usize) -> Sprite {
|
||||
let mut out = Sprite::blank(w, h);
|
||||
for y in 0..h {
|
||||
for x in 0..w {
|
||||
out.pixels[y * w + x] =
|
||||
sprite.pixels[(y * sprite.height / h) * sprite.width + x * sprite.width / w];
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
fn main() {
|
||||
let args: Vec<_> = env::args().collect();
|
||||
assert_eq!(args.len(), 4, "usage: native_review DATA MODS EVIDENCE");
|
||||
let catalog = Catalog::open(&args[1]).unwrap();
|
||||
let base = Registry::base(&catalog).unwrap();
|
||||
let ids = ["iron_coast_railburst", "iron_coast_depth_charge"].map(String::from);
|
||||
let discovery = modding::discover(Path::new(&args[2]));
|
||||
let active = ActiveMods::build(&base, &discovery, &ids, Some(&catalog)).unwrap();
|
||||
let out = Path::new(&args[3]);
|
||||
fs::create_dir_all(out).unwrap();
|
||||
let palette = catalog.palette().unwrap();
|
||||
let mut rows = Vec::new();
|
||||
let mut gallery = RgbaImage::new(1024, 1024);
|
||||
let mut row = 0;
|
||||
for owner in &ids {
|
||||
for kind in ["equipment", "projectile"] {
|
||||
let id: ContentId = format!(
|
||||
"{owner}:{}",
|
||||
if kind == "equipment" {
|
||||
"equipment"
|
||||
} else {
|
||||
"projectile"
|
||||
}
|
||||
)
|
||||
.as_str()
|
||||
.into();
|
||||
let art = active.registry.art(&id).unwrap();
|
||||
for hd in [false, true] {
|
||||
let source =
|
||||
art_sprite_variant(&catalog, &active.registry, owner, art, 0, hd).unwrap();
|
||||
assert!(
|
||||
source
|
||||
.pixels
|
||||
.iter()
|
||||
.filter(|c| **c != TRANSPARENT)
|
||||
.all(|c| *c < 240)
|
||||
);
|
||||
assert!(
|
||||
source.pixels[0] == TRANSPARENT
|
||||
&& source.pixels[source.width - 1] == TRANSPARENT
|
||||
);
|
||||
let mut counts = Vec::new();
|
||||
for scale in 1..=4 {
|
||||
// The same canvas sizing and nearest resampling used by Host::art.
|
||||
let display = if source.width == art.logical_width as usize
|
||||
&& source.height == art.logical_height as usize
|
||||
{
|
||||
nearest(&source, scale)
|
||||
} else {
|
||||
normalized(
|
||||
&source,
|
||||
art.logical_width as usize * scale,
|
||||
art.logical_height as usize * scale,
|
||||
)
|
||||
};
|
||||
counts.push(json!({"scale":scale,"width":display.width,"height":display.height,"painted":display.pixels.iter().filter(|c|**c!=TRANSPARENT).count()}));
|
||||
let mut canvas = Canvas::new(scale);
|
||||
canvas.clear(12);
|
||||
canvas.rect(160, 0, 160, 200, 93);
|
||||
for (x, y) in [(70, 90), (230, 90)] {
|
||||
canvas.blit(&display, x * scale as i32, y * scale as i32);
|
||||
}
|
||||
let rgba = RgbaImage::from_raw(
|
||||
canvas.image.width as u32,
|
||||
canvas.image.height as u32,
|
||||
canvas.rgba(&palette, false),
|
||||
)
|
||||
.unwrap();
|
||||
rgba.save(out.join(format!(
|
||||
"{owner}-{kind}-{}-{scale}x.png",
|
||||
if hd { "hd" } else { "sd" }
|
||||
)))
|
||||
.unwrap();
|
||||
}
|
||||
let display = normalized(
|
||||
&source,
|
||||
art.logical_width as usize * 8,
|
||||
art.logical_height as usize * 8,
|
||||
);
|
||||
let mut cell = Canvas::new(1);
|
||||
cell.clear(12);
|
||||
cell.rect(160, 0, 160, 200, 93);
|
||||
cell.blit(&display, 20, 20);
|
||||
cell.blit(&display, 180, 20);
|
||||
let rgba = RgbaImage::from_raw(320, 200, cell.rgba(&palette, false)).unwrap();
|
||||
imageops::overlay(
|
||||
&mut gallery,
|
||||
&rgba,
|
||||
if hd { 512 } else { 0 },
|
||||
(row * 256) as i64,
|
||||
);
|
||||
rows.push(json!({"owner":owner,"kind":kind,"hd":hd,"physical_canvas":[source.width,source.height],"logical_canvas":[art.logical_width,art.logical_height],"frame":0,"frames":art.frames,"ordinary_palette_only":true,"clear_corner_alpha":true,"all_scales":counts}));
|
||||
}
|
||||
row += 1;
|
||||
}
|
||||
}
|
||||
gallery.save(out.join("indexed-sd-hd-gallery.png")).unwrap();
|
||||
let instruments = catalog.named("GENMIDI_OP2").unwrap();
|
||||
let mut audio = Vec::new();
|
||||
for owner in &ids {
|
||||
for kind in ["fire", "impact"] {
|
||||
let id: ContentId = format!("{owner}:{kind}").as_str().into();
|
||||
let mut bank = SoundBank::default();
|
||||
let sample = bank.mod_sample(&active.registry, &id).unwrap();
|
||||
assert!(!sample.data.is_empty());
|
||||
let mut mixer = Mixer::new(44100, &instruments).unwrap();
|
||||
mixer.start_capture(1).unwrap();
|
||||
bank.queue_mod(&active.registry, &mut mixer, &id).unwrap();
|
||||
let mut samples = vec![0; 44100 * 2];
|
||||
mixer.mix(&mut samples);
|
||||
assert!(samples.iter().any(|x| *x != 0));
|
||||
let file = format!("{owner}-{kind}-mixed.wav");
|
||||
fs::write(
|
||||
out.join(&file),
|
||||
encode_capture(&mixer.take_capture().unwrap()).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
audio.push(json!({"id":id,"decoder":"SoundBank::mod_sample","mixer":"Mixer::sample through SoundBank::queue_mod","source_rate":sample.rate,"decoded_samples":sample.data.len(),"mixed_rate":44100,"mixed_channels":2,"nonzero_output_samples":samples.iter().filter(|x|**x!=0).count(),"peak":samples.iter().map(|x|(*x as i32).abs()).max().unwrap(),"capture":file}));
|
||||
}
|
||||
}
|
||||
fs::write(out.join("native-review.json"),serde_json::to_vec_pretty(&json!({"scope":"Public PNG decoder, same Host art normalization, indexed Canvas blitter and actual SoundBank/Mixer. Synthetic backgrounds; no live desktop/gameplay claim.","assets":rows,"audio":audio})).unwrap()).unwrap();
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
{
|
||||
"package": "iron_coast_railburst",
|
||||
"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": 94,
|
||||
"scale": 1,
|
||||
"width": 16
|
||||
},
|
||||
{
|
||||
"height": 32,
|
||||
"painted": 376,
|
||||
"scale": 2,
|
||||
"width": 32
|
||||
},
|
||||
{
|
||||
"height": 48,
|
||||
"painted": 846,
|
||||
"scale": 3,
|
||||
"width": 48
|
||||
},
|
||||
{
|
||||
"height": 64,
|
||||
"painted": 1504,
|
||||
"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_railburst",
|
||||
"physical_canvas": [
|
||||
16,
|
||||
16
|
||||
]
|
||||
},
|
||||
{
|
||||
"all_scales": [
|
||||
{
|
||||
"height": 16,
|
||||
"painted": 92,
|
||||
"scale": 1,
|
||||
"width": 16
|
||||
},
|
||||
{
|
||||
"height": 32,
|
||||
"painted": 361,
|
||||
"scale": 2,
|
||||
"width": 32
|
||||
},
|
||||
{
|
||||
"height": 48,
|
||||
"painted": 809,
|
||||
"scale": 3,
|
||||
"width": 48
|
||||
},
|
||||
{
|
||||
"height": 64,
|
||||
"painted": 1434,
|
||||
"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_railburst",
|
||||
"physical_canvas": [
|
||||
64,
|
||||
64
|
||||
]
|
||||
},
|
||||
{
|
||||
"all_scales": [
|
||||
{
|
||||
"height": 20,
|
||||
"painted": 26,
|
||||
"scale": 1,
|
||||
"width": 4
|
||||
},
|
||||
{
|
||||
"height": 40,
|
||||
"painted": 104,
|
||||
"scale": 2,
|
||||
"width": 8
|
||||
},
|
||||
{
|
||||
"height": 60,
|
||||
"painted": 234,
|
||||
"scale": 3,
|
||||
"width": 12
|
||||
},
|
||||
{
|
||||
"height": 80,
|
||||
"painted": 416,
|
||||
"scale": 4,
|
||||
"width": 16
|
||||
}
|
||||
],
|
||||
"clear_corner_alpha": true,
|
||||
"frame": 0,
|
||||
"frames": 1,
|
||||
"hd": false,
|
||||
"kind": "projectile",
|
||||
"logical_canvas": [
|
||||
4,
|
||||
20
|
||||
],
|
||||
"ordinary_palette_only": true,
|
||||
"owner": "iron_coast_railburst",
|
||||
"physical_canvas": [
|
||||
4,
|
||||
20
|
||||
]
|
||||
},
|
||||
{
|
||||
"all_scales": [
|
||||
{
|
||||
"height": 20,
|
||||
"painted": 21,
|
||||
"scale": 1,
|
||||
"width": 4
|
||||
},
|
||||
{
|
||||
"height": 40,
|
||||
"painted": 87,
|
||||
"scale": 2,
|
||||
"width": 8
|
||||
},
|
||||
{
|
||||
"height": 60,
|
||||
"painted": 200,
|
||||
"scale": 3,
|
||||
"width": 12
|
||||
},
|
||||
{
|
||||
"height": 80,
|
||||
"painted": 352,
|
||||
"scale": 4,
|
||||
"width": 16
|
||||
}
|
||||
],
|
||||
"clear_corner_alpha": true,
|
||||
"frame": 0,
|
||||
"frames": 1,
|
||||
"hd": true,
|
||||
"kind": "projectile",
|
||||
"logical_canvas": [
|
||||
4,
|
||||
20
|
||||
],
|
||||
"ordinary_palette_only": true,
|
||||
"owner": "iron_coast_railburst",
|
||||
"physical_canvas": [
|
||||
16,
|
||||
80
|
||||
]
|
||||
}
|
||||
],
|
||||
"audio": [
|
||||
{
|
||||
"capture": "iron_coast_railburst-fire-mixed.wav",
|
||||
"decoded_samples": 3528,
|
||||
"decoder": "SoundBank::mod_sample",
|
||||
"id": "iron_coast_railburst:fire",
|
||||
"mixed_channels": 2,
|
||||
"mixed_rate": 44100,
|
||||
"mixer": "Mixer::sample through SoundBank::queue_mod",
|
||||
"nonzero_output_samples": 6320,
|
||||
"peak": 3200,
|
||||
"source_rate": 22050
|
||||
},
|
||||
{
|
||||
"capture": "iron_coast_railburst-impact-mixed.wav",
|
||||
"decoded_samples": 5071,
|
||||
"decoder": "SoundBank::mod_sample",
|
||||
"id": "iron_coast_railburst:impact",
|
||||
"mixed_channels": 2,
|
||||
"mixed_rate": 44100,
|
||||
"mixer": "Mixer::sample through SoundBank::queue_mod",
|
||||
"nonzero_output_samples": 11168,
|
||||
"peak": 2432,
|
||||
"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."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Reproduce isolated Stage 2 package validation and public indexed/audio review."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--data", type=Path)
|
||||
parser.add_argument("--output", type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
root = Path(__file__).resolve().parents[3]
|
||||
data = (args.data or root / "data").resolve()
|
||||
output = args.output.resolve()
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
packages = ["iron_coast_railburst", "iron_coast_depth_charge"]
|
||||
subprocess.run(["cargo", "build", "--locked", "--no-default-features", "--lib", "--bin", "raptor-rust"], cwd=root, check=True)
|
||||
deps = root / "target/debug/deps"
|
||||
suffix = ".exe" if os.name == "nt" else ""
|
||||
executable = output / ("native_review" + suffix)
|
||||
command = ["rustc", "--edition=2024", str(Path(__file__).with_name("native_review.rs")), "-L", f"dependency={deps}", "-o", str(executable)]
|
||||
libraries = {}
|
||||
for name in ["raptor_replica", "image", "serde_json"]:
|
||||
library = root / "target/debug/libraptor_replica.rlib" if name == "raptor_replica" else max(deps.glob(f"lib{name}-*.rlib"), key=lambda path: path.stat().st_mtime_ns)
|
||||
command += ["--extern", f"{name}={library}"]
|
||||
libraries[name] = {"path": str(library), "sha256": hashlib.sha256(library.read_bytes()).hexdigest()}
|
||||
subprocess.run(command, cwd=root, check=True)
|
||||
cases = []
|
||||
with tempfile.TemporaryDirectory(prefix="iron-coast-stage2-review-") as folder:
|
||||
frozen = Path(folder)
|
||||
for package in packages:
|
||||
shutil.copytree(root / "mods" / package, frozen / package)
|
||||
for selected in [[packages[0]], [packages[1]], packages]:
|
||||
result = subprocess.run([str(root / ("target/debug/raptor-rust" + suffix)), "--data", str(data), "--mods", str(frozen), "--validate-mods", ",".join(selected)], cwd=root, check=True, capture_output=True, text=True)
|
||||
print(result.stdout, end="")
|
||||
cases.append({"enabled": selected, "stdout": result.stdout.strip(), "stderr": result.stderr.strip(), "exit_code": result.returncode})
|
||||
subprocess.run([str(executable), str(data), str(frozen), str(output)], cwd=root, check=True)
|
||||
(output / "build-bindings.json").write_text(json.dumps({"libraries": libraries, "review_source_sha256": hashlib.sha256(Path(__file__).with_name("native_review.rs").read_bytes()).hexdigest(), "validation_cases": cases, "scope": "Frozen package copies; public asset, indexed Canvas and audio APIs; no live desktop or pilot mutations."}, indent=2) + "\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user