-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdata.js
More file actions
201 lines (186 loc) · 13.8 KB
/
Copy pathdata.js
File metadata and controls
201 lines (186 loc) · 13.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/* =====================================================================
* data.js: the bundled EXAMPLE BATTLE (a COMPLETE, self-contained demo).
* ---------------------------------------------------------------------
* This is a FICTIONAL coastal assault: "Blue Force" lands from the sea and
* drives inland up the mountains; "Red Force" defends the high ground. It is
* NOT a real battle, it cites no sources (it is invented), and it exists only
* to show the engine running a full scenario out of the box on real terrain.
*
* To build YOUR OWN battle, do NOT edit this file. Copy the minimal annotated
* skeleton instead: data.example.js (and flags.example.js), then follow
* PLAYBOOK.md (the field reference) and AGENTS.md (the procedure). Validate as
* you author, no browser or tiles needed: node tools/validate.mjs data.example.js
*
* Bilingual slots: `_zh` = your PRIMARY / local language (any script: set
* meta.fonts + meta.dir:"rtl" for non-Latin / right-to-left); `_en` = the
* SECONDARY language (conventionally English). This fictional demo uses English in both.
* ===================================================================== */
window.BATTLE_DATA = (function () {
/* -- the two sides. The faction <key> ("blue"/"red") becomes a CSS variable
* (--fac-<key>) and a class. role drives attacker/defender behaviour. ------- */
const factions = {
blue: { main:0x3b7be2, glow:0x5aa0ff, dim:0x1f3f7a, css:"#3b7be2", name_zh:"Blue Force", name_en:"Blue Force", role:"attacker", maxStrength:5200, defaultFlag:"blue" },
red: { main:0xe23b3b, glow:0xff6a5a, dim:0x7a1f1f, css:"#e23b3b", name_zh:"Red Force", name_en:"Red Force", role:"defender", maxStrength:4800, defaultFlag:"red" },
};
/* -- the map box (REAL WGS84 lng/lat) + the clock window + identity.
* meta.geo is the single bbox source (tools/fetch_tiles reads it). Z is the tile zoom. */
const meta = {
geo:{ minLng:14.58, maxLng:14.72, minLat:40.61, maxLat:40.72, Z:13 }, // a real coastal mountain front: sea to the south, ridges inland
dayMin:1, dayMax:2.4, year:0, month:0, lastDay:2, // clock window (a fictional battle, so the running date chip is hidden via ui.sceneLabel below rather than shown as a fake calendar date)
title:"Example Battle", subtitle:"A fictional coastal assault, built to show the engine",
// OPTIONAL theme:{ sky:{...}, sea, sun:{...}, grade:{...} } restyles the look (see PLAYBOOK.md); omitted here to use the engine defaults.
};
/* -- ui: only the scene-label is customised here; every other interface string uses the engine's English DEFAULT_UI.
* ui.sceneLabel: false hides the running date chip; a string with {year}/{month}/{day} tokens formats it instead. */
const ui = { sceneLabel:false }; // fictional battle: hide the calendar chip (the per-shot dateLabels carry the relative day)
/* -- intro: the opening title card + its establishing camera. ----------------- */
const intro = { title_zh:"Example Battle", title_en:"Example Battle",
sub_zh:"A fictional coastal assault, Blue Force vs Red Force", sub_en:"A fictional coastal assault, Blue Force vs Red Force",
cam:{ lng:14.642, lat:40.662, dist:3000, az:0, el:54 } };
/* -- outro: the closing pull-back camera. ------------------------------------- */
const outro = { title_zh:"The Beachhead Holds", title_en:"The Beachhead Holds",
narration_zh:"By nightfall Blue Force is ashore and into the hills. A fictional engine demo: replace it with your own battle.",
narration_en:"By nightfall Blue Force is ashore and into the hills. A fictional engine demo: replace it with your own battle.",
cam:{ lng:14.636, lat:40.66, dist:2900, az:0, el:50, orbit:1.0, tween:3.4 } };
/* -- flagLegend: the flag swatches in the legend (flag id + faction). Art is in flags.js. -- */
const flagLegend = [
{ flag:"blue", zh:"Blue Force", en:"Blue Force", faction:"blue" },
{ flag:"red", zh:"Red Force", en:"Red Force", faction:"red" },
];
/* -- geography: place labels + an optional defensive line. All on land. -------- */
const geography = {
points: [
{ name_en:"The Bay", name_zh:"The Bay", type:"town", lng:14.632, lat:40.651 },
{ name_en:"West Cove", name_zh:"West Cove", type:"town", lng:14.612, lat:40.648 },
{ name_en:"East Point", name_zh:"East Point", type:"fort", lng:14.668, lat:40.652 },
{ name_en:"Hill 953", name_zh:"Hill 953", type:"peak", lng:14.620, lat:40.701, h:953 },
{ name_en:"North Ridge", name_zh:"North Ridge", type:"region", lng:14.640, lat:40.700 },
{ name_en:"The Saddle", name_zh:"The Saddle", type:"peak", lng:14.654, lat:40.690 },
],
lines: [
{ name_zh:"Red Defence Line", name_en:"Red Defence Line", color:"#e23b3b",
path:[[14.612,40.690],[14.634,40.686],[14.654,40.686],[14.668,40.680]],
fade:{ holdUntil:1.4, collapseBy:2.2, span:0.5 } },
],
};
/* -- units: each force along its track of keyframes {d,lng,lat,s,st}.
* st (state) in march | hold | attack | retreat | landing | dead. Every keyframe is on land. -- */
const units = [
// Blue Force: lands along the bay and drives inland up the valleys.
{ id:"blue_marines", faction:"blue", kind:"infantry", flag:"blue", cf:true,
name_zh:"Blue Marines", name_en:"Blue Marines", type:"Marines",
track:[ {d:1, lng:14.632, lat:40.651, s:1600, st:"landing"},
{d:1.5, lng:14.633, lat:40.662, s:1500, st:"attack"},
{d:2, lng:14.635, lat:40.674, s:1380, st:"attack"} ] },
{ id:"blue_rifles", faction:"blue", kind:"infantry", flag:"blue", cf:true,
name_zh:"1st Rifles", name_en:"1st Rifles", type:"Infantry",
track:[ {d:1, lng:14.614, lat:40.650, s:1300, st:"landing"},
{d:2, lng:14.620, lat:40.668, s:1120, st:"attack"} ] },
{ id:"blue_cdo", faction:"blue", kind:"infantry", flag:"blue", cf:true,
name_zh:"Blue Commandos", name_en:"Blue Commandos", type:"Commandos",
track:[ {d:1, lng:14.662, lat:40.651, s:900, st:"landing"},
{d:2, lng:14.658, lat:40.667, s:760, st:"attack"} ] },
{ id:"blue_armour", faction:"blue", kind:"infantry", flag:"blue", cf:true,
name_zh:"Armoured Squadron", name_en:"Armoured Squadron", type:"Armour",
track:[ {d:1.3, lng:14.634, lat:40.654, s:1200, st:"march"},
{d:2, lng:14.640, lat:40.676, s:1140, st:"attack"} ] },
{ id:"blue_fleet", faction:"blue", kind:"navy", flag:"blue", cf:true,
name_zh:"Naval Squadron", name_en:"Naval Squadron", type:"Fire Support",
track:[ {d:1, lng:14.626, lat:40.634, s:1500, st:"attack"},
{d:2, lng:14.648, lat:40.636, s:1400, st:"attack"} ] },
{ id:"blue_air", faction:"blue", kind:"air", flag:"blue", cf:true,
name_zh:"Air Wing", name_en:"Air Wing", type:"Air Support",
track:[ {d:1, lng:14.626, lat:40.658, s:1200, st:"attack"},
{d:2, lng:14.646, lat:40.682, s:1100, st:"attack"} ] },
// Red Force: holds the ridges, a coastal battery on the east point, a reserve that counterattacks.
{ id:"red_garrison", faction:"red", kind:"infantry", flag:"red", cf:true,
name_zh:"Red Garrison", name_en:"Red Garrison", type:"Infantry",
track:[ {d:1, lng:14.634, lat:40.686, s:1400, st:"hold"},
{d:2, lng:14.637, lat:40.696, s:980, st:"retreat"} ] },
{ id:"red_mtn", faction:"red", kind:"infantry", flag:"red", cf:true,
name_zh:"Mountain Battalion", name_en:"Mountain Battalion", type:"Infantry",
track:[ {d:1, lng:14.614, lat:40.691, s:1100, st:"hold"},
{d:2, lng:14.617, lat:40.697, s:920, st:"hold"} ] },
{ id:"red_battery", faction:"red", kind:"artillery", flag:"red", cf:true,
name_zh:"Coastal Battery", name_en:"Coastal Battery", type:"Artillery",
track:[ {d:1, lng:14.668, lat:40.664, s:800, st:"hold"},
{d:2, lng:14.665, lat:40.680, s:540, st:"retreat"} ] },
{ id:"red_reserve", faction:"red", kind:"infantry", flag:"red", cf:true,
name_zh:"Red Reserve", name_en:"Red Reserve", type:"Infantry",
track:[ {d:1, lng:14.644, lat:40.710, s:1300, st:"hold"},
{d:2, lng:14.640, lat:40.695, s:1180, st:"attack"} ] },
];
/* -- arrows: dated movement annotations {f,from,to,d,kind,label}. The seaborne
* approach is shown by LANDING arrows (sea -> shore), not by units on the water. -- */
const arrows = [
{ f:"blue", from:[14.630,40.632], to:[14.632,40.648], d:1.0, kind:"landing", label:"Landing" },
{ f:"blue", from:[14.610,40.630], to:[14.614,40.647], d:1.0, kind:"landing", label:"Landing" },
{ f:"blue", from:[14.666,40.632], to:[14.662,40.648], d:1.0, kind:"landing", label:"Landing" },
{ f:"blue", from:[14.633,40.654], to:[14.635,40.672], d:1.6, kind:"attack", label:"Advance" },
{ f:"red", from:[14.643,40.708], to:[14.640,40.696], d:2.0, kind:"attack", label:"Counterattack" },
];
/* -- fronts: dated front-line polylines, each { d, path:[[lng,lat],…] }. All on land. -- */
const fronts = [
{ d:1, path:[[14.612,40.666],[14.634,40.662],[14.654,40.664],[14.668,40.666]] },
{ d:2, path:[[14.616,40.688],[14.636,40.684],[14.654,40.684],[14.666,40.682]] },
];
/* -- weather: per-day { d, night, fog, rain, smoke } (each 0..1). ------------- */
const weather = [
{ d:1, night:0.12, fog:0.12, rain:0.0, smoke:0.05, zh:"Dawn, hazy", en:"Dawn, hazy" },
{ d:2, night:0.0, fog:0.18, rain:0.05, smoke:0.18, zh:"Overcast, smoke", en:"Overcast, smoke" },
];
/* -- hotspots: dated combat FX { a, b, kind, lng, lat, i }. -------------------- */
const hotspots = [
{ a:1.0, b:1.5, kind:"landing", lng:14.632, lat:40.650, i:0.7 },
{ a:1.0, b:1.5, kind:"landing", lng:14.662, lat:40.650, i:0.5 },
{ a:1.2, b:2.0, kind:"artillery", lng:14.624, lat:40.676, i:0.55 },
{ a:1.6, b:2.3, kind:"firefight", lng:14.636, lat:40.684, i:0.7 },
];
/* -- storyboard: the directed shots the camera plays in order. ----------------- */
const storyboard = [
{ day:1, hold:9, cam:{lng:14.636, lat:40.658, dist:2700, az:0, el:42, orbit:0.6},
title_zh:"The Approach", title_en:"The Approach", dateLabel:"DAY 1 · 05:30",
narration_zh:"At first light Blue Force closes on the coast, the fleet standing off the bay.",
narration_en:"At first light Blue Force closes on the coast, the fleet standing off the bay.",
side:"blue", focus:["blue_marines"] },
{ day:1.15, hold:11, cam:{lng:14.632, lat:40.652, dist:1300, az:0, el:38, orbit:0.7},
title_zh:"The Landings", title_en:"The Landings", dateLabel:"DAY 1 · 06:10",
narration_zh:"The first waves hit the bay and the flanking coves, under fire from the coastal battery on East Point.",
narration_en:"The first waves hit the bay and the flanking coves, under fire from the coastal battery on East Point.",
side:"blue", focus:["blue_marines","blue_rifles","blue_cdo"] },
{ day:1.5, hold:10, cam:{lng:14.632, lat:40.668, dist:1250, az:0, el:44, orbit:0.8},
title_zh:"Into the Hills", title_en:"Into the Hills", dateLabel:"DAY 1 · Afternoon",
narration_zh:"Off the beaches, Blue pushes inland up the valleys toward the ridge.",
narration_en:"Off the beaches, Blue pushes inland up the valleys toward the ridge.",
side:"blue", focus:["blue_marines","blue_armour"] },
{ day:2, hold:11, cam:{lng:14.636, lat:40.686, dist:1150, az:200, el:46, orbit:0.8},
title_zh:"The Ridge", title_en:"The Ridge", dateLabel:"DAY 2 · Morning",
narration_zh:"Red Force holds the high ground along the ridge. The fighting is hardest here.",
narration_en:"Red Force holds the high ground along the ridge. The fighting is hardest here.",
side:"both", focus:["red_garrison","blue_marines"] },
{ day:2.1, hold:10, cam:{lng:14.642, lat:40.700, dist:1300, az:0, el:44, orbit:0.9},
title_zh:"The Counterattack", title_en:"The Counterattack", dateLabel:"DAY 2 · Midday",
narration_zh:"Red's reserve strikes back down from North Ridge, but the beachhead holds.",
narration_en:"Red's reserve strikes back down from North Ridge, but the beachhead holds.",
side:"red", focus:["red_reserve","blue_armour"] },
{ day:2.3, hold:12, cam:{lng:14.636, lat:40.662, dist:2600, az:0, el:50, orbit:1.0},
title_zh:"The Beachhead Holds", title_en:"The Beachhead Holds", dateLabel:"DAY 2 · Nightfall",
narration_zh:"By nightfall Blue Force is ashore and into the hills, the coast secured.",
narration_en:"By nightfall Blue Force is ashore and into the hills, the coast secured.",
side:"blue", focus:["blue_marines","blue_armour","blue_rifles"] },
{ day:2, hold:13, cam:{lng:14.652, lat:40.680, dist:1150, az:200, el:46, orbit:0.5},
title_zh:"Combined Arms", title_en:"Combined Arms", dateLabel:"DAY 2",
narration_zh:"Each arm reads as its own shape: the swept aircraft aloft, the artillery gun, and the infantry wedge.",
narration_en:"Each arm reads as its own shape: the swept aircraft aloft, the artillery gun, and the infantry wedge.",
side:"both", focus:["blue_air","red_battery"] },
];
/* -- notes: REQUIRED. For a real battle, sources MUST cite your references; the
* engine refuses to boot without a non-empty sources. This demo is fictional, marked honestly. -- */
const notes = {
summary:"A fictional coastal assault (Blue Force vs Red Force), built to demonstrate the engine on real terrain. Not a real battle.",
caveats:[ "Every force, movement, label and event here is invented for the demo; nothing depicts a real engagement.",
"The terrain is real present-day satellite imagery and elevation; the battle laid over it is fictional." ],
sources:"FICTIONAL DEMONSTRATION SCENARIO, no historical sources (none exist; it is invented). Real battles you build MUST cite real sources here.",
};
return { meta, ui, factions, intro, outro, flagLegend, geography, units, arrows, fronts, weather, hotspots, storyboard, notes };
})();