Add independent Rust engine, deterministic mod API and asset pipeline
This commit is contained in:
1 parent
f2cce6f51b
commit
dbb1d4596b
53 files changed
+18314
-56
No files matched your search
@@ -0,0 +1,15 @@
|
||||
# Aurora Field Trials
|
||||
|
||||
This API v1 example adds a scripted pulse cannon, a repair pickup, weaving drones, a guardian, a mission and a campaign. It references the player's installed original sprite catalog; no game artwork is included.
|
||||
|
||||
From the repository root:
|
||||
|
||||
```sh
|
||||
cargo run --no-default-features -- --mods examples/mods --validate-mods aurora
|
||||
cargo run --no-default-features -- --mods examples/mods --enabled aurora \
|
||||
--headless aurora:field_trials --ticks 700
|
||||
```
|
||||
|
||||
To play, start the Rust engine with `--mods examples/mods`, enable Aurora in **Mods**, apply the selection at the main menu, create a separate pilot and choose **Aurora Field Trials**. The mission equips its cannon on the first simulation step. Keep existing pilots' required mod sets available.
|
||||
|
||||
Content IDs intentionally separate the inventory item `aurora:pulse_cannon` from its projectile `aurora:pulse_projectile`. The scripts demonstrate `on_fire`, `on_hit`, `on_spawn`, `on_tick`, `on_death`, `on_pickup`, `on_use`, `on_mission_start` and `on_mission_end`. See `docs/modding-api.md` for the complete API and compatibility rules.
|
||||
@@ -0,0 +1,247 @@
|
||||
{
|
||||
"weapons": [
|
||||
{
|
||||
"id": "aurora:pulse_projectile",
|
||||
"name": "Aurora Pulse",
|
||||
"damage": 3,
|
||||
"speed": 8,
|
||||
"cooldown": 9,
|
||||
"behavior": "straight",
|
||||
"target": "all",
|
||||
"offsets": [
|
||||
[
|
||||
0,
|
||||
-4
|
||||
]
|
||||
],
|
||||
"art": {
|
||||
"asset": 65999,
|
||||
"logical_width": 8,
|
||||
"logical_height": 8,
|
||||
"frames": 2
|
||||
},
|
||||
"script": "scripts/weapon.rhai"
|
||||
},
|
||||
{
|
||||
"id": "aurora:drone_projectile",
|
||||
"name": "Drone Pulse",
|
||||
"damage": 3,
|
||||
"speed": 3,
|
||||
"cooldown": 32,
|
||||
"behavior": "straight",
|
||||
"target": "all",
|
||||
"art": {
|
||||
"asset": 65999,
|
||||
"logical_width": 8,
|
||||
"logical_height": 8,
|
||||
"frames": 2
|
||||
}
|
||||
}
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"id": "aurora:pulse_cannon",
|
||||
"name": "Aurora Pulse Cannon",
|
||||
"price": 4000,
|
||||
"max_count": 1,
|
||||
"weapon": "aurora:pulse_projectile",
|
||||
"art": {
|
||||
"asset": 66225,
|
||||
"logical_width": 16,
|
||||
"logical_height": 16
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "aurora:repair_cell",
|
||||
"name": "Aurora Repair Cell",
|
||||
"price": 100,
|
||||
"max_count": 10,
|
||||
"consumable": true,
|
||||
"shield": 12,
|
||||
"art": {
|
||||
"asset": 66225,
|
||||
"logical_width": 16,
|
||||
"logical_height": 16
|
||||
},
|
||||
"script": "scripts/cell.rhai",
|
||||
"special": true
|
||||
}
|
||||
],
|
||||
"enemies": [
|
||||
{
|
||||
"id": "aurora:weaver",
|
||||
"name": "Aurora Weaver",
|
||||
"health": 16,
|
||||
"speed": 2,
|
||||
"reward": 100,
|
||||
"cooldown": 32,
|
||||
"weapon": "aurora:drone_projectile",
|
||||
"drop": "aurora:repair_cell",
|
||||
"art": {
|
||||
"asset": 66296,
|
||||
"logical_width": 32,
|
||||
"logical_height": 24
|
||||
},
|
||||
"script": "scripts/drone.rhai"
|
||||
},
|
||||
{
|
||||
"id": "aurora:guardian",
|
||||
"name": "Aurora Guardian",
|
||||
"health": 160,
|
||||
"speed": 1,
|
||||
"reward": 1500,
|
||||
"boss": true,
|
||||
"cooldown": 20,
|
||||
"weapon": "aurora:drone_projectile",
|
||||
"drop": "aurora:repair_cell",
|
||||
"path": [
|
||||
[
|
||||
0,
|
||||
60
|
||||
],
|
||||
[
|
||||
40,
|
||||
60
|
||||
],
|
||||
[
|
||||
-40,
|
||||
60
|
||||
]
|
||||
],
|
||||
"repeat": true,
|
||||
"art": {
|
||||
"asset": 66310,
|
||||
"logical_width": 80,
|
||||
"logical_height": 40
|
||||
},
|
||||
"script": "scripts/drone.rhai"
|
||||
}
|
||||
],
|
||||
"missions": [
|
||||
{
|
||||
"id": "aurora:field_trials",
|
||||
"name": "Aurora Field Trials",
|
||||
"duration": 650,
|
||||
"spawns": [
|
||||
{
|
||||
"tick": 30,
|
||||
"enemy": "aurora:weaver",
|
||||
"x": 70,
|
||||
"y": -24
|
||||
},
|
||||
{
|
||||
"tick": 60,
|
||||
"enemy": "aurora:weaver",
|
||||
"x": 200,
|
||||
"y": -24
|
||||
},
|
||||
{
|
||||
"tick": 110,
|
||||
"enemy": "aurora:weaver",
|
||||
"x": 140,
|
||||
"y": -24
|
||||
},
|
||||
{
|
||||
"tick": 150,
|
||||
"enemy": "aurora:weaver",
|
||||
"x": 90,
|
||||
"y": -24
|
||||
},
|
||||
{
|
||||
"tick": 180,
|
||||
"enemy": "aurora:weaver",
|
||||
"x": 190,
|
||||
"y": -24
|
||||
},
|
||||
{
|
||||
"tick": 230,
|
||||
"enemy": "aurora:weaver",
|
||||
"x": 150,
|
||||
"y": -24
|
||||
},
|
||||
{
|
||||
"tick": 300,
|
||||
"enemy": "aurora:guardian",
|
||||
"x": 120,
|
||||
"y": -40
|
||||
}
|
||||
],
|
||||
"tiles": [
|
||||
{
|
||||
"art": {
|
||||
"asset": 66400,
|
||||
"logical_width": 32,
|
||||
"logical_height": 32
|
||||
}
|
||||
}
|
||||
],
|
||||
"columns": 9,
|
||||
"layout": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"script": "scripts/mission.rhai"
|
||||
}
|
||||
],
|
||||
"campaigns": [
|
||||
{
|
||||
"id": "aurora:trials",
|
||||
"name": "Aurora Trials",
|
||||
"missions": [
|
||||
"aurora:field_trials"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
id = "aurora"
|
||||
name = "Aurora Field Trials"
|
||||
version = "1.0.0"
|
||||
api_version = 1
|
||||
description = "A short mission with a scripted pulse cannon, weaving drones and repair cells. Uses your installed original artwork."
|
||||
content = "content.json"
|
||||
scripts = ["scripts/weapon.rhai", "scripts/drone.rhai", "scripts/cell.rhai", "scripts/mission.rhai"]
|
||||
@@ -0,0 +1,11 @@
|
||||
fn on_pickup(event, state, random) {
|
||||
let recovered = if state.contains("recovered") { state.recovered + 1 } else { 1 };
|
||||
#{ commands: [#{ op: "credits", amount: 25 }], state: #{ recovered: recovered } }
|
||||
}
|
||||
|
||||
// A selected repair cell can also be consumed with the special-action button.
|
||||
fn on_use(event, state, random) {
|
||||
let used = if state.contains("used") { state.used + 1 } else { 1 };
|
||||
state.used = used;
|
||||
#{ commands: [#{ op: "objective", key: "aurora:repairs_used", value: used }], state: state }
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
fn on_spawn(event, state, random) {
|
||||
#{ commands: [], state: state }
|
||||
}
|
||||
|
||||
fn on_tick(event, state, random) {
|
||||
// on_tick may be queued on the same step as on_death; do not command a retired entity.
|
||||
if event.health <= 0 { return #{ commands: [], state: state }; }
|
||||
let sideways = if (event.tick / 24) % 2 == 0 { 1 } else { -1 };
|
||||
#{ commands: [#{ op: "velocity", entity: event.entity, vx: sideways, vy: 1 }], state: state }
|
||||
}
|
||||
|
||||
fn on_death(event, state, random) {
|
||||
let destroyed = if state.contains("destroyed") { state.destroyed + 1 } else { 1 };
|
||||
#{ commands: [#{ op: "objective", key: "aurora:destroyed", value: destroyed }],
|
||||
state: #{ destroyed: destroyed } }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fn on_mission_start(event, state, random) {
|
||||
#{ commands: [
|
||||
#{ op: "give_item", item: "aurora:pulse_cannon", count: 1 },
|
||||
#{ op: "objective", key: "aurora:destroyed", value: 0 }
|
||||
], state: state }
|
||||
}
|
||||
|
||||
fn on_mission_end(event, state, random) {
|
||||
#{ commands: [#{ op: "objective", key: "aurora:trial_finished", value: 1 }], state: state }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// The normal centre projectile is emitted by the engine. Add two angled pulses.
|
||||
fn on_fire(event, state, random) {
|
||||
let shots = if state.contains("shots") { state.shots + 1 } else { 1 };
|
||||
let spread = 1 + random[0] % 2;
|
||||
#{ commands: [
|
||||
#{ op: "projectile", weapon: "aurora:pulse_projectile", x: event.x - 6, y: event.y, vx: -spread, vy: -8 },
|
||||
#{ op: "projectile", weapon: "aurora:pulse_projectile", x: event.x + 6, y: event.y, vx: spread, vy: -8 }
|
||||
], state: #{ shots: shots } }
|
||||
}
|
||||
|
||||
fn on_hit(event, state, random) {
|
||||
#{ commands: [#{ op: "effect", x: event.x, y: event.y }], state: state }
|
||||
}
|
||||
Reference in new issue
Block a user