@origingame/create-game 0.0.0-stage → 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.
Files changed (581) hide show
  1. package/README.md +57 -2
  2. package/archetypes/README.md +99 -0
  3. package/archetypes/idle/.origin/setup +14 -0
  4. package/archetypes/idle/LICENSES.md +12 -0
  5. package/archetypes/idle/README.md +234 -0
  6. package/archetypes/idle/assets/audio/buy.wav +0 -0
  7. package/archetypes/idle/assets/audio/milestone.wav +0 -0
  8. package/archetypes/idle/assets/audio/nova.wav +0 -0
  9. package/archetypes/idle/assets/audio/orbit.wav +0 -0
  10. package/archetypes/idle/assets/audio/tap.wav +0 -0
  11. package/archetypes/idle/assets/audio/ui-close.ogt +9 -0
  12. package/archetypes/idle/assets/audio/ui-error.ogt +9 -0
  13. package/archetypes/idle/assets/audio/ui-open.ogt +9 -0
  14. package/archetypes/idle/assets/audio/ui-press.ogt +9 -0
  15. package/archetypes/idle/assets/audio/ui-success.ogt +9 -0
  16. package/archetypes/idle/assets/fonts/NotoSansSC-subset.ttf +0 -0
  17. package/archetypes/idle/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
  18. package/archetypes/idle/assets/fonts/OFL.txt +93 -0
  19. package/archetypes/idle/assets/fx/drift.ogt +21 -0
  20. package/archetypes/idle/assets/fx/milestone.ogt +21 -0
  21. package/archetypes/idle/assets/fx/nova.ogt +22 -0
  22. package/archetypes/idle/assets/fx/stars.ogt +20 -0
  23. package/archetypes/idle/assets/fx/tap.ogt +23 -0
  24. package/archetypes/idle/assets/looks/idle.ogt +17 -0
  25. package/archetypes/idle/assets/skins/sparkorb/ChakraPetch-BoldItalic.ttf +0 -0
  26. package/archetypes/idle/assets/skins/sparkorb/ChakraPetch-BoldItalic.ttf.ogt +9 -0
  27. package/archetypes/idle/assets/skins/sparkorb/LICENSES.md +19 -0
  28. package/archetypes/idle/assets/skins/sparkorb/OFL.txt +95 -0
  29. package/archetypes/idle/assets/skins/sparkorb/Orbitron-Medium.ttf +0 -0
  30. package/archetypes/idle/assets/skins/sparkorb/Orbitron-Medium.ttf.ogt +9 -0
  31. package/archetypes/idle/assets/skins/sparkorb/Rajdhani-Bold.ttf +0 -0
  32. package/archetypes/idle/assets/skins/sparkorb/Rajdhani-Bold.ttf.ogt +9 -0
  33. package/archetypes/idle/assets/skins/sparkorb/atlas.png +0 -0
  34. package/archetypes/idle/assets/skins/sparkorb/atlas.png.ogt +7 -0
  35. package/archetypes/idle/assets/skins/sparkorb/icons.png +0 -0
  36. package/archetypes/idle/assets/skins/sparkorb/icons.png.ogt +7 -0
  37. package/archetypes/idle/assets/skins/sparkorb/skin.ogt +113 -0
  38. package/archetypes/idle/assets/sprites/glow.png +0 -0
  39. package/archetypes/idle/assets/sprites/glow.png.ogt +8 -0
  40. package/archetypes/idle/assets/sprites/mote-crystal.png +0 -0
  41. package/archetypes/idle/assets/sprites/mote-crystal.png.ogt +7 -0
  42. package/archetypes/idle/assets/sprites/mote-ember.png +0 -0
  43. package/archetypes/idle/assets/sprites/mote-ember.png.ogt +7 -0
  44. package/archetypes/idle/assets/sprites/mote-star.png +0 -0
  45. package/archetypes/idle/assets/sprites/mote-star.png.ogt +7 -0
  46. package/archetypes/idle/assets/sprites/mote-storm.png +0 -0
  47. package/archetypes/idle/assets/sprites/mote-storm.png.ogt +7 -0
  48. package/archetypes/idle/assets/sprites/orb.png +0 -0
  49. package/archetypes/idle/assets/sprites/orb.png.ogt +7 -0
  50. package/archetypes/idle/assets/sprites/spark.png +0 -0
  51. package/archetypes/idle/assets/sprites/spark.png.ogt +7 -0
  52. package/archetypes/idle/assets/strings/en.ogt +62 -0
  53. package/archetypes/idle/assets/strings/zh-CN.ogt +62 -0
  54. package/archetypes/idle/gitattributes +22 -0
  55. package/archetypes/idle/host.d.ts +46 -0
  56. package/archetypes/idle/package.json +18 -0
  57. package/archetypes/idle/project.ogt +14 -0
  58. package/archetypes/idle/references/metal/card.png +0 -0
  59. package/archetypes/idle/references/metal/orbit.png +0 -0
  60. package/archetypes/idle/references/metal/title.png +0 -0
  61. package/archetypes/idle/src/components.ts +139 -0
  62. package/archetypes/idle/src/main.ts +247 -0
  63. package/archetypes/idle/src/numbers.ts +126 -0
  64. package/archetypes/idle/src/systems.ts +340 -0
  65. package/archetypes/idle/src/ui.ts +412 -0
  66. package/archetypes/idle/tests/away.og.ts +42 -0
  67. package/archetypes/idle/tests/flow.og.ts +57 -0
  68. package/archetypes/idle/tests/frames.og.ts +33 -0
  69. package/archetypes/idle/tests/frames.ts +134 -0
  70. package/archetypes/idle/tests/lib.ts +74 -0
  71. package/archetypes/idle/tests/milestone.og.ts +32 -0
  72. package/archetypes/idle/tests/nova.og.ts +52 -0
  73. package/archetypes/idle/tests/offline.og.ts +60 -0
  74. package/archetypes/idle/tests/pad.og.ts +55 -0
  75. package/archetypes/idle/tests/pause.og.ts +68 -0
  76. package/archetypes/idle/tests/phone.og.ts +50 -0
  77. package/archetypes/idle/tests/replay.og.ts +28 -0
  78. package/archetypes/idle/tools/make-assets.py +448 -0
  79. package/archetypes/idle/tools/oglite.py +285 -0
  80. package/archetypes/idle/tsconfig.json +17 -0
  81. package/archetypes/match3/.origin/setup +14 -0
  82. package/archetypes/match3/LICENSES.md +7 -0
  83. package/archetypes/match3/README.md +205 -0
  84. package/archetypes/match3/assets/audio/cascade.wav +0 -0
  85. package/archetypes/match3/assets/audio/clear.wav +0 -0
  86. package/archetypes/match3/assets/audio/lost.wav +0 -0
  87. package/archetypes/match3/assets/audio/refused.wav +0 -0
  88. package/archetypes/match3/assets/audio/select.wav +0 -0
  89. package/archetypes/match3/assets/audio/swap.wav +0 -0
  90. package/archetypes/match3/assets/audio/won.wav +0 -0
  91. package/archetypes/match3/assets/fonts/OFL.txt +93 -0
  92. package/archetypes/match3/assets/fonts/ui.ttf +0 -0
  93. package/archetypes/match3/assets/fonts/ui.ttf.ogt +11 -0
  94. package/archetypes/match3/assets/scenes/main.ogt +24 -0
  95. package/archetypes/match3/assets/sprites/backdrop.png +0 -0
  96. package/archetypes/match3/assets/sprites/board.ogt +21 -0
  97. package/archetypes/match3/assets/sprites/cells.ogt +7 -0
  98. package/archetypes/match3/assets/sprites/cells.png +0 -0
  99. package/archetypes/match3/assets/sprites/cells.png.ogt +7 -0
  100. package/archetypes/match3/assets/sprites/gems.ogt +75 -0
  101. package/archetypes/match3/assets/sprites/gems.png +0 -0
  102. package/archetypes/match3/assets/sprites/panel.png +0 -0
  103. package/archetypes/match3/assets/sprites/ring.png +0 -0
  104. package/archetypes/match3/gitattributes +22 -0
  105. package/archetypes/match3/host.d.ts +46 -0
  106. package/archetypes/match3/package.json +18 -0
  107. package/archetypes/match3/project.ogt +18 -0
  108. package/archetypes/match3/references/metal/cascade.png +0 -0
  109. package/archetypes/match3/references/metal/clearing.png +0 -0
  110. package/archetypes/match3/references/metal/dealt.png +0 -0
  111. package/archetypes/match3/src/art.ts +54 -0
  112. package/archetypes/match3/src/board.ts +112 -0
  113. package/archetypes/match3/src/components.ts +95 -0
  114. package/archetypes/match3/src/layout.ts +25 -0
  115. package/archetypes/match3/src/main.ts +199 -0
  116. package/archetypes/match3/src/systems.ts +631 -0
  117. package/archetypes/match3/tests/drag.og.ts +31 -0
  118. package/archetypes/match3/tests/endings.og.ts +40 -0
  119. package/archetypes/match3/tests/frames.og.ts +49 -0
  120. package/archetypes/match3/tests/frames.ts +134 -0
  121. package/archetypes/match3/tests/hidpi.og.ts +41 -0
  122. package/archetypes/match3/tests/lib.ts +64 -0
  123. package/archetypes/match3/tests/replay.og.ts +28 -0
  124. package/archetypes/match3/tests/sounds.og.ts +50 -0
  125. package/archetypes/match3/tests/swap.og.ts +67 -0
  126. package/archetypes/match3/tools/make-assets.py +404 -0
  127. package/archetypes/match3/tools/oglite.py +285 -0
  128. package/archetypes/match3/tsconfig.json +17 -0
  129. package/archetypes/rhythm/.origin/setup +14 -0
  130. package/archetypes/rhythm/LICENSES.md +13 -0
  131. package/archetypes/rhythm/README.md +235 -0
  132. package/archetypes/rhythm/assets/audio/bass0.wav +0 -0
  133. package/archetypes/rhythm/assets/audio/bass1.wav +0 -0
  134. package/archetypes/rhythm/assets/audio/bass2.wav +0 -0
  135. package/archetypes/rhythm/assets/audio/bass3.wav +0 -0
  136. package/archetypes/rhythm/assets/audio/chords0.wav +0 -0
  137. package/archetypes/rhythm/assets/audio/chords1.wav +0 -0
  138. package/archetypes/rhythm/assets/audio/chords2.wav +0 -0
  139. package/archetypes/rhythm/assets/audio/chords3.wav +0 -0
  140. package/archetypes/rhythm/assets/audio/clear.wav +0 -0
  141. package/archetypes/rhythm/assets/audio/click.wav +0 -0
  142. package/archetypes/rhythm/assets/audio/drums.wav +0 -0
  143. package/archetypes/rhythm/assets/audio/fail.wav +0 -0
  144. package/archetypes/rhythm/assets/audio/leadA.wav +0 -0
  145. package/archetypes/rhythm/assets/audio/leadB.wav +0 -0
  146. package/archetypes/rhythm/assets/audio/miss.wav +0 -0
  147. package/archetypes/rhythm/assets/audio/tap0.wav +0 -0
  148. package/archetypes/rhythm/assets/audio/tap1.wav +0 -0
  149. package/archetypes/rhythm/assets/audio/tap2.wav +0 -0
  150. package/archetypes/rhythm/assets/audio/ui-close.ogt +9 -0
  151. package/archetypes/rhythm/assets/audio/ui-error.ogt +9 -0
  152. package/archetypes/rhythm/assets/audio/ui-open.ogt +9 -0
  153. package/archetypes/rhythm/assets/audio/ui-press.ogt +9 -0
  154. package/archetypes/rhythm/assets/audio/ui-success.ogt +9 -0
  155. package/archetypes/rhythm/assets/charts/neon-pulse.ogt +919 -0
  156. package/archetypes/rhythm/assets/fonts/NotoSansSC-subset.ttf +0 -0
  157. package/archetypes/rhythm/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
  158. package/archetypes/rhythm/assets/fonts/OFL.txt +93 -0
  159. package/archetypes/rhythm/assets/fx/hit.ogt +22 -0
  160. package/archetypes/rhythm/assets/skins/lanebeat/ChakraPetch-Medium.ttf +0 -0
  161. package/archetypes/rhythm/assets/skins/lanebeat/ChakraPetch-Medium.ttf.ogt +9 -0
  162. package/archetypes/rhythm/assets/skins/lanebeat/JetBrainsMono-Regular.ttf +0 -0
  163. package/archetypes/rhythm/assets/skins/lanebeat/JetBrainsMono-Regular.ttf.ogt +9 -0
  164. package/archetypes/rhythm/assets/skins/lanebeat/LICENSES.md +17 -0
  165. package/archetypes/rhythm/assets/skins/lanebeat/OFL.txt +95 -0
  166. package/archetypes/rhythm/assets/skins/lanebeat/Orbitron-Bold.ttf +0 -0
  167. package/archetypes/rhythm/assets/skins/lanebeat/Orbitron-Bold.ttf.ogt +9 -0
  168. package/archetypes/rhythm/assets/skins/lanebeat/atlas.png +0 -0
  169. package/archetypes/rhythm/assets/skins/lanebeat/atlas.png.ogt +7 -0
  170. package/archetypes/rhythm/assets/skins/lanebeat/icons.png +0 -0
  171. package/archetypes/rhythm/assets/skins/lanebeat/icons.png.ogt +7 -0
  172. package/archetypes/rhythm/assets/skins/lanebeat/skin.ogt +110 -0
  173. package/archetypes/rhythm/assets/sprites/lane.png +0 -0
  174. package/archetypes/rhythm/assets/sprites/lane.png.ogt +7 -0
  175. package/archetypes/rhythm/assets/sprites/note.png +0 -0
  176. package/archetypes/rhythm/assets/sprites/note.png.ogt +7 -0
  177. package/archetypes/rhythm/assets/sprites/ring.png +0 -0
  178. package/archetypes/rhythm/assets/sprites/ring.png.ogt +7 -0
  179. package/archetypes/rhythm/assets/sprites/spark.png +0 -0
  180. package/archetypes/rhythm/assets/sprites/spark.png.ogt +7 -0
  181. package/archetypes/rhythm/assets/strings/en.ogt +61 -0
  182. package/archetypes/rhythm/assets/strings/zh-CN.ogt +61 -0
  183. package/archetypes/rhythm/gitattributes +22 -0
  184. package/archetypes/rhythm/host.d.ts +46 -0
  185. package/archetypes/rhythm/package.json +18 -0
  186. package/archetypes/rhythm/project.ogt +14 -0
  187. package/archetypes/rhythm/references/metal/highway.png +0 -0
  188. package/archetypes/rhythm/references/metal/results.png +0 -0
  189. package/archetypes/rhythm/references/metal/title.png +0 -0
  190. package/archetypes/rhythm/src/components.ts +147 -0
  191. package/archetypes/rhythm/src/main.ts +202 -0
  192. package/archetypes/rhythm/src/systems.ts +490 -0
  193. package/archetypes/rhythm/src/ui.ts +421 -0
  194. package/archetypes/rhythm/tests/band.og.ts +45 -0
  195. package/archetypes/rhythm/tests/calibrate.og.ts +49 -0
  196. package/archetypes/rhythm/tests/clear.og.ts +51 -0
  197. package/archetypes/rhythm/tests/fail.og.ts +40 -0
  198. package/archetypes/rhythm/tests/flow.og.ts +54 -0
  199. package/archetypes/rhythm/tests/frames.og.ts +35 -0
  200. package/archetypes/rhythm/tests/frames.ts +134 -0
  201. package/archetypes/rhythm/tests/lib.ts +123 -0
  202. package/archetypes/rhythm/tests/pad.og.ts +41 -0
  203. package/archetypes/rhythm/tests/pause.og.ts +77 -0
  204. package/archetypes/rhythm/tests/phone.og.ts +44 -0
  205. package/archetypes/rhythm/tests/replay.og.ts +27 -0
  206. package/archetypes/rhythm/tests/timing.og.ts +37 -0
  207. package/archetypes/rhythm/tools/make-assets.py +383 -0
  208. package/archetypes/rhythm/tools/oglite.py +285 -0
  209. package/archetypes/rhythm/tsconfig.json +17 -0
  210. package/archetypes/roguelike/.origin/setup +14 -0
  211. package/archetypes/roguelike/LICENSES.md +14 -0
  212. package/archetypes/roguelike/README.md +256 -0
  213. package/archetypes/roguelike/assets/ai/foe.ogt +28 -0
  214. package/archetypes/roguelike/assets/ai/guardian.ogt +26 -0
  215. package/archetypes/roguelike/assets/audio/bump.wav +0 -0
  216. package/archetypes/roguelike/assets/audio/drink.wav +0 -0
  217. package/archetypes/roguelike/assets/audio/fall.wav +0 -0
  218. package/archetypes/roguelike/assets/audio/hit.wav +0 -0
  219. package/archetypes/roguelike/assets/audio/hurt.wav +0 -0
  220. package/archetypes/roguelike/assets/audio/item.wav +0 -0
  221. package/archetypes/roguelike/assets/audio/kill.wav +0 -0
  222. package/archetypes/roguelike/assets/audio/pickup.wav +0 -0
  223. package/archetypes/roguelike/assets/audio/roar.wav +0 -0
  224. package/archetypes/roguelike/assets/audio/stairs.wav +0 -0
  225. package/archetypes/roguelike/assets/audio/step.ogt +9 -0
  226. package/archetypes/roguelike/assets/audio/telegraph.wav +0 -0
  227. package/archetypes/roguelike/assets/audio/tomb.wav +0 -0
  228. package/archetypes/roguelike/assets/audio/ui-close.ogt +9 -0
  229. package/archetypes/roguelike/assets/audio/ui-error.ogt +9 -0
  230. package/archetypes/roguelike/assets/audio/ui-open.ogt +9 -0
  231. package/archetypes/roguelike/assets/audio/ui-press.ogt +9 -0
  232. package/archetypes/roguelike/assets/audio/ui-success.ogt +9 -0
  233. package/archetypes/roguelike/assets/audio/won.wav +0 -0
  234. package/archetypes/roguelike/assets/fonts/NotoSansSC-subset.ttf +0 -0
  235. package/archetypes/roguelike/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
  236. package/archetypes/roguelike/assets/fonts/OFL.txt +93 -0
  237. package/archetypes/roguelike/assets/maps/dive.ogt +106 -0
  238. package/archetypes/roguelike/assets/skins/lampdive/DotGothic16-Regular.ttf +0 -0
  239. package/archetypes/roguelike/assets/skins/lampdive/DotGothic16-Regular.ttf.ogt +9 -0
  240. package/archetypes/roguelike/assets/skins/lampdive/LICENSES.md +16 -0
  241. package/archetypes/roguelike/assets/skins/lampdive/OFL.txt +93 -0
  242. package/archetypes/roguelike/assets/skins/lampdive/atlas.png +0 -0
  243. package/archetypes/roguelike/assets/skins/lampdive/atlas.png.ogt +7 -0
  244. package/archetypes/roguelike/assets/skins/lampdive/icons.png +0 -0
  245. package/archetypes/roguelike/assets/skins/lampdive/icons.png.ogt +7 -0
  246. package/archetypes/roguelike/assets/skins/lampdive/skin.ogt +115 -0
  247. package/archetypes/roguelike/assets/sprites/dive.ogt +50 -0
  248. package/archetypes/roguelike/assets/sprites/dive.png +0 -0
  249. package/archetypes/roguelike/assets/sprites/dive.png.ogt +7 -0
  250. package/archetypes/roguelike/assets/sprites/glow.png +0 -0
  251. package/archetypes/roguelike/assets/sprites/glow.png.ogt +7 -0
  252. package/archetypes/roguelike/assets/strings/en.ogt +57 -0
  253. package/archetypes/roguelike/assets/strings/zh-CN.ogt +57 -0
  254. package/archetypes/roguelike/assets/tiles/tomb.ogt +31 -0
  255. package/archetypes/roguelike/assets/tiles/tomb.png +0 -0
  256. package/archetypes/roguelike/assets/tiles/tomb.png.ogt +7 -0
  257. package/archetypes/roguelike/gitattributes +22 -0
  258. package/archetypes/roguelike/host.d.ts +46 -0
  259. package/archetypes/roguelike/package.json +18 -0
  260. package/archetypes/roguelike/project.ogt +14 -0
  261. package/archetypes/roguelike/references/metal/dive.png +0 -0
  262. package/archetypes/roguelike/references/metal/over.png +0 -0
  263. package/archetypes/roguelike/references/metal/title.png +0 -0
  264. package/archetypes/roguelike/src/art.ts +23 -0
  265. package/archetypes/roguelike/src/components.ts +169 -0
  266. package/archetypes/roguelike/src/dive.ts +144 -0
  267. package/archetypes/roguelike/src/foes.ts +174 -0
  268. package/archetypes/roguelike/src/main.ts +258 -0
  269. package/archetypes/roguelike/src/systems.ts +620 -0
  270. package/archetypes/roguelike/src/ui.ts +350 -0
  271. package/archetypes/roguelike/tests/flow.og.ts +54 -0
  272. package/archetypes/roguelike/tests/foes.og.ts +45 -0
  273. package/archetypes/roguelike/tests/frames.og.ts +32 -0
  274. package/archetypes/roguelike/tests/frames.ts +134 -0
  275. package/archetypes/roguelike/tests/lib.ts +83 -0
  276. package/archetypes/roguelike/tests/lose.og.ts +44 -0
  277. package/archetypes/roguelike/tests/pad.og.ts +54 -0
  278. package/archetypes/roguelike/tests/pause.og.ts +59 -0
  279. package/archetypes/roguelike/tests/phone.og.ts +54 -0
  280. package/archetypes/roguelike/tests/replay.og.ts +24 -0
  281. package/archetypes/roguelike/tests/win.og.ts +60 -0
  282. package/archetypes/roguelike/tools/make-assets.py +518 -0
  283. package/archetypes/roguelike/tools/oglite.py +285 -0
  284. package/archetypes/roguelike/tsconfig.json +17 -0
  285. package/archetypes/runner/.origin/setup +14 -0
  286. package/archetypes/runner/LICENSES.md +10 -0
  287. package/archetypes/runner/README.md +225 -0
  288. package/archetypes/runner/assets/audio/coin.wav +0 -0
  289. package/archetypes/runner/assets/audio/crash.wav +0 -0
  290. package/archetypes/runner/assets/audio/hold.ogt +9 -0
  291. package/archetypes/runner/assets/audio/jump.wav +0 -0
  292. package/archetypes/runner/assets/audio/start.wav +0 -0
  293. package/archetypes/runner/assets/fonts/OFL.txt +93 -0
  294. package/archetypes/runner/assets/fonts/ui.ttf +0 -0
  295. package/archetypes/runner/assets/fonts/ui.ttf.ogt +11 -0
  296. package/archetypes/runner/assets/maps/far.ogt +25 -0
  297. package/archetypes/runner/assets/maps/near.ogt +25 -0
  298. package/archetypes/runner/assets/maps/roofs.ogt +19 -0
  299. package/archetypes/runner/assets/scenes/main.ogt +35 -0
  300. package/archetypes/runner/assets/sprites/coin.ogt +11 -0
  301. package/archetypes/runner/assets/sprites/coin.png +0 -0
  302. package/archetypes/runner/assets/sprites/coin.png.ogt +7 -0
  303. package/archetypes/runner/assets/sprites/courier.ogt +32 -0
  304. package/archetypes/runner/assets/sprites/courier.png +0 -0
  305. package/archetypes/runner/assets/sprites/courier.png.ogt +7 -0
  306. package/archetypes/runner/assets/sprites/props.ogt +21 -0
  307. package/archetypes/runner/assets/sprites/props.png +0 -0
  308. package/archetypes/runner/assets/sprites/props.png.ogt +7 -0
  309. package/archetypes/runner/assets/sprites/sky.png +0 -0
  310. package/archetypes/runner/assets/sprites/sky.png.ogt +7 -0
  311. package/archetypes/runner/assets/tiles/city.ogt +18 -0
  312. package/archetypes/runner/assets/tiles/city.png +0 -0
  313. package/archetypes/runner/assets/tiles/city.png.ogt +7 -0
  314. package/archetypes/runner/gitattributes +22 -0
  315. package/archetypes/runner/host.d.ts +46 -0
  316. package/archetypes/runner/package.json +18 -0
  317. package/archetypes/runner/project.ogt +18 -0
  318. package/archetypes/runner/references/metal/frames-coin.png +0 -0
  319. package/archetypes/runner/references/metal/frames-crash.png +0 -0
  320. package/archetypes/runner/references/metal/frames-title.png +0 -0
  321. package/archetypes/runner/src/art.ts +57 -0
  322. package/archetypes/runner/src/components.ts +94 -0
  323. package/archetypes/runner/src/main.ts +241 -0
  324. package/archetypes/runner/src/systems.ts +553 -0
  325. package/archetypes/runner/tests/coins.og.ts +30 -0
  326. package/archetypes/runner/tests/flow.og.ts +72 -0
  327. package/archetypes/runner/tests/frames.og.ts +37 -0
  328. package/archetypes/runner/tests/frames.ts +134 -0
  329. package/archetypes/runner/tests/jump.og.ts +44 -0
  330. package/archetypes/runner/tests/lib.ts +42 -0
  331. package/archetypes/runner/tests/records.og.ts +43 -0
  332. package/archetypes/runner/tests/replay.og.ts +36 -0
  333. package/archetypes/runner/tests/sounds.og.ts +43 -0
  334. package/archetypes/runner/tests/tune.og.ts +36 -0
  335. package/archetypes/runner/tools/make-assets.py +603 -0
  336. package/archetypes/runner/tools/oglite.py +285 -0
  337. package/archetypes/runner/tsconfig.json +17 -0
  338. package/archetypes/third-person/.origin/setup +14 -0
  339. package/archetypes/third-person/LICENSES.md +23 -0
  340. package/archetypes/third-person/README.md +249 -0
  341. package/archetypes/third-person/assets/ai/sentinel-east.ogt +69 -0
  342. package/archetypes/third-person/assets/ai/sentinel-north.ogt +69 -0
  343. package/archetypes/third-person/assets/ai/sentinel-west.ogt +69 -0
  344. package/archetypes/third-person/assets/anims/humanoid-clips.glb +0 -0
  345. package/archetypes/third-person/assets/audio/alarm.wav +0 -0
  346. package/archetypes/third-person/assets/audio/dawn.wav +0 -0
  347. package/archetypes/third-person/assets/audio/grab.wav +0 -0
  348. package/archetypes/third-person/assets/audio/ignite.wav +0 -0
  349. package/archetypes/third-person/assets/audio/jump.wav +0 -0
  350. package/archetypes/third-person/assets/audio/night.wav +0 -0
  351. package/archetypes/third-person/assets/audio/splash.wav +0 -0
  352. package/archetypes/third-person/assets/audio/step.ogt +9 -0
  353. package/archetypes/third-person/assets/audio/ui-close.ogt +9 -0
  354. package/archetypes/third-person/assets/audio/ui-error.ogt +9 -0
  355. package/archetypes/third-person/assets/audio/ui-open.ogt +9 -0
  356. package/archetypes/third-person/assets/audio/ui-press.ogt +9 -0
  357. package/archetypes/third-person/assets/audio/ui-success.ogt +9 -0
  358. package/archetypes/third-person/assets/audio/vale.wav +0 -0
  359. package/archetypes/third-person/assets/fonts/NotoSansSC-subset.ttf +0 -0
  360. package/archetypes/third-person/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
  361. package/archetypes/third-person/assets/fonts/OFL.txt +93 -0
  362. package/archetypes/third-person/assets/fx/burst.ogt +25 -0
  363. package/archetypes/third-person/assets/fx/fire.ogt +24 -0
  364. package/archetypes/third-person/assets/fx/smoke.ogt +24 -0
  365. package/archetypes/third-person/assets/fx/splash.ogt +24 -0
  366. package/archetypes/third-person/assets/luts/teal-orange.cube +4917 -0
  367. package/archetypes/third-person/assets/models/stout.glb +0 -0
  368. package/archetypes/third-person/assets/models/strider.glb +0 -0
  369. package/archetypes/third-person/assets/models/strider.glb.ogt +9 -0
  370. package/archetypes/third-person/assets/nav/vale.ogt +43 -0
  371. package/archetypes/third-person/assets/rigs/strider.ogt +6 -0
  372. package/archetypes/third-person/assets/skins/ember/Cinzel-Bold.ttf +0 -0
  373. package/archetypes/third-person/assets/skins/ember/Cinzel-Bold.ttf.ogt +9 -0
  374. package/archetypes/third-person/assets/skins/ember/LICENSES.md +13 -0
  375. package/archetypes/third-person/assets/skins/ember/Newsreader-Medium.ttf +0 -0
  376. package/archetypes/third-person/assets/skins/ember/Newsreader-Medium.ttf.ogt +9 -0
  377. package/archetypes/third-person/assets/skins/ember/OFL.txt +94 -0
  378. package/archetypes/third-person/assets/skins/ember/atlas.png +0 -0
  379. package/archetypes/third-person/assets/skins/ember/atlas.png.ogt +7 -0
  380. package/archetypes/third-person/assets/skins/ember/icons.png +0 -0
  381. package/archetypes/third-person/assets/skins/ember/icons.png.ogt +7 -0
  382. package/archetypes/third-person/assets/skins/ember/skin.ogt +109 -0
  383. package/archetypes/third-person/assets/strings/en.ogt +47 -0
  384. package/archetypes/third-person/assets/strings/zh-CN.ogt +47 -0
  385. package/archetypes/third-person/assets/terrain/vale-control.png +0 -0
  386. package/archetypes/third-person/assets/terrain/vale.ogt +42 -0
  387. package/archetypes/third-person/assets/terrain/vale.png +0 -0
  388. package/archetypes/third-person/assets/textures/decals.png +0 -0
  389. package/archetypes/third-person/assets/textures/flame.png +0 -0
  390. package/archetypes/third-person/assets/textures/smoke.png +0 -0
  391. package/archetypes/third-person/assets/textures/spark.png +0 -0
  392. package/archetypes/third-person/assets/textures/terrain-grass.png +0 -0
  393. package/archetypes/third-person/assets/textures/terrain-path.png +0 -0
  394. package/archetypes/third-person/assets/textures/terrain-rock.png +0 -0
  395. package/archetypes/third-person/assets/textures/terrain-sand.png +0 -0
  396. package/archetypes/third-person/gitattributes +22 -0
  397. package/archetypes/third-person/host.d.ts +46 -0
  398. package/archetypes/third-person/package.json +18 -0
  399. package/archetypes/third-person/project.ogt +14 -0
  400. package/archetypes/third-person/references/metal/beacon.png +0 -0
  401. package/archetypes/third-person/references/metal/dawn.png +0 -0
  402. package/archetypes/third-person/references/metal/title.png +0 -0
  403. package/archetypes/third-person/references/webgl2/beacon.png +0 -0
  404. package/archetypes/third-person/src/anim.ts +87 -0
  405. package/archetypes/third-person/src/beacons.ts +80 -0
  406. package/archetypes/third-person/src/components.ts +148 -0
  407. package/archetypes/third-person/src/hero.ts +293 -0
  408. package/archetypes/third-person/src/main.ts +164 -0
  409. package/archetypes/third-person/src/sentinels.ts +159 -0
  410. package/archetypes/third-person/src/sound.ts +66 -0
  411. package/archetypes/third-person/src/ui.ts +451 -0
  412. package/archetypes/third-person/src/world.ts +212 -0
  413. package/archetypes/third-person/tests/flow.og.ts +70 -0
  414. package/archetypes/third-person/tests/frames.og.ts +35 -0
  415. package/archetypes/third-person/tests/frames.ts +134 -0
  416. package/archetypes/third-person/tests/hitstop.og.ts +26 -0
  417. package/archetypes/third-person/tests/lib.ts +87 -0
  418. package/archetypes/third-person/tests/lose.og.ts +44 -0
  419. package/archetypes/third-person/tests/pause.og.ts +64 -0
  420. package/archetypes/third-person/tests/phone.og.ts +65 -0
  421. package/archetypes/third-person/tests/replay.og.ts +32 -0
  422. package/archetypes/third-person/tests/restart.og.ts +28 -0
  423. package/archetypes/third-person/tests/sentinels.og.ts +48 -0
  424. package/archetypes/third-person/tests/win.og.ts +62 -0
  425. package/archetypes/third-person/tools/make-assets.py +353 -0
  426. package/archetypes/third-person/tools/oglite.py +285 -0
  427. package/archetypes/third-person/tsconfig.json +17 -0
  428. package/archetypes/topdown/.origin/setup +14 -0
  429. package/archetypes/topdown/LICENSES.md +10 -0
  430. package/archetypes/topdown/README.md +235 -0
  431. package/archetypes/topdown/assets/ai/slime.ogt +49 -0
  432. package/archetypes/topdown/assets/audio/coin.wav +0 -0
  433. package/archetypes/topdown/assets/audio/door.wav +0 -0
  434. package/archetypes/topdown/assets/audio/hit.wav +0 -0
  435. package/archetypes/topdown/assets/audio/hurt.wav +0 -0
  436. package/archetypes/topdown/assets/audio/key.wav +0 -0
  437. package/archetypes/topdown/assets/audio/step.ogt +9 -0
  438. package/archetypes/topdown/assets/fonts/OFL.txt +93 -0
  439. package/archetypes/topdown/assets/fonts/ui.ttf +0 -0
  440. package/archetypes/topdown/assets/fonts/ui.ttf.ogt +9 -0
  441. package/archetypes/topdown/assets/maps/tomb.tmj +2183 -0
  442. package/archetypes/topdown/assets/sprites/hero.ogt +58 -0
  443. package/archetypes/topdown/assets/sprites/hero.png +0 -0
  444. package/archetypes/topdown/assets/sprites/hero.png.ogt +7 -0
  445. package/archetypes/topdown/assets/sprites/items.ogt +15 -0
  446. package/archetypes/topdown/assets/sprites/items.png +0 -0
  447. package/archetypes/topdown/assets/sprites/items.png.ogt +7 -0
  448. package/archetypes/topdown/assets/sprites/slime.ogt +17 -0
  449. package/archetypes/topdown/assets/sprites/slime.png +0 -0
  450. package/archetypes/topdown/assets/sprites/slime.png.ogt +7 -0
  451. package/archetypes/topdown/assets/tiles/dungeon.ogt +65 -0
  452. package/archetypes/topdown/assets/tiles/dungeon.png +0 -0
  453. package/archetypes/topdown/assets/tiles/dungeon.png.ogt +7 -0
  454. package/archetypes/topdown/gitattributes +22 -0
  455. package/archetypes/topdown/host.d.ts +46 -0
  456. package/archetypes/topdown/package.json +18 -0
  457. package/archetypes/topdown/project.ogt +14 -0
  458. package/archetypes/topdown/references/metal/crit.png +0 -0
  459. package/archetypes/topdown/references/metal/dash.png +0 -0
  460. package/archetypes/topdown/references/metal/east.png +0 -0
  461. package/archetypes/topdown/references/metal/start.png +0 -0
  462. package/archetypes/topdown/src/art.ts +48 -0
  463. package/archetypes/topdown/src/components.ts +128 -0
  464. package/archetypes/topdown/src/main.ts +275 -0
  465. package/archetypes/topdown/src/systems.ts +503 -0
  466. package/archetypes/topdown/tests/ai.og.ts +64 -0
  467. package/archetypes/topdown/tests/combat.og.ts +72 -0
  468. package/archetypes/topdown/tests/door.og.ts +62 -0
  469. package/archetypes/topdown/tests/flee.og.ts +49 -0
  470. package/archetypes/topdown/tests/frames.og.ts +45 -0
  471. package/archetypes/topdown/tests/frames.ts +134 -0
  472. package/archetypes/topdown/tests/lib.ts +71 -0
  473. package/archetypes/topdown/tests/replay.og.ts +40 -0
  474. package/archetypes/topdown/tests/walk.og.ts +46 -0
  475. package/archetypes/topdown/tools/make-assets.py +623 -0
  476. package/archetypes/topdown/tools/oglite.py +285 -0
  477. package/archetypes/topdown/tsconfig.json +17 -0
  478. package/archetypes/tower-defense/.origin/setup +14 -0
  479. package/archetypes/tower-defense/LICENSES.md +15 -0
  480. package/archetypes/tower-defense/README.md +240 -0
  481. package/archetypes/tower-defense/assets/ai/plant.ogt +16 -0
  482. package/archetypes/tower-defense/assets/audio/clear.wav +0 -0
  483. package/archetypes/tower-defense/assets/audio/frost.wav +0 -0
  484. package/archetypes/tower-defense/assets/audio/leak.wav +0 -0
  485. package/archetypes/tower-defense/assets/audio/lost.wav +0 -0
  486. package/archetypes/tower-defense/assets/audio/night.wav +0 -0
  487. package/archetypes/tower-defense/assets/audio/plant.wav +0 -0
  488. package/archetypes/tower-defense/assets/audio/pop.wav +0 -0
  489. package/archetypes/tower-defense/assets/audio/thorn.wav +0 -0
  490. package/archetypes/tower-defense/assets/audio/ui-close.ogt +9 -0
  491. package/archetypes/tower-defense/assets/audio/ui-error.ogt +9 -0
  492. package/archetypes/tower-defense/assets/audio/ui-open.ogt +9 -0
  493. package/archetypes/tower-defense/assets/audio/ui-press.ogt +9 -0
  494. package/archetypes/tower-defense/assets/audio/ui-success.ogt +9 -0
  495. package/archetypes/tower-defense/assets/audio/wave.wav +0 -0
  496. package/archetypes/tower-defense/assets/audio/won.wav +0 -0
  497. package/archetypes/tower-defense/assets/fonts/NotoSansSC-subset.ttf +0 -0
  498. package/archetypes/tower-defense/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
  499. package/archetypes/tower-defense/assets/fonts/OFL.txt +93 -0
  500. package/archetypes/tower-defense/assets/fx/fireflies.ogt +21 -0
  501. package/archetypes/tower-defense/assets/fx/pop.ogt +21 -0
  502. package/archetypes/tower-defense/assets/maps/garden.ogt +91 -0
  503. package/archetypes/tower-defense/assets/skins/pathguard/Fredoka-SemiBold.ttf +0 -0
  504. package/archetypes/tower-defense/assets/skins/pathguard/Fredoka-SemiBold.ttf.ogt +9 -0
  505. package/archetypes/tower-defense/assets/skins/pathguard/LICENSES.md +13 -0
  506. package/archetypes/tower-defense/assets/skins/pathguard/LilitaOne-Regular.ttf +0 -0
  507. package/archetypes/tower-defense/assets/skins/pathguard/LilitaOne-Regular.ttf.ogt +9 -0
  508. package/archetypes/tower-defense/assets/skins/pathguard/OFL.txt +94 -0
  509. package/archetypes/tower-defense/assets/skins/pathguard/atlas.png +0 -0
  510. package/archetypes/tower-defense/assets/skins/pathguard/atlas.png.ogt +7 -0
  511. package/archetypes/tower-defense/assets/skins/pathguard/icons.png +0 -0
  512. package/archetypes/tower-defense/assets/skins/pathguard/icons.png.ogt +7 -0
  513. package/archetypes/tower-defense/assets/skins/pathguard/skin.ogt +111 -0
  514. package/archetypes/tower-defense/assets/sprites/garden.ogt +66 -0
  515. package/archetypes/tower-defense/assets/sprites/garden.png +0 -0
  516. package/archetypes/tower-defense/assets/sprites/garden.png.ogt +7 -0
  517. package/archetypes/tower-defense/assets/sprites/glow.png +0 -0
  518. package/archetypes/tower-defense/assets/sprites/glow.png.ogt +7 -0
  519. package/archetypes/tower-defense/assets/sprites/ring.png +0 -0
  520. package/archetypes/tower-defense/assets/sprites/ring.png.ogt +7 -0
  521. package/archetypes/tower-defense/assets/sprites/spark.png +0 -0
  522. package/archetypes/tower-defense/assets/sprites/spark.png.ogt +7 -0
  523. package/archetypes/tower-defense/assets/strings/en.ogt +47 -0
  524. package/archetypes/tower-defense/assets/strings/zh-CN.ogt +47 -0
  525. package/archetypes/tower-defense/assets/tiles/garden.ogt +10 -0
  526. package/archetypes/tower-defense/assets/tiles/garden.png +0 -0
  527. package/archetypes/tower-defense/assets/tiles/garden.png.ogt +7 -0
  528. package/archetypes/tower-defense/gitattributes +22 -0
  529. package/archetypes/tower-defense/host.d.ts +46 -0
  530. package/archetypes/tower-defense/package.json +18 -0
  531. package/archetypes/tower-defense/project.ogt +14 -0
  532. package/archetypes/tower-defense/references/metal/end.png +0 -0
  533. package/archetypes/tower-defense/references/metal/title.png +0 -0
  534. package/archetypes/tower-defense/references/metal/wave.png +0 -0
  535. package/archetypes/tower-defense/src/art.ts +24 -0
  536. package/archetypes/tower-defense/src/components.ts +156 -0
  537. package/archetypes/tower-defense/src/main.ts +253 -0
  538. package/archetypes/tower-defense/src/systems.ts +658 -0
  539. package/archetypes/tower-defense/src/ui.ts +382 -0
  540. package/archetypes/tower-defense/tests/flow.og.ts +56 -0
  541. package/archetypes/tower-defense/tests/frames.og.ts +31 -0
  542. package/archetypes/tower-defense/tests/frames.ts +134 -0
  543. package/archetypes/tower-defense/tests/lib.ts +81 -0
  544. package/archetypes/tower-defense/tests/lose.og.ts +40 -0
  545. package/archetypes/tower-defense/tests/maze.og.ts +53 -0
  546. package/archetypes/tower-defense/tests/pad.og.ts +41 -0
  547. package/archetypes/tower-defense/tests/pause.og.ts +59 -0
  548. package/archetypes/tower-defense/tests/phone.og.ts +49 -0
  549. package/archetypes/tower-defense/tests/replay.og.ts +28 -0
  550. package/archetypes/tower-defense/tests/win.og.ts +58 -0
  551. package/archetypes/tower-defense/tools/make-assets.py +640 -0
  552. package/archetypes/tower-defense/tools/oglite.py +285 -0
  553. package/archetypes/tower-defense/tsconfig.json +17 -0
  554. package/bin/create.ts +496 -0
  555. package/looks/catalogue.json +1871 -0
  556. package/package.json +31 -4
  557. package/template/.origin/setup +14 -0
  558. package/template/LICENSES.md +23 -0
  559. package/template/README.md +37 -0
  560. package/template/assets/ai/guard.ogt +48 -0
  561. package/template/assets/audio/blip.wav +0 -0
  562. package/template/assets/audio/click.ogt +9 -0
  563. package/template/assets/fonts/NotoSansSC-Regular-subset.ttf +0 -0
  564. package/template/assets/fonts/NotoSansSC-Regular-subset.ttf.ogt +12 -0
  565. package/template/assets/fonts/OFL.txt +93 -0
  566. package/template/assets/looks/origin-game.ogt +12 -0
  567. package/template/assets/models/dropship.glb +0 -0
  568. package/template/assets/models/walker.glb +0 -0
  569. package/template/assets/nav/yard.ogt +27 -0
  570. package/template/assets/scenes/main.ogt +34 -0
  571. package/template/assets/strings/en.ogt +14 -0
  572. package/template/assets/textures/stone.png +0 -0
  573. package/template/assets/textures/stone_n.png +0 -0
  574. package/template/assets/textures/stone_n.png.ogt +7 -0
  575. package/template/gitattributes +22 -0
  576. package/template/package.json +18 -0
  577. package/template/project.ogt +25 -0
  578. package/template/src/main.ts +246 -0
  579. package/template/tests/guard.og.ts +67 -0
  580. package/template/tests/smoke.og.ts +43 -0
  581. package/template/tsconfig.json +17 -0
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "origin-idle",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "og dev .",
8
+ "start": "og run .",
9
+ "build": "og build .",
10
+ "publish-build": "og build . --publish",
11
+ "cook": "og cook .",
12
+ "check": "og check .",
13
+ "test": "og test ."
14
+ },
15
+ "dependencies": {
16
+ "@origingame/engine": "0.1.0"
17
+ }
18
+ }
@@ -0,0 +1,14 @@
1
+ type project
2
+ version 1
3
+ ---
4
+ name "Spark Orb"
5
+ id "idle"
6
+ engine "0.1.0"
7
+ entry "src/main.ts"
8
+ profile "2d"
9
+ tick 60
10
+ seed 1
11
+ publish {
12
+ probe player
13
+ out "dist"
14
+ }
@@ -0,0 +1,139 @@
1
+ // Every piece of Spark Orb's state lives in these reflected types: dumps,
2
+ // the probe, Tune and the command channel's `get` and `set` read and write
3
+ // them by name.
4
+ //
5
+ // The run and the save (Game), the knobs (Tuning) and the player's
6
+ // settings (Prefs) are resources. The drawn things are rows spawned in
7
+ // `start`: the orb, its glow, the motes that circle it (one pool per
8
+ // generator) and one voice per sound.
9
+
10
+ import { bool, defineComponent, defineResource, f32, f64, i32, u32 } from "@origingame/engine";
11
+
12
+ /** The screen the game is on. */
13
+ export const Phase = { Title: 0, Play: 1, Nova: 2 } as const;
14
+
15
+ /** The generators, in order: what each is called in the string tables and drawn with. */
16
+ export const GENERATORS = ["ember", "storm", "crystal", "star"] as const;
17
+
18
+ /** Motes drawn per generator at most (one per generator owned). */
19
+ export const MOTES = 12;
20
+
21
+ /** Sound requests: bits of Game.sfx that the Voices system plays once each. */
22
+ export const Sound = { Tap: 1, Buy: 2, Milestone: 4, Nova: 8, Welcome: 16, Move: 32 } as const;
23
+
24
+ /** The run, the save and the effects' bookkeeping. */
25
+ export const Game = defineResource("Game", {
26
+ phase: u32(Phase.Title, { doc: "Phase.* of src/components.ts." }),
27
+ leftTitle: bool(false, { doc: "The player has left the title the game opened on: from then on the title enters with the skin's entrance (the opening one is built settled, og.ui.mainMenu's instant: the web draws it behind the play gate)." }),
28
+ paused: bool(false),
29
+ settingsOpen: bool(false),
30
+ held: bool(false, { doc: "The time scale is held at 0 (paused, in the settings or a dialog)." }),
31
+ confirmNova: bool(false, { doc: "The Supernova dialog is open." }),
32
+ welcome: bool(false, { doc: "The welcome-back dialog is open." }),
33
+ sparks: f64(0, { doc: "The currency." }),
34
+ runEarned: f64(0, { doc: "Sparks made this run (since the last supernova): the supernova's stardust grows with it." }),
35
+ lifetime: f64(0, { doc: "Sparks made on this save, every run." }),
36
+ owned0: u32(0, { doc: "Embers owned." }),
37
+ owned1: u32(0, { doc: "Storms owned." }),
38
+ owned2: u32(0, { doc: "Crystals owned." }),
39
+ owned3: u32(0, { doc: "Stars owned." }),
40
+ dust: u32(0, { doc: "Stardust: +10 % to everything each (Tuning.dustBonus)." }),
41
+ novas: u32(0, { doc: "Supernovas on this save." }),
42
+ lastGain: u32(0, { doc: "Stardust the last supernova gave." }),
43
+ lastRun: f64(0, { doc: "Sparks the last supernova's run made." }),
44
+ lastRunTicks: u32(0, { unit: "ticks" }),
45
+ runTicks: u32(0, { unit: "ticks", doc: "Ticks played this run." }),
46
+ rate: f64(0, { unit: "sparks/s", doc: "Sparks a second now (the generators, the milestones, the stardust)." }),
47
+ tapValue: f64(1, { doc: "Sparks a tap makes now." }),
48
+ taps: u32(0),
49
+ streak: u32(0, { doc: "Taps in a quick run (each within 20 ticks of the last): the chime climbs." }),
50
+ lastTapTick: i32(-100, { unit: "ticks" }),
51
+ buys: u32(0),
52
+ boughtSlot: i32(-1, { doc: "The generator bought last (its card pops)." }),
53
+ boughtTick: i32(-1, { unit: "ticks" }),
54
+ refused: u32(0, { doc: "Purchases refused for want of sparks." }),
55
+ refusedSlot: i32(-1, { doc: "The generator whose purchase was refused last (its card shakes)." }),
56
+ refusedTick: i32(-1, { unit: "ticks" }),
57
+ milestoneSlot: i32(-1, { doc: "The generator that reached a milestone last (its card bursts)." }),
58
+ milestoneTick: i32(-1, { unit: "ticks" }),
59
+ selected: u32(0, { doc: "The generator the keys and the pad buy (0-3)." }),
60
+ playTick: i32(-1, { unit: "ticks", doc: "The tick play began (from the title or a new run): the key or button that began it is not also a tap or a purchase." }),
61
+ pendingTap: bool(false, { doc: "A tap asked for by the HUD this tick (the Orb system makes it)." }),
62
+ pendingBuy: i32(-1, { doc: "A purchase asked for by the HUD this tick (the Economy system makes it)." }),
63
+ pendingNova: bool(false, { doc: "The supernova confirmed this tick (the Economy system makes it)." }),
64
+ away: f64(0, { unit: "s", doc: "Seconds the game was closed: the save's answer's time (og.platform's host clock) less the time the save was written; relaunch:<s> sets it for a test." }),
65
+ offline: f64(0, { doc: "Sparks the orb made while the game was closed (shown on the welcome-back dialog)." }),
66
+ saveRequest: u32(0, { doc: "The store request reading `orb`." }),
67
+ saveRevision: u32(0, { doc: "The revision `orb` was read or written at." }),
68
+ saveWrite: u32(0, { doc: "The store request writing `orb`." }),
69
+ saveMerge: bool(false, { doc: "A write was refused as stale: the save is read again, merged and written." }),
70
+ saveConflicts: u32(0),
71
+ saves: u32(0, { doc: "Saves written." }),
72
+ loaded: bool(false, { doc: "The save was read (or found empty) on launch." }),
73
+ sinceSave: u32(0, { unit: "ticks" }),
74
+ saveNow: bool(false, { doc: "Write the save this tick (after a supernova, on pause, on Quit)." }),
75
+ burstKind: u32(0, { doc: "The burst asked for this tick (BURST.* of src/systems.ts)." }),
76
+ burstX: f32(0, { unit: "m" }),
77
+ burstY: f32(0, { unit: "m" }),
78
+ burstTick: i32(-1, { unit: "ticks", doc: "The tick a burst was asked for (the Bursts system fires it the same tick)." }),
79
+ sfx: u32(0),
80
+ viewW: f32(0, { unit: "cssPx" }),
81
+ viewH: f32(0, { unit: "cssPx" }),
82
+ orbX: f32(0, { unit: "m", doc: "The orb's centre (it moves up on a phone)." }),
83
+ orbY: f32(0, { unit: "m" }),
84
+ language: u32(0, { doc: "Prefs.language, mirrored for the facts." }),
85
+ });
86
+
87
+ /** The knobs. Tune reads the tunable fields; `set:Tuning.<field>=<value>` writes them. */
88
+ export const Tuning = defineResource("Tuning", {
89
+ emberRate: f32(0.5, { min: 0, max: 1000, tunable: true, unit: "sparks/s", label: "Ember makes" }),
90
+ emberCost: f32(15, { min: 1, max: 1e6, tunable: true, label: "Ember costs" }),
91
+ stormRate: f32(4, { min: 0, max: 1e4, tunable: true, unit: "sparks/s", label: "Storm makes" }),
92
+ stormCost: f32(110, { min: 1, max: 1e7, tunable: true, label: "Storm costs" }),
93
+ crystalRate: f32(26, { min: 0, max: 1e5, tunable: true, unit: "sparks/s", label: "Crystal makes" }),
94
+ crystalCost: f32(1200, { min: 1, max: 1e8, tunable: true, label: "Crystal costs" }),
95
+ starRate: f32(160, { min: 0, max: 1e6, tunable: true, unit: "sparks/s", label: "Star makes" }),
96
+ starCost: f32(13000, { min: 1, max: 1e9, tunable: true, label: "Star costs" }),
97
+ costGrowth: f32(1.15, { min: 1, max: 2, step: 0.01, tunable: true, label: "Price growth", doc: "Each one bought multiplies the next one's price." }),
98
+ milestone: u32(10, { min: 1, max: 100, tunable: true, label: "Milestone every", doc: "Every this many of a generator doubles what that generator makes." }),
99
+ tapBase: f32(1, { min: 0, max: 1000, tunable: true, label: "A tap makes" }),
100
+ tapShare: f32(0.05, { min: 0, max: 1, step: 0.01, tunable: true, label: "Tap's share of the rate", doc: "A tap also makes this many seconds' worth of the rate." }),
101
+ dustBonus: f32(0.1, { min: 0, max: 1, step: 0.01, tunable: true, label: "Stardust bonus", doc: "Each stardust adds this to every multiplier." }),
102
+ novaScale: f32(100000, { min: 1, max: 1e12, tunable: true, label: "Supernova scale", doc: "Stardust from a supernova is floor(sqrt(run sparks / this))." }),
103
+ offlineShare: f32(0.5, { min: 0, max: 1, step: 0.05, tunable: true, label: "Offline share", doc: "The share of the rate the orb makes while the game is closed." }),
104
+ offlineCap: f32(28800, { min: 0, max: 604800, tunable: true, unit: "s", label: "Offline cap" }),
105
+ saveEvery: u32(600, { min: 60, max: 36000, tunable: true, unit: "ticks", label: "Save every" }),
106
+ });
107
+
108
+ /** The player's settings: kept in og.platform's settings, restored on the first ticks. */
109
+ export const Prefs = defineResource("Prefs", {
110
+ master: f32(1, { min: 0, max: 1 }),
111
+ music: f32(0.7, { min: 0, max: 1 }),
112
+ effects: f32(1, { min: 0, max: 1 }),
113
+ language: u32(0, { doc: "0 English, 1 简体中文 (LANGUAGES in src/ui.ts)." }),
114
+ reducedMotion: bool(false),
115
+ loadRequest: u32(0),
116
+ saves: u32(0),
117
+ });
118
+
119
+ /** The orb: a tap squashes and flashes it. */
120
+ export const Orb = defineComponent("Orb", {
121
+ taps: u32(0),
122
+ });
123
+
124
+ /** A mote circling the orb: one per generator owned, up to MOTES per generator. */
125
+ export const Mote = defineComponent("Mote", {
126
+ tier: u32(0, { doc: "The generator (0-3)." }),
127
+ index: u32(0, { doc: "Its place in the tier's ring." }),
128
+ });
129
+
130
+ /** A pooled particle burst of one kind (BURST.* of src/systems.ts). */
131
+ export const Burst = defineComponent("Burst", {
132
+ kind: u32(0),
133
+ });
134
+
135
+ /** One voice: plays its sound once when Game.sfx asks for its bit. */
136
+ export const Sfx = defineComponent("Sfx", {
137
+ bit: u32(0),
138
+ plays: u32(0),
139
+ });
@@ -0,0 +1,247 @@
1
+ // Spark Orb, the idle archetype (2D profile): a glowing orb in the night.
2
+ // Tap it for sparks; spend them on generators (embers, storms, crystals,
3
+ // stars) that make sparks on their own and circle the orb as motes; every
4
+ // tenth of a kind doubles that kind. When the run has made enough, the orb
5
+ // can collapse into a supernova: sparks and generators go, stardust stays,
6
+ // and each stardust makes everything 10 % stronger. The save lives in
7
+ // og.platform's store with the host's time it was written at; on a launch
8
+ // the time away (the save's answer's time less that) is credited at half
9
+ // the rate.
10
+ //
11
+ // The look (GameDesc.look, a file under assets/looks/) sets the frame's
12
+ // treatment and the UI skin before start runs. `start` loads the strings,
13
+ // the sounds and the orb's art and spawns the rows: the orb and its glow,
14
+ // 48 motes (12 per generator), the burst pools, a voice per sound and the
15
+ // music. The systems are in
16
+ // src/systems.ts, the formulas and big numbers in src/numbers.ts, the
17
+ // screens and the save in src/ui.ts and the state in src/components.ts.
18
+
19
+ import { og } from "@origingame/engine";
20
+ import type { World } from "@origingame/engine";
21
+ import { Burst, Game, GENERATORS, Mote, MOTES, Orb, Phase, Prefs, Sfx, Sound, Tuning } from "./components.ts";
22
+ import { counts, Bursts, BURST, Economy, lazyTuning, Motes, nova, ORB_RADIUS, OrbTap, TIER_COLOURS, Voices } from "./systems.ts";
23
+ import { setOwned } from "./numbers.ts";
24
+ import { LANGUAGES, launch, Ui } from "./ui.ts";
25
+
26
+ /** The night, linear. */
27
+ const NIGHT = { r: 0.004, g: 0.002, b: 0.012 };
28
+
29
+ function must<T>(r: { ok: true; value: T } | { ok: false; reason: string }): T;
30
+ function must(r: { ok: true } | { ok: false; reason: string }): void;
31
+ function must<T>(r: { ok: true; value?: T } | { ok: false; reason: string }): T | void {
32
+ if (!r.ok) throw new Error(r.reason);
33
+ return r.value;
34
+ }
35
+
36
+ function start(world: World): void {
37
+ for (const l of LANGUAGES) must(og.i18n.load(world, `strings/${l.code}.ogt`));
38
+ // GameDesc.look set the frame and loaded the skin before start; the UI
39
+ // keeps that skin and adds the sounds.
40
+ const skin = og.render.look(world)?.skin ?? null;
41
+ const sound = (path: string) => must(og.load.sound(world, path));
42
+ must(og.ui.configure(world, { skin, sounds: { press: sound("audio/ui-press.ogt"), open: sound("audio/ui-open.ogt"), close: sound("audio/ui-close.ogt"), error: sound("audio/ui-error.ogt"), success: sound("audio/ui-success.ogt") } }));
43
+
44
+ const camera = must(world.resource(og.Camera));
45
+ camera.orthographic = true;
46
+ camera.height = 10;
47
+ camera.position = { x: 0, y: 0, z: 50 };
48
+ camera.background = NIGHT;
49
+
50
+ const texture = (path: string) => must(og.load.texture(world, path));
51
+ // The night: a violet haze and fixed stars of the dice (og.Rng's "stars" stream, the same every launch).
52
+ const haze = must(world.spawn({ name: "haze", position: { x: 0, y: 0.35, z: 0 } }));
53
+ must(world.insert(haze, og.Sprite, { texture: texture("sprites/glow.png"), width: 24, height: 18, color: { r: 0.4, g: 0.2, b: 0.85 }, opacity: 0.16, blend: "additive", layer: -11 }));
54
+ const spark = texture("sprites/spark.png");
55
+ const dice = must(world.resource(og.Rng)).fork("stars");
56
+ for (let i = 0; i < 140; i++) {
57
+ const star = must(world.spawn({ name: `star-${i}`, position: { x: dice.range(-15, 15), y: dice.range(-10, 10), z: 0 } }));
58
+ const size = dice.range(0.05, 0.16);
59
+ const warm = dice.next();
60
+ must(world.insert(star, og.Sprite, { texture: spark, width: size, height: size, color: { r: 0.75 + 0.25 * warm, g: 0.82 + 0.1 * warm, b: 1 - 0.25 * warm }, opacity: dice.range(0.35, 0.9), blend: "additive", layer: -10 }));
61
+ }
62
+ const stars = must(world.spawn({ name: "stars", position: { x: 0, y: 0, z: 0 } }));
63
+ must(world.insert(stars, og.ParticleSystem, { emitter: must(og.load.emitter(world, "fx/stars.ogt")), seed: 3 }));
64
+ const glow = must(world.spawn({ name: "glow", position: { x: 0, y: 0.35, z: 0 } }));
65
+ must(world.insert(glow, og.Sprite, { texture: texture("sprites/glow.png"), width: ORB_RADIUS * 5.5, height: ORB_RADIUS * 5.5, color: { r: 1, g: 0.6, b: 0.2 }, opacity: 0.85, blend: "additive", layer: 1 }));
66
+ const drift = must(world.spawn({ name: "drift", position: { x: 0, y: 0.35, z: 0 } }));
67
+ must(world.insert(drift, og.ParticleSystem, { emitter: must(og.load.emitter(world, "fx/drift.ogt")), seed: 5 }));
68
+ const orb = must(world.spawn({ name: "orb", position: { x: 0, y: 0.35, z: 0 } }));
69
+ must(world.insert(orb, og.Sprite, { texture: texture("sprites/orb.png"), width: ORB_RADIUS * 2.2, height: ORB_RADIUS * 2.2, layer: 3 }));
70
+ must(world.insert(orb, Orb));
71
+
72
+ const moteTextures = GENERATORS.map((name) => texture(`sprites/mote-${name}.png`));
73
+ GENERATORS.forEach((_, tier) => {
74
+ for (let k = 0; k < MOTES; k++) {
75
+ const m = must(world.spawn({ name: `mote-${tier}-${k}`, position: { x: 0, y: -40, z: 0 } }));
76
+ const c = TIER_COLOURS[tier]!;
77
+ must(world.insert(m, og.Sprite, { texture: moteTextures[tier]!, width: 0.42, height: 0.42, color: c, blend: "additive", layer: 4, visible: false }));
78
+ must(world.insert(m, Mote, { tier, index: k }));
79
+ }
80
+ });
81
+ const pools: [number, string, number][] = [[BURST.Tap, "fx/tap.ogt", 6], [BURST.Milestone, "fx/milestone.ogt", 2], [BURST.Nova, "fx/nova.ogt", 1]];
82
+ for (const [kind, path, n] of pools) {
83
+ const emitter = must(og.load.emitter(world, path));
84
+ for (let i = 0; i < n; i++) {
85
+ const b = must(world.spawn({ name: `burst-${kind}-${i}`, position: { x: 0, y: -40, z: 0 } }));
86
+ must(world.insert(b, og.ParticleSystem, { emitter, seed: kind * 10 + i + 1, visible: false }));
87
+ must(world.insert(b, Burst, { kind }));
88
+ }
89
+ }
90
+
91
+ const voices: [string, number, "sfx" | "ui", number][] = [
92
+ // The orb is the game's one big button: its chime is on the ui bus, as a press's sound (og-audio §3).
93
+ ["audio/tap.wav", Sound.Tap, "ui", 0.5],
94
+ ["audio/buy.wav", Sound.Buy, "sfx", 0.55],
95
+ ["audio/milestone.wav", Sound.Milestone, "sfx", 0.6],
96
+ ["audio/nova.wav", Sound.Nova, "sfx", 0.75],
97
+ ["audio/ui-success.ogt", Sound.Welcome, "ui", 0.6],
98
+ ["audio/ui-press.ogt", Sound.Move, "ui", 0.3],
99
+ ];
100
+ for (const [path, bit, bus, volume] of voices) {
101
+ const v = must(world.spawn({ name: `sfx-${bit}` }));
102
+ must(world.insert(v, og.AudioSource, { sound: sound(path), playing: false, bus, volume, priority: 160 }));
103
+ must(world.insert(v, Sfx, { bit }));
104
+ }
105
+ const music = must(world.spawn({ name: "music" }));
106
+ must(world.insert(music, og.AudioSource, { sound: sound("audio/orbit.wav"), bus: "music", loop: true, volume: 0.55, priority: 220 }));
107
+ const fx = must(world.spawn({ name: "music-bus" }));
108
+ must(world.insert(fx, og.AudioBusFx, { bus: "music", duck: true, duckBus: "sfx", duckDepth: 4, duckRelease: 0.6 }));
109
+ const game = must(world.resource(Game));
110
+ game.orbY = 0.35;
111
+ }
112
+
113
+ function gameOf(world: World) {
114
+ return must(world.resource(Game));
115
+ }
116
+
117
+ function num(s: string | undefined, what: string): number {
118
+ const n = Number(s);
119
+ if (s === undefined || !Number.isFinite(n)) throw new Error(`${what} is a number`);
120
+ return n;
121
+ }
122
+
123
+ /** `play`: from the title to the orb, as Play does. */
124
+ function play(world: World): void {
125
+ gameOf(world).phase = Phase.Play;
126
+ }
127
+
128
+ /** `sparks:<n>`: set the sparks (and count them as made this run). */
129
+ function sparks(world: World, args: readonly string[]): void {
130
+ const g = gameOf(world);
131
+ const n = num(args[0], "n");
132
+ const more = Math.max(0, n - g.sparks);
133
+ g.sparks = n;
134
+ g.runEarned += more;
135
+ g.lifetime += more;
136
+ }
137
+
138
+ /** `own:<generator 0-3>:<n>`: set how many of a generator are owned. */
139
+ function own(world: World, args: readonly string[]): void {
140
+ const g = gameOf(world);
141
+ const i = num(args[0], "generator");
142
+ if (i < 0 || i > 3) throw new Error("the generator is 0 to 3");
143
+ setOwned(g, i, num(args[1], "n"));
144
+ }
145
+
146
+ /** `supernova`: collapse now, as the dialog's Collapse does (refused under one stardust). */
147
+ function supernova(world: World): void {
148
+ nova(world, gameOf(world), lazyTuning(world));
149
+ }
150
+
151
+ /**
152
+ * `relaunch:<seconds away>`: the game closed and opened again that much later, in this process:
153
+ * the run forgotten, the save read again, the time away credited. For tests: a real launch reads
154
+ * the time away from the host's clock (the save's `at` against its answer's time; tests/away.og.ts
155
+ * runs it across two processes).
156
+ */
157
+ function relaunch(world: World, args: readonly string[]): void {
158
+ const g = gameOf(world);
159
+ const away = num(args[0], "seconds");
160
+ g.phase = Phase.Title;
161
+ g.paused = false;
162
+ g.settingsOpen = false;
163
+ g.confirmNova = false;
164
+ g.welcome = false;
165
+ g.sparks = 0;
166
+ g.runEarned = 0;
167
+ g.lifetime = 0;
168
+ g.owned0 = 0;
169
+ g.owned1 = 0;
170
+ g.owned2 = 0;
171
+ g.owned3 = 0;
172
+ g.dust = 0;
173
+ g.novas = 0;
174
+ g.runTicks = 0;
175
+ g.taps = 0;
176
+ g.rate = 0;
177
+ g.offline = 0;
178
+ g.loaded = false;
179
+ g.saveRevision = 0;
180
+ g.away = away;
181
+ launch(world, g, must(world.resource(Prefs)));
182
+ }
183
+
184
+ /** `stale_save`: another device writes a save with more lifetime sparks, so this one's next write is refused as stale and the other's progress kept. */
185
+ function staleSave(world: World): void {
186
+ must(og.platform.storeSet(world, { key: "orb", value: { v: 1, sparks: 5000, runEarned: 9000, lifetime: 1e9, owned: [20, 5, 0, 0], dust: 3, novas: 1, runTicks: 600, taps: 10 } }));
187
+ }
188
+
189
+ /** `viewport:<desktop|phone>`: lay the UI out for a phone in portrait. */
190
+ function viewport(world: World, args: readonly string[]): void {
191
+ const phone = { width: 390, height: 844, dpr: 3, safeArea: { left: 0, top: 47, right: 0, bottom: 34 }, coarsePointer: true, breakpoint: "phonePortrait" } as const;
192
+ og.ui.previewViewport(world, args[0] === "phone" ? phone : null);
193
+ }
194
+
195
+ /** `language:<en|zh-CN>`. */
196
+ function language(world: World, args: readonly string[]): void {
197
+ const p = must(world.resource(Prefs));
198
+ const at = LANGUAGES.findIndex((l) => l.code === args[0]);
199
+ if (at < 0) throw new Error("write language:<en|zh-CN>");
200
+ p.language = at;
201
+ og.i18n.setLocale(world, LANGUAGES[at]!.code);
202
+ }
203
+
204
+ export default og.game({
205
+ tick: 60,
206
+ seed: 1,
207
+ resources: [Game, Tuning, Prefs],
208
+ systems: [Ui, OrbTap, Economy, Motes, Bursts, Voices],
209
+ render: { antialias: "off" },
210
+ look: "looks/idle.ogt",
211
+ start,
212
+ commands: { play, sparks, own, supernova, relaunch, stale_save: staleSave, viewport, language },
213
+ commandHelp: {
214
+ play: { usage: "", doc: "From the title to the orb, as Play does." },
215
+ sparks: { usage: "<n>", doc: "Set the sparks (the rise counts as made this run)." },
216
+ own: { usage: "<generator 0-3>:<n>", doc: "Set how many of a generator are owned." },
217
+ supernova: { usage: "", doc: "Collapse now, as the dialog's Collapse does (refused under one stardust)." },
218
+ relaunch: { usage: "<seconds away>", doc: "Close and reopen the game that much later in this process (for tests; a real launch reads the time away from the host's clock): the save read again, the time away credited." },
219
+ stale_save: { usage: "", doc: "Another device writes a save with more progress, so this one's next write is refused as stale and merged." },
220
+ viewport: { usage: "<desktop|phone>", doc: "Lay the UI out for a phone in portrait (390×844 at 3×)." },
221
+ language: { usage: "<en|zh-CN>", doc: "Switch the language as the settings do." },
222
+ },
223
+ facts: (world) => {
224
+ const game = world.resource(Game);
225
+ if (!game.ok) return null;
226
+ const g = game.value;
227
+ return {
228
+ phase: ["title", "play", "nova"][g.phase],
229
+ sparks: g.sparks,
230
+ rate: g.rate,
231
+ tapValue: g.tapValue,
232
+ owned: counts(g),
233
+ dust: g.dust,
234
+ novas: g.novas,
235
+ runEarned: g.runEarned,
236
+ lifetime: g.lifetime,
237
+ taps: g.taps,
238
+ buys: g.buys,
239
+ refused: g.refused,
240
+ saves: g.saves,
241
+ saveConflicts: g.saveConflicts,
242
+ offline: g.offline,
243
+ language: LANGUAGES[g.language]!.code,
244
+ };
245
+ },
246
+ });
247
+
@@ -0,0 +1,126 @@
1
+ // The economy's formulas and big numbers in words of the locale.
2
+ //
3
+ // Prices, rates, milestones and stardust are pure functions of the counts
4
+ // and the tuning, so the systems, the HUD, the save's merge and the
5
+ // playtests agree on every number.
6
+ //
7
+ // Big numbers come from the string tables (og-i18n): `num.step` is how
8
+ // many digits a unit spans (3 in English: K, M, B…; 4 in Chinese: 万, 亿,
9
+ // 万亿…), `num.<k>` the k-th unit, `num.short` how mantissa and unit join
10
+ // and `num.sci` the scientific form past the last unit. Below the first
11
+ // unit's tenfold a number is whole and grouped by `{n, number}`.
12
+
13
+ import { og } from "@origingame/engine";
14
+ import type { Value, World } from "@origingame/engine";
15
+ import type { Game, Tuning } from "./components.ts";
16
+
17
+ type GameV = Value<typeof Game>;
18
+ type TuneV = Value<typeof Tuning>;
19
+
20
+ /** Generator i's rate and base price from the tuning. */
21
+ export function base(t: TuneV, i: number): { rate: number; cost: number } {
22
+ switch (i) {
23
+ case 0:
24
+ return { rate: t.emberRate, cost: t.emberCost };
25
+ case 1:
26
+ return { rate: t.stormRate, cost: t.stormCost };
27
+ case 2:
28
+ return { rate: t.crystalRate, cost: t.crystalCost };
29
+ default:
30
+ return { rate: t.starRate, cost: t.starCost };
31
+ }
32
+ }
33
+
34
+ export function owned(g: GameV, i: number): number {
35
+ return i === 0 ? g.owned0 : i === 1 ? g.owned1 : i === 2 ? g.owned2 : g.owned3;
36
+ }
37
+
38
+ export function setOwned(g: GameV, i: number, n: number): void {
39
+ if (i === 0) g.owned0 = n;
40
+ else if (i === 1) g.owned1 = n;
41
+ else if (i === 2) g.owned2 = n;
42
+ else g.owned3 = n;
43
+ }
44
+
45
+ /** The next one's price: the base times the growth to the count owned, rounded up. */
46
+ export function price(t: TuneV, i: number, n: number): number {
47
+ return Math.ceil(base(t, i).cost * Math.pow(t.costGrowth, n));
48
+ }
49
+
50
+ /** Everything's multiplier from stardust. */
51
+ export function dustMultiplier(t: TuneV, dust: number): number {
52
+ return 1 + t.dustBonus * dust;
53
+ }
54
+
55
+ /** What generator i makes a second with n owned: doubled at every milestone. */
56
+ export function generatorRate(t: TuneV, i: number, n: number, dust: number): number {
57
+ return base(t, i).rate * n * Math.pow(2, Math.floor(n / t.milestone)) * dustMultiplier(t, dust);
58
+ }
59
+
60
+ export function totalRate(t: TuneV, counts: readonly number[], dust: number): number {
61
+ let r = 0;
62
+ counts.forEach((n, i) => (r += generatorRate(t, i, n, dust)));
63
+ return r;
64
+ }
65
+
66
+ /** A tap: the base, plus a share of the rate, times the stardust. */
67
+ export function tapValue(t: TuneV, rate: number, dust: number): number {
68
+ return (t.tapBase * dustMultiplier(t, dust)) + t.tapShare * rate;
69
+ }
70
+
71
+ /** Stardust a supernova would give now. */
72
+ export function novaGain(t: TuneV, runEarned: number): number {
73
+ return Math.floor(Math.sqrt(runEarned / t.novaScale));
74
+ }
75
+
76
+ /** Run sparks at which the supernova gives its first stardust. */
77
+ export function novaAt(t: TuneV): number {
78
+ return t.novaScale;
79
+ }
80
+
81
+ /** Sparks made while the game was closed for `away` seconds. */
82
+ export function offlineGain(t: TuneV, rate: number, away: number): number {
83
+ return rate * t.offlineShare * Math.min(Math.max(0, away), t.offlineCap);
84
+ }
85
+
86
+ /** Three significant digits, as text (the mantissa of a big number). */
87
+ function mantissa(m: number): string {
88
+ return m >= 100 ? m.toFixed(0) : m >= 10 ? m.toFixed(1) : m.toFixed(2);
89
+ }
90
+
91
+ /** The locale's unit for a big number: its value in units, the unit's text and the decimals to show. */
92
+ export function bigParts(world: World, n: number): { value: number; unit: string; decimals: number } {
93
+ const step = Number(og.i18n.t(world, "num.step")) || 3;
94
+ const unitBase = Math.pow(10, step);
95
+ if (!Number.isFinite(n) || n < unitBase * 10) return { value: Math.floor(Math.max(0, n)), unit: "", decimals: 0 };
96
+ let k = Math.floor(Math.log10(n) / step);
97
+ let value = n / Math.pow(unitBase, k);
98
+ // Rounding to three digits can make 1000K: then it is 1.00M.
99
+ if (Number(mantissa(value)) >= unitBase) {
100
+ k += 1;
101
+ value /= unitBase;
102
+ }
103
+ const key = `num.${k}`;
104
+ if (!og.i18n.has(world, key)) return { value, unit: "", decimals: -1 };
105
+ return { value, unit: og.i18n.t(world, key), decimals: value >= 100 ? 0 : value >= 10 ? 1 : 2 };
106
+ }
107
+
108
+ /** A number in the locale's words: `9,999`, `12.3K`, `1.20亿`, `4.56e45`. */
109
+ export function big(world: World, n: number): string {
110
+ const p = bigParts(world, n);
111
+ if (p.unit === "" && p.decimals === 0) return og.i18n.t(world, "num.whole", { n: p.value });
112
+ if (p.decimals < 0) {
113
+ const e = Math.floor(Math.log10(n));
114
+ return og.i18n.t(world, "num.sci", { m: mantissa(n / Math.pow(10, e)), e });
115
+ }
116
+ return og.i18n.t(world, "num.short", { m: mantissa(p.value), u: p.unit });
117
+ }
118
+
119
+ /** A duration in the locale's words. */
120
+ export function duration(world: World, seconds: number): string {
121
+ const s = Math.max(0, Math.floor(seconds));
122
+ const h = Math.floor(s / 3600);
123
+ const m = Math.floor((s % 3600) / 60);
124
+ if (h > 0) return og.i18n.t(world, "time.hm", { h, m });
125
+ return og.i18n.t(world, "time.ms", { m, s: s % 60 });
126
+ }