termfront 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +41 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +21 -0
- data/README.md +160 -0
- data/Rakefile +12 -0
- data/data/audio/THIRD_PARTY_NOTICES.md +45 -0
- data/data/audio/beep_02.ogg +0 -0
- data/data/audio/button1.ogg +0 -0
- data/data/audio/complete.ogg +0 -0
- data/data/audio/manifest.json +17 -0
- data/data/audio/mission_bgm.wav +0 -0
- data/data/audio/mission_clear_se.wav +0 -0
- data/data/audio/on.ogg +0 -0
- data/data/audio/page_se.wav +0 -0
- data/data/audio/sector.mp3 +0 -0
- data/data/audio/sfx_22b.ogg +0 -0
- data/data/audio/shield_alarm_se.wav +0 -0
- data/data/audio/shield_regen_se.wav +0 -0
- data/data/audio/shoot_01.ogg +0 -0
- data/data/audio/terminal_se.wav +0 -0
- data/data/audio/title.mp3 +0 -0
- data/data/audio/title_bgm.wav +0 -0
- data/data/audio/victory.mp3 +0 -0
- data/data/events/corridor_sweep.json +27 -0
- data/data/events/final_push.json +40 -0
- data/data/events/stronghold.json +27 -0
- data/data/events/the_gauntlet.json +27 -0
- data/data/events/training_grounds.json +31 -0
- data/exe/termfront +6 -0
- data/exe/termfront-server +7 -0
- data/lib/termfront/audio_manager.rb +225 -0
- data/lib/termfront/config.rb +38 -0
- data/lib/termfront/demo_player.rb +181 -0
- data/lib/termfront/drop_item/base.rb +26 -0
- data/lib/termfront/drop_item/weapon.rb +38 -0
- data/lib/termfront/enemy/base.rb +133 -0
- data/lib/termfront/enemy/crawler.rb +18 -0
- data/lib/termfront/enemy/executor.rb +18 -0
- data/lib/termfront/game.rb +637 -0
- data/lib/termfront/input.rb +75 -0
- data/lib/termfront/map.rb +72 -0
- data/lib/termfront/mission/base.rb +81 -0
- data/lib/termfront/mission/corridor_sweep.rb +41 -0
- data/lib/termfront/mission/event_loader.rb +87 -0
- data/lib/termfront/mission/event_runtime.rb +37 -0
- data/lib/termfront/mission/final_push.rb +44 -0
- data/lib/termfront/mission/stronghold.rb +45 -0
- data/lib/termfront/mission/the_gauntlet.rb +38 -0
- data/lib/termfront/mission/training.rb +38 -0
- data/lib/termfront/mission/training_grounds.rb +37 -0
- data/lib/termfront/network/client.rb +865 -0
- data/lib/termfront/network/connection.rb +101 -0
- data/lib/termfront/network/server.rb +620 -0
- data/lib/termfront/network/wavesfight_client.rb +364 -0
- data/lib/termfront/opponent.rb +24 -0
- data/lib/termfront/player.rb +147 -0
- data/lib/termfront/projectile.rb +44 -0
- data/lib/termfront/remote_enemy.rb +21 -0
- data/lib/termfront/renderer.rb +707 -0
- data/lib/termfront/scene_player.rb +164 -0
- data/lib/termfront/sprite.rb +73 -0
- data/lib/termfront/terminal_output.rb +63 -0
- data/lib/termfront/title_screen.rb +299 -0
- data/lib/termfront/version.rb +5 -0
- data/lib/termfront/weapon/assault_rifle.rb +15 -0
- data/lib/termfront/weapon/base.rb +44 -0
- data/lib/termfront/weapon/pistol.rb +15 -0
- data/lib/termfront/weapon/shock_pistol.rb +15 -0
- data/lib/termfront/weapon/shock_rifle.rb +15 -0
- data/lib/termfront.rb +51 -0
- data/sig/termfront.rbs +4 -0
- metadata +119 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 97daf7d1b118259e9d1bf5913b4f24ea301c5b3bea048c5b45b37f3df164a61c
|
|
4
|
+
data.tar.gz: 0d4911cd9755884f61dc9d8ee5400655d654dd55e710784997c974414626d5ce
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 7a19c3fa19333be6ddb23f63d2d944e70ea2f5128a0461822283ac3853046a82179aed19cdd5c8e46d36750afd1fddea6eb12f50c9be4d055077f3fe6f7d892d
|
|
7
|
+
data.tar.gz: ad42e1e6b604b473c5124b526e9510e0c33cfc01fdf44609822ec12784f4a7b24165d2dcaa95e488393163a7a80d84478f40293fc0b8689951be5eb99a267fb7
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on Keep a Changelog, and this project follows Semantic Versioning as it stabilizes.
|
|
6
|
+
|
|
7
|
+
## [0.1.0] - 2026-05-20
|
|
8
|
+
|
|
9
|
+
Initial public gem release candidate.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Terminal FPS core with DDA raycasting renderer
|
|
14
|
+
- Singleplayer mission mode
|
|
15
|
+
- Campaign mode with multiple missions
|
|
16
|
+
- JSON-driven campaign event system
|
|
17
|
+
- Story scenes with dialogue and title cards
|
|
18
|
+
- In-mission terminal interactions tied to campaign events
|
|
19
|
+
- Experimental PvP mode over TCP + TLS
|
|
20
|
+
- PvP matchmaking queues for `1v1`, `2v2`, and `4v4`
|
|
21
|
+
- Wavesfight PvE mode with stage selection, wave-based survival, and optional 2-player co-op
|
|
22
|
+
- External audio manifest and runtime audio playback
|
|
23
|
+
- Third-party audio notices for bundled CC0 assets
|
|
24
|
+
- Looping shield regeneration audio channel separate from BGM
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- Improved title/campaign transitions by fixing incomplete terminal writes
|
|
29
|
+
- Added terminal markers to the radar and interaction HUD
|
|
30
|
+
- Reworked campaign story content and terminal logs
|
|
31
|
+
- Replaced placeholder audio mappings with selected CC0 assets for BGM and core SE
|
|
32
|
+
- Reworked PvP client/server flow for team-based matches with ally/enemy sync, elimination handling, and team win detection
|
|
33
|
+
- Updated PvP spawn placement to use walkable map positions and improved diagonal team separation
|
|
34
|
+
- Updated PvP match-size selection to support arrow keys in addition to `J`/`K`
|
|
35
|
+
- Disabled quitting PvP matches with `Q` to avoid accidental exits during combat
|
|
36
|
+
- Added Wavesfight arena registration for `Corridor Sweep`, `Stronghold`, and `Final Push`
|
|
37
|
+
|
|
38
|
+
### Notes
|
|
39
|
+
|
|
40
|
+
- PvP is still considered experimental and needs broader WAN verification
|
|
41
|
+
- Audio playback depends on an available local player such as `ffplay`, `afplay`, `paplay`, or `aplay`
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 S.H.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 S-H-GAMELINKS
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Termfront
|
|
2
|
+
|
|
3
|
+
`Termfront` is a terminal FPS built in Ruby with a raycasting renderer, campaign scripting, audio support, and experimental PvP multiplayer.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- DDA raycasting renderer for ANSI terminals
|
|
8
|
+
- Singleplayer mission mode
|
|
9
|
+
- Wavesfight PvE mode with wave-based survival arenas
|
|
10
|
+
- Campaign mode with intro/outro scenes and in-mission terminals
|
|
11
|
+
- Experimental PvP over TCP + TLS
|
|
12
|
+
- Radar, pickups, weapons, shields, and enemy projectiles
|
|
13
|
+
- External audio manifest with BGM, SE, and looped shield regeneration audio
|
|
14
|
+
|
|
15
|
+
## Requirements
|
|
16
|
+
|
|
17
|
+
- Ruby `>= 3.2`
|
|
18
|
+
- A terminal with ANSI escape sequence support
|
|
19
|
+
- One of these audio players if you want sound:
|
|
20
|
+
- `ffplay`
|
|
21
|
+
- `afplay`
|
|
22
|
+
- `paplay`
|
|
23
|
+
- `aplay`
|
|
24
|
+
|
|
25
|
+
RubyGems metadata currently targets Ruby `0.1.0`.
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
If the gem is published:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
gem install termfront
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
For local development from this repository:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
bundle install
|
|
39
|
+
bundle exec rake test
|
|
40
|
+
bundle exec rake install
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Running
|
|
44
|
+
|
|
45
|
+
Start the game:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
termfront
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Start a PvP server:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
termfront-server
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Use a custom port:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
termfront-server 9000
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Default PvP port is `7777`.
|
|
64
|
+
|
|
65
|
+
## Controls
|
|
66
|
+
|
|
67
|
+
- `W` `A` `S` `D`: move
|
|
68
|
+
- `Left` / `Right`: turn
|
|
69
|
+
- `Space`: fire
|
|
70
|
+
- `T`: swap weapon
|
|
71
|
+
- `E`: interact / pick up / use terminal
|
|
72
|
+
- `Q` or `Esc`: quit or back out
|
|
73
|
+
- `Enter`: confirm menus
|
|
74
|
+
|
|
75
|
+
In story scenes:
|
|
76
|
+
|
|
77
|
+
- `Enter` / `Space`: next page
|
|
78
|
+
- `Esc` / `Q`: skip scene
|
|
79
|
+
|
|
80
|
+
## Modes
|
|
81
|
+
|
|
82
|
+
### Singleplayer
|
|
83
|
+
|
|
84
|
+
Quick mission start for testing the core combat loop.
|
|
85
|
+
|
|
86
|
+
### Campaign
|
|
87
|
+
|
|
88
|
+
Campaign missions include:
|
|
89
|
+
|
|
90
|
+
- mission start scenes
|
|
91
|
+
- mission complete scenes
|
|
92
|
+
- optional in-mission terminal logs
|
|
93
|
+
|
|
94
|
+
Story/event data lives in `data/events/*.json`.
|
|
95
|
+
|
|
96
|
+
### Wavesfight
|
|
97
|
+
|
|
98
|
+
Wavesfight is a PvE survival mode built on selected campaign maps.
|
|
99
|
+
|
|
100
|
+
- Select from `Corridor Sweep`, `Stronghold`, and `Final Push`
|
|
101
|
+
- Survive escalating enemy waves
|
|
102
|
+
- Difficulty ramps up every few waves
|
|
103
|
+
- Shield, health, and ammo get a partial refresh between waves
|
|
104
|
+
- Supports both solo play and 2-player online co-op
|
|
105
|
+
|
|
106
|
+
### PvP
|
|
107
|
+
|
|
108
|
+
PvP is currently marked experimental.
|
|
109
|
+
|
|
110
|
+
- The server listens on TCP and wraps traffic with TLS.
|
|
111
|
+
- The client connects directly to `host:port`.
|
|
112
|
+
- Matchmaking now supports `1v1`, `2v2`, and `4v4`.
|
|
113
|
+
- Players choose the match size on the client, and the server keeps separate queues for each mode.
|
|
114
|
+
- Team matches end when one side is fully eliminated.
|
|
115
|
+
- Local relay/start/state/ping behavior is covered by tests.
|
|
116
|
+
- Internet/WAN play still needs broader real-world verification.
|
|
117
|
+
|
|
118
|
+
For internet testing, the simplest setups are:
|
|
119
|
+
|
|
120
|
+
- direct TCP port forwarding to the host running `termfront-server`
|
|
121
|
+
- `nginx stream` TCP passthrough on a VPS
|
|
122
|
+
- a mesh/VPN overlay such as Tailscale
|
|
123
|
+
|
|
124
|
+
## Audio
|
|
125
|
+
|
|
126
|
+
Audio mappings are defined in:
|
|
127
|
+
|
|
128
|
+
- [data/audio/manifest.json](data/audio/manifest.json)
|
|
129
|
+
|
|
130
|
+
Third-party audio notices are tracked here:
|
|
131
|
+
|
|
132
|
+
- [data/audio/THIRD_PARTY_NOTICES.md](data/audio/THIRD_PARTY_NOTICES.md)
|
|
133
|
+
|
|
134
|
+
If no supported audio player is available, the game still runs without sound.
|
|
135
|
+
|
|
136
|
+
## Development
|
|
137
|
+
|
|
138
|
+
Run tests:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
ruby -Itest test/test_termfront.rb
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Build the gem:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
gem build termfront.gemspec
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Install the built gem locally:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
gem install ./termfront-0.1.0.gem
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
Code is available under the [MIT License](LICENSE.txt).
|
|
159
|
+
|
|
160
|
+
Third-party audio assets remain under their own licenses as documented in [data/audio/THIRD_PARTY_NOTICES.md](data/audio/THIRD_PARTY_NOTICES.md).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Third-Party Audio Notices
|
|
2
|
+
|
|
3
|
+
## In Use
|
|
4
|
+
|
|
5
|
+
### Dark Sci-Fi Audio Pack
|
|
6
|
+
|
|
7
|
+
- Author: SRG774
|
|
8
|
+
- License: CC0 1.0 Universal
|
|
9
|
+
- Source: https://opengameart.org/content/dark-sci-fi-audio-pack
|
|
10
|
+
- Used files:
|
|
11
|
+
- `title.mp3` -> `title_bgm`
|
|
12
|
+
- `sector.mp3` -> `mission_bgm`
|
|
13
|
+
- `victory.mp3` -> `shield_regen` loop
|
|
14
|
+
|
|
15
|
+
### 50 CC0 Sci-Fi SFX
|
|
16
|
+
|
|
17
|
+
- Author: rubberduck
|
|
18
|
+
- License: CC0 1.0 Universal
|
|
19
|
+
- Source: https://opengameart.org/content/50-cc0-sci-fi-sfx
|
|
20
|
+
- Used files:
|
|
21
|
+
- `shoot_01.ogg` -> `shoot`
|
|
22
|
+
- `beep_02.ogg` -> `shield_alarm`
|
|
23
|
+
|
|
24
|
+
### 60 CC0 Sci-Fi SFX
|
|
25
|
+
|
|
26
|
+
- Author: rubberduck
|
|
27
|
+
- License: CC0 1.0 Universal
|
|
28
|
+
- Source: https://opengameart.org/content/60-cc0-sci-fi-sfx
|
|
29
|
+
- Used files:
|
|
30
|
+
- `sfx_22b.ogg` -> `damage`
|
|
31
|
+
|
|
32
|
+
### UI Sounds
|
|
33
|
+
|
|
34
|
+
- Author: StumpyStrust
|
|
35
|
+
- License: CC0 1.0 Universal
|
|
36
|
+
- Source: https://opengameart.org/content/ui-sounds
|
|
37
|
+
- Used files:
|
|
38
|
+
- `button1.ogg` -> `terminal`
|
|
39
|
+
- `on.ogg` -> `page`
|
|
40
|
+
- `complete.ogg` -> `mission_clear`
|
|
41
|
+
|
|
42
|
+
## Notes
|
|
43
|
+
|
|
44
|
+
- Because these assets are CC0, they can be redistributed with the gem without changing the gem's own code license.
|
|
45
|
+
- Even though attribution is not required for CC0 assets, this file keeps provenance clear for future maintenance.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"bgm": {
|
|
3
|
+
"title": "data/audio/title.mp3",
|
|
4
|
+
"mission": "data/audio/sector.mp3"
|
|
5
|
+
},
|
|
6
|
+
"se": {
|
|
7
|
+
"shoot": "data/audio/shoot_01.ogg",
|
|
8
|
+
"damage": "data/audio/sfx_22b.ogg",
|
|
9
|
+
"terminal": "data/audio/button1.ogg",
|
|
10
|
+
"mission_clear": "data/audio/complete.ogg",
|
|
11
|
+
"page": "data/audio/on.ogg",
|
|
12
|
+
"shield_alarm": "data/audio/beep_02.ogg"
|
|
13
|
+
},
|
|
14
|
+
"loop_se": {
|
|
15
|
+
"shield_regen": "data/audio/victory.mp3"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
Binary file
|
|
Binary file
|
data/data/audio/on.ogg
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"events": [
|
|
3
|
+
{
|
|
4
|
+
"id": "corridor_sweep_intro",
|
|
5
|
+
"trigger": { "type": "mission_start" },
|
|
6
|
+
"actions": [
|
|
7
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "Facility A-13 went dark six hours ago. This corridor is your first live sector." },
|
|
8
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "Sweep the access corridor and recover any surviving logs before local systems collapse." }
|
|
9
|
+
]
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"id": "corridor_terminal_a",
|
|
13
|
+
"trigger": { "type": "terminal_used", "terminal_id": "ops_corridor_a" },
|
|
14
|
+
"actions": [
|
|
15
|
+
{ "type": "text", "text": "OPS LOG 04\nPower loss started in the maintenance wing, then moved against cable direction.\nSecurity sealed Sector C after staff reported chanting inside locked rooms." }
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": "corridor_sweep_outro",
|
|
20
|
+
"trigger": { "type": "mission_complete" },
|
|
21
|
+
"actions": [
|
|
22
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "Corridor secure. The blackout did not stop the transmissions." },
|
|
23
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "Advance to the service run. If the logs are right, the facility was sealing something in, not keeping us out." }
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"events": [
|
|
3
|
+
{
|
|
4
|
+
"id": "final_push_intro",
|
|
5
|
+
"trigger": { "type": "mission_start" },
|
|
6
|
+
"actions": [
|
|
7
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "This is the last gate. Expect fortress-grade resistance and no clean answers." },
|
|
8
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "If the archive core is intact, bring back whatever it stored and who authorized the breach." }
|
|
9
|
+
]
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"id": "final_push_terminal_archive",
|
|
13
|
+
"trigger": { "type": "terminal_used", "terminal_id": "archive_core" },
|
|
14
|
+
"actions": [
|
|
15
|
+
{ "type": "text", "text": "ARCHIVE CORE\nDirective mismatch detected.\nContainment protocol revoked by archive authority: ORPHEUS.\nLocal command objections logged, denied, and sealed." }
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": "final_push_outro",
|
|
20
|
+
"trigger": { "type": "mission_complete" },
|
|
21
|
+
"actions": [
|
|
22
|
+
{
|
|
23
|
+
"type": "demo",
|
|
24
|
+
"duration": 3.0,
|
|
25
|
+
"caption": "ARCHIVE VAULT / SIGNAL STILL PRESENT",
|
|
26
|
+
"path": [
|
|
27
|
+
{ "x": 20.5, "y": 9.5, "angle": 3.14, "t": 0.0 },
|
|
28
|
+
{ "x": 16.5, "y": 9.5, "angle": 3.05, "t": 1.0 },
|
|
29
|
+
{ "x": 11.5, "y": 9.5, "angle": 2.95, "t": 2.0 },
|
|
30
|
+
{ "x": 7.5, "y": 8.5, "angle": 2.75, "t": 3.0 }
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
{ "type": "title_card", "text": "FORTRESS CLEARED\nSIGNAL SOURCE UNRESOLVED" },
|
|
34
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "Fortress cleared. The signal is still active somewhere below you." },
|
|
35
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "This facility did not fail containment. Someone revoked it." },
|
|
36
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "Archive authority ORPHEUS is still broadcasting. This sector is over, but the incident is not." }
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"events": [
|
|
3
|
+
{
|
|
4
|
+
"id": "stronghold_intro",
|
|
5
|
+
"trigger": { "type": "mission_start" },
|
|
6
|
+
"actions": [
|
|
7
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "Inner rooms are fortified. Executors are holding the choke points on purpose." },
|
|
8
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "Break the stronghold and find the source of their command signal before it reroutes again." }
|
|
9
|
+
]
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"id": "stronghold_terminal_guard",
|
|
13
|
+
"trigger": { "type": "terminal_used", "terminal_id": "guard_post" },
|
|
14
|
+
"actions": [
|
|
15
|
+
{ "type": "text", "text": "SECURITY POST\nStaff rotation suspended by archive authority, not site command.\nAny report of ritual language is to be escalated and removed from local logs before outside review." }
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": "stronghold_outro",
|
|
20
|
+
"trigger": { "type": "mission_complete" },
|
|
21
|
+
"actions": [
|
|
22
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "Stronghold is down. Something in the facility wanted time, not victory." },
|
|
23
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "Archive authority overrode local containment. Push the final gate and confirm what they were trying to keep active." }
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"events": [
|
|
3
|
+
{
|
|
4
|
+
"id": "the_gauntlet_intro",
|
|
5
|
+
"trigger": { "type": "mission_start" },
|
|
6
|
+
"actions": [
|
|
7
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "The service corridor ahead is a kill lane, but its layout is wrong for defense." },
|
|
8
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "Push through fast. If a terminal still answers, check why the shutters were chained inward." }
|
|
9
|
+
]
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"id": "the_gauntlet_terminal_service",
|
|
13
|
+
"trigger": { "type": "terminal_used", "terminal_id": "service_hub" },
|
|
14
|
+
"actions": [
|
|
15
|
+
{ "type": "text", "text": "SERVICE HUB\nEmergency shutters failed in sequence from the archive end of the corridor.\nWitnesses reported synchronized movement before first contact, as if something was herding them away from the vault." }
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": "the_gauntlet_outro",
|
|
20
|
+
"trigger": { "type": "mission_complete" },
|
|
21
|
+
"actions": [
|
|
22
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "You made it through. The path deeper into the complex is open." },
|
|
23
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "These corridors were built to funnel breaches back toward the core. Move on the stronghold and find who broke the seal." }
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"events": [
|
|
3
|
+
{
|
|
4
|
+
"id": "training_grounds_intro",
|
|
5
|
+
"trigger": { "type": "mission_start" },
|
|
6
|
+
"actions": [
|
|
7
|
+
{ "type": "title_card", "text": "OPERATION: TRAINING GROUNDS\nSIMULATION WING / SECTOR A-13" },
|
|
8
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "This is a training sweep on paper. Treat it like deployment anyway." },
|
|
9
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "Sector A-13 lost contact beyond this wing. We are not waiting for a second failure." },
|
|
10
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "Use the yard terminals. They still carry the old incident briefings." }
|
|
11
|
+
]
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"id": "training_grounds_terminal_intro",
|
|
15
|
+
"trigger": { "type": "terminal_used", "terminal_id": "training_console" },
|
|
16
|
+
"actions": [
|
|
17
|
+
{ "type": "text", "text": "TRAINING CONSOLE\nIncident drill package: Sector A-13 containment loss.\nScenario note: field teams are not to be told whether the exercise has gone live." }
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "training_grounds_outro",
|
|
22
|
+
"trigger": { "type": "mission_complete" },
|
|
23
|
+
"actions": [
|
|
24
|
+
{ "type": "title_card", "text": "SECTOR SECURE\nTRAINING SWEEP COMPLETE" },
|
|
25
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "Training sweep complete. Your live assignment starts now." },
|
|
26
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "The blackout in the next sector is real. This was the last clean room." },
|
|
27
|
+
{ "type": "dialogue", "speaker": "OPS", "text": "Move to the access corridor. Recover logs before the sector goes completely dark." }
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
data/exe/termfront
ADDED