From 6c94909367b118738a0e1798855361929021ea13 Mon Sep 17 00:00:00 2001
From: sprunk
Date: Wed, 11 Oct 2023 17:50:46 +0200
Subject: [PATCH] Changelogs.
---
.gitignore | 5 +
404.html | 25 +
Gemfile | 48 +
Gemfile.lock | 281 +++
README.md | 26 +
_authors/badosu.markdown | 4 +
_authors/lhog.markdown | 4 +
_authors/p2004a.markdown | 4 +
_authors/sprunk.markdown | 4 +
_authors/verybadsoldier.markdown | 4 +
_config.yml | 175 ++
_data/configs.json | 2082 +++++++++++++++++++++
_data/glossary.yml | 38 +
_data/latest_release.json | 244 +++
_data/non_coder_contributors.yml | 3 +
_data/synced_commands.json | 116 ++
_data/unsynced_commands.json | 1164 ++++++++++++
_data/weapondefs.json | 819 ++++++++
_includes/head.html | 52 +
_includes/header_custom.html | 34 +
_layouts/post.html | 21 +
_sass/content-nocharset.scss | 237 +++
_sass/custom/custom.scss | 226 +++
_sass/modules-nocharset.scss | 16 +
_scripts/get_engine_data.sh | 36 +
_scripts/get_release_data.sh | 10 +
about.markdown | 10 +
articles.markdown | 10 +
articles/ceg-operators.markdown | 190 ++
articles/modrules-and-others.markdown | 39 +
articles/pathfinding.markdown | 7 +
articles/select-command.markdown | 210 +++
articles/team-terminology.markdown | 89 +
articles/unit-defs.markdown | 178 ++
articles/units-of-measurement.markdown | 55 +
articles/vfs-basics.markdown | 63 +
assets/css/just-the-docs-themes.scss | 83 +
assets/github-mark-white.svg | 1 +
assets/github-mark.svg | 1 +
assets/guides/lua-vbo-vao-1.png | Bin 0 -> 59905 bytes
assets/guides/lua-vbo-vao-2.png | Bin 0 -> 85689 bytes
assets/guides/lua-vbo-vao-3.png | Bin 0 -> 137537 bytes
assets/guides/lua-vbo-vao-4.png | Bin 0 -> 89526 bytes
assets/js/theme-switcher.js | 58 +
assets/matrix-logo-white.svg | 18 +
assets/matrix-logo.svg | 5 +
changelogs.markdown | 10 +
changelogs/changelog-105-1214.markdown | 88 +
changelogs/changelog-105-1354.markdown | 54 +
changelogs/changelog-105-1544.markdown | 90 +
changelogs/changelog-105-1775.markdown | 100 +
changelogs/changelog-105-861.markdown | 143 ++
changelogs/changelog-105-902.markdown | 41 +
changelogs/changelog-105-941.markdown | 25 +
changelogs/changelog-105-966.markdown | 58 +
changelogs/running-changelog.markdown | 268 +++
development.markdown | 10 +
development/build-with-docker.markdown | 139 ++
development/build-without-docker.markdown | 229 +++
guides.markdown | 10 +
guides/choose-recoil.markdown | 43 +
guides/configuration-variables.markdown | 49 +
guides/glossary.markdown | 15 +
guides/headless-and-dedi.markdown | 32 +
guides/lua-vbo-vao.markdown | 155 ++
guides/synced-commands.markdown | 47 +
guides/unsynced-commands.markdown | 48 +
guides/weapondefs.markdown | 40 +
guides/widgets.markdown | 7 +
index.markdown | 88 +
ldoc/.gitkeep | 0
lua-api.md | 20 +
migrating-from-spring.markdown | 222 +++
73 files changed, 8726 insertions(+)
create mode 100644 .gitignore
create mode 100644 404.html
create mode 100644 Gemfile
create mode 100644 Gemfile.lock
create mode 100644 README.md
create mode 100644 _authors/badosu.markdown
create mode 100644 _authors/lhog.markdown
create mode 100644 _authors/p2004a.markdown
create mode 100644 _authors/sprunk.markdown
create mode 100644 _authors/verybadsoldier.markdown
create mode 100644 _config.yml
create mode 100644 _data/configs.json
create mode 100644 _data/glossary.yml
create mode 100644 _data/latest_release.json
create mode 100644 _data/non_coder_contributors.yml
create mode 100644 _data/synced_commands.json
create mode 100644 _data/unsynced_commands.json
create mode 100644 _data/weapondefs.json
create mode 100644 _includes/head.html
create mode 100644 _includes/header_custom.html
create mode 100644 _layouts/post.html
create mode 100644 _sass/content-nocharset.scss
create mode 100644 _sass/custom/custom.scss
create mode 100644 _sass/modules-nocharset.scss
create mode 100755 _scripts/get_engine_data.sh
create mode 100755 _scripts/get_release_data.sh
create mode 100644 about.markdown
create mode 100644 articles.markdown
create mode 100644 articles/ceg-operators.markdown
create mode 100644 articles/modrules-and-others.markdown
create mode 100644 articles/pathfinding.markdown
create mode 100644 articles/select-command.markdown
create mode 100644 articles/team-terminology.markdown
create mode 100644 articles/unit-defs.markdown
create mode 100644 articles/units-of-measurement.markdown
create mode 100644 articles/vfs-basics.markdown
create mode 100644 assets/css/just-the-docs-themes.scss
create mode 100644 assets/github-mark-white.svg
create mode 100644 assets/github-mark.svg
create mode 100644 assets/guides/lua-vbo-vao-1.png
create mode 100644 assets/guides/lua-vbo-vao-2.png
create mode 100644 assets/guides/lua-vbo-vao-3.png
create mode 100644 assets/guides/lua-vbo-vao-4.png
create mode 100644 assets/js/theme-switcher.js
create mode 100644 assets/matrix-logo-white.svg
create mode 100644 assets/matrix-logo.svg
create mode 100644 changelogs.markdown
create mode 100644 changelogs/changelog-105-1214.markdown
create mode 100644 changelogs/changelog-105-1354.markdown
create mode 100644 changelogs/changelog-105-1544.markdown
create mode 100644 changelogs/changelog-105-1775.markdown
create mode 100644 changelogs/changelog-105-861.markdown
create mode 100644 changelogs/changelog-105-902.markdown
create mode 100644 changelogs/changelog-105-941.markdown
create mode 100644 changelogs/changelog-105-966.markdown
create mode 100644 changelogs/running-changelog.markdown
create mode 100644 development.markdown
create mode 100644 development/build-with-docker.markdown
create mode 100644 development/build-without-docker.markdown
create mode 100644 guides.markdown
create mode 100644 guides/choose-recoil.markdown
create mode 100644 guides/configuration-variables.markdown
create mode 100644 guides/glossary.markdown
create mode 100644 guides/headless-and-dedi.markdown
create mode 100644 guides/lua-vbo-vao.markdown
create mode 100644 guides/synced-commands.markdown
create mode 100644 guides/unsynced-commands.markdown
create mode 100644 guides/weapondefs.markdown
create mode 100644 guides/widgets.markdown
create mode 100644 index.markdown
create mode 100644 ldoc/.gitkeep
create mode 100644 lua-api.md
create mode 100644 migrating-from-spring.markdown
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..f40fbd8ba5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+_site
+.sass-cache
+.jekyll-cache
+.jekyll-metadata
+vendor
diff --git a/404.html b/404.html
new file mode 100644
index 0000000000..086a5c9ea9
--- /dev/null
+++ b/404.html
@@ -0,0 +1,25 @@
+---
+permalink: /404.html
+layout: default
+---
+
+
+
+
+
404
+
+
Page not found :(
+
The requested page could not be found.
+
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000000..fb80b448fb
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+source 'https://rubygems.org'
+# Hello! This is where you manage which Jekyll version is used to run.
+# When you want to use a different version, change it below, save the
+# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
+#
+# bundle exec jekyll serve
+#
+# This will help ensure the proper Jekyll version is running.
+# Happy Jekylling!
+# This is the default theme for new Jekyll sites. You may change this to anything you like.
+gem 'just-the-docs'
+# If you want to use GitHub Pages, remove the 'gem 'jekyll'' above and
+# uncomment the line below. To upgrade, run `bundle update github-pages`.
+
+# Already included with github-pages gem
+# gem 'jekyll'
+
+# If you have any plugins, put them here!
+group :jekyll_plugins do
+ gem 'github-pages'
+ gem 'jekyll-feed'
+ # Already included with github-pages gem
+ # gem 'jekyll-github-metadata'
+ gem 'jekyll-glossary_tooltip'
+ gem 'jekyll-liquify'
+ gem 'jekyll-remote-theme'
+ gem 'jekyll-sitemap'
+end
+
+# Can't serve locally without webrick
+# https://github.com/github/pages-gem/issues/752
+gem 'webrick'
+
+# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
+# and associated library.
+platforms :mingw, :x64_mingw, :mswin, :jruby do
+ gem 'tzinfo', '>= 1', '< 3'
+ gem 'tzinfo-data'
+end
+
+# Performance-booster for watching directories on Windows
+gem 'wdm', '~> 0.1.1', platforms: %i[mingw x64_mingw mswin]
+
+# Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem
+# do not have a Java counterpart.
+gem 'http_parser.rb', '~> 0.6.0', platforms: %i[jruby]
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000000..f78bcafe66
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,281 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activesupport (7.0.4.2)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (>= 1.6, < 2)
+ minitest (>= 5.1)
+ tzinfo (~> 2.0)
+ addressable (2.8.1)
+ public_suffix (>= 2.0.2, < 6.0)
+ coffee-script (2.4.1)
+ coffee-script-source
+ execjs
+ coffee-script-source (1.11.1)
+ colorator (1.1.0)
+ commonmarker (0.23.8)
+ concurrent-ruby (1.2.2)
+ dnsruby (1.61.9)
+ simpleidn (~> 0.1)
+ em-websocket (0.5.3)
+ eventmachine (>= 0.12.9)
+ http_parser.rb (~> 0)
+ ethon (0.16.0)
+ ffi (>= 1.15.0)
+ eventmachine (1.2.7)
+ execjs (2.8.1)
+ faraday (2.7.4)
+ faraday-net_http (>= 2.0, < 3.1)
+ ruby2_keywords (>= 0.0.4)
+ faraday-net_http (3.0.2)
+ ffi (1.15.5)
+ forwardable-extended (2.6.0)
+ gemoji (3.0.1)
+ github-pages (228)
+ github-pages-health-check (= 1.17.9)
+ jekyll (= 3.9.3)
+ jekyll-avatar (= 0.7.0)
+ jekyll-coffeescript (= 1.1.1)
+ jekyll-commonmark-ghpages (= 0.4.0)
+ jekyll-default-layout (= 0.1.4)
+ jekyll-feed (= 0.15.1)
+ jekyll-gist (= 1.5.0)
+ jekyll-github-metadata (= 2.13.0)
+ jekyll-include-cache (= 0.2.1)
+ jekyll-mentions (= 1.6.0)
+ jekyll-optional-front-matter (= 0.3.2)
+ jekyll-paginate (= 1.1.0)
+ jekyll-readme-index (= 0.3.0)
+ jekyll-redirect-from (= 0.16.0)
+ jekyll-relative-links (= 0.6.1)
+ jekyll-remote-theme (= 0.4.3)
+ jekyll-sass-converter (= 1.5.2)
+ jekyll-seo-tag (= 2.8.0)
+ jekyll-sitemap (= 1.4.0)
+ jekyll-swiss (= 1.0.0)
+ jekyll-theme-architect (= 0.2.0)
+ jekyll-theme-cayman (= 0.2.0)
+ jekyll-theme-dinky (= 0.2.0)
+ jekyll-theme-hacker (= 0.2.0)
+ jekyll-theme-leap-day (= 0.2.0)
+ jekyll-theme-merlot (= 0.2.0)
+ jekyll-theme-midnight (= 0.2.0)
+ jekyll-theme-minimal (= 0.2.0)
+ jekyll-theme-modernist (= 0.2.0)
+ jekyll-theme-primer (= 0.6.0)
+ jekyll-theme-slate (= 0.2.0)
+ jekyll-theme-tactile (= 0.2.0)
+ jekyll-theme-time-machine (= 0.2.0)
+ jekyll-titles-from-headings (= 0.5.3)
+ jemoji (= 0.12.0)
+ kramdown (= 2.3.2)
+ kramdown-parser-gfm (= 1.1.0)
+ liquid (= 4.0.4)
+ mercenary (~> 0.3)
+ minima (= 2.5.1)
+ nokogiri (>= 1.13.6, < 2.0)
+ rouge (= 3.26.0)
+ terminal-table (~> 1.4)
+ github-pages-health-check (1.17.9)
+ addressable (~> 2.3)
+ dnsruby (~> 1.60)
+ octokit (~> 4.0)
+ public_suffix (>= 3.0, < 5.0)
+ typhoeus (~> 1.3)
+ html-pipeline (2.14.3)
+ activesupport (>= 2)
+ nokogiri (>= 1.4)
+ http_parser.rb (0.8.0)
+ i18n (1.12.0)
+ concurrent-ruby (~> 1.0)
+ jekyll (3.9.3)
+ addressable (~> 2.4)
+ colorator (~> 1.0)
+ em-websocket (~> 0.5)
+ i18n (>= 0.7, < 2)
+ jekyll-sass-converter (~> 1.0)
+ jekyll-watch (~> 2.0)
+ kramdown (>= 1.17, < 3)
+ liquid (~> 4.0)
+ mercenary (~> 0.3.3)
+ pathutil (~> 0.9)
+ rouge (>= 1.7, < 4)
+ safe_yaml (~> 1.0)
+ jekyll-avatar (0.7.0)
+ jekyll (>= 3.0, < 5.0)
+ jekyll-coffeescript (1.1.1)
+ coffee-script (~> 2.2)
+ coffee-script-source (~> 1.11.1)
+ jekyll-commonmark (1.4.0)
+ commonmarker (~> 0.22)
+ jekyll-commonmark-ghpages (0.4.0)
+ commonmarker (~> 0.23.7)
+ jekyll (~> 3.9.0)
+ jekyll-commonmark (~> 1.4.0)
+ rouge (>= 2.0, < 5.0)
+ jekyll-default-layout (0.1.4)
+ jekyll (~> 3.0)
+ jekyll-feed (0.15.1)
+ jekyll (>= 3.7, < 5.0)
+ jekyll-gist (1.5.0)
+ octokit (~> 4.2)
+ jekyll-github-metadata (2.13.0)
+ jekyll (>= 3.4, < 5.0)
+ octokit (~> 4.0, != 4.4.0)
+ jekyll-glossary_tooltip (1.5.0)
+ jekyll (>= 3.7, < 5.0)
+ jekyll-include-cache (0.2.1)
+ jekyll (>= 3.7, < 5.0)
+ jekyll-liquify (0.0.2)
+ liquid (>= 2.5, < 5.0)
+ redcarpet (~> 3.1)
+ jekyll-mentions (1.6.0)
+ html-pipeline (~> 2.3)
+ jekyll (>= 3.7, < 5.0)
+ jekyll-optional-front-matter (0.3.2)
+ jekyll (>= 3.0, < 5.0)
+ jekyll-paginate (1.1.0)
+ jekyll-readme-index (0.3.0)
+ jekyll (>= 3.0, < 5.0)
+ jekyll-redirect-from (0.16.0)
+ jekyll (>= 3.3, < 5.0)
+ jekyll-relative-links (0.6.1)
+ jekyll (>= 3.3, < 5.0)
+ jekyll-remote-theme (0.4.3)
+ addressable (~> 2.0)
+ jekyll (>= 3.5, < 5.0)
+ jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
+ rubyzip (>= 1.3.0, < 3.0)
+ jekyll-sass-converter (1.5.2)
+ sass (~> 3.4)
+ jekyll-seo-tag (2.8.0)
+ jekyll (>= 3.8, < 5.0)
+ jekyll-sitemap (1.4.0)
+ jekyll (>= 3.7, < 5.0)
+ jekyll-swiss (1.0.0)
+ jekyll-theme-architect (0.2.0)
+ jekyll (> 3.5, < 5.0)
+ jekyll-seo-tag (~> 2.0)
+ jekyll-theme-cayman (0.2.0)
+ jekyll (> 3.5, < 5.0)
+ jekyll-seo-tag (~> 2.0)
+ jekyll-theme-dinky (0.2.0)
+ jekyll (> 3.5, < 5.0)
+ jekyll-seo-tag (~> 2.0)
+ jekyll-theme-hacker (0.2.0)
+ jekyll (> 3.5, < 5.0)
+ jekyll-seo-tag (~> 2.0)
+ jekyll-theme-leap-day (0.2.0)
+ jekyll (> 3.5, < 5.0)
+ jekyll-seo-tag (~> 2.0)
+ jekyll-theme-merlot (0.2.0)
+ jekyll (> 3.5, < 5.0)
+ jekyll-seo-tag (~> 2.0)
+ jekyll-theme-midnight (0.2.0)
+ jekyll (> 3.5, < 5.0)
+ jekyll-seo-tag (~> 2.0)
+ jekyll-theme-minimal (0.2.0)
+ jekyll (> 3.5, < 5.0)
+ jekyll-seo-tag (~> 2.0)
+ jekyll-theme-modernist (0.2.0)
+ jekyll (> 3.5, < 5.0)
+ jekyll-seo-tag (~> 2.0)
+ jekyll-theme-primer (0.6.0)
+ jekyll (> 3.5, < 5.0)
+ jekyll-github-metadata (~> 2.9)
+ jekyll-seo-tag (~> 2.0)
+ jekyll-theme-slate (0.2.0)
+ jekyll (> 3.5, < 5.0)
+ jekyll-seo-tag (~> 2.0)
+ jekyll-theme-tactile (0.2.0)
+ jekyll (> 3.5, < 5.0)
+ jekyll-seo-tag (~> 2.0)
+ jekyll-theme-time-machine (0.2.0)
+ jekyll (> 3.5, < 5.0)
+ jekyll-seo-tag (~> 2.0)
+ jekyll-titles-from-headings (0.5.3)
+ jekyll (>= 3.3, < 5.0)
+ jekyll-watch (2.2.1)
+ listen (~> 3.0)
+ jemoji (0.12.0)
+ gemoji (~> 3.0)
+ html-pipeline (~> 2.2)
+ jekyll (>= 3.0, < 5.0)
+ just-the-docs (0.4.1)
+ jekyll (>= 3.8.5)
+ jekyll-seo-tag (>= 2.0)
+ rake (>= 12.3.1)
+ kramdown (2.3.2)
+ rexml
+ kramdown-parser-gfm (1.1.0)
+ kramdown (~> 2.0)
+ liquid (4.0.4)
+ listen (3.8.0)
+ rb-fsevent (~> 0.10, >= 0.10.3)
+ rb-inotify (~> 0.9, >= 0.9.10)
+ mercenary (0.3.6)
+ minima (2.5.1)
+ jekyll (>= 3.5, < 5.0)
+ jekyll-feed (~> 0.9)
+ jekyll-seo-tag (~> 2.1)
+ minitest (5.17.0)
+ nokogiri (1.14.2-x86_64-linux)
+ racc (~> 1.4)
+ octokit (4.25.1)
+ faraday (>= 1, < 3)
+ sawyer (~> 0.9)
+ pathutil (0.16.2)
+ forwardable-extended (~> 2.6)
+ public_suffix (4.0.7)
+ racc (1.6.2)
+ rake (13.0.6)
+ rb-fsevent (0.11.2)
+ rb-inotify (0.10.1)
+ ffi (~> 1.0)
+ redcarpet (3.6.0)
+ rexml (3.2.5)
+ rouge (3.26.0)
+ ruby2_keywords (0.0.5)
+ rubyzip (2.3.2)
+ safe_yaml (1.0.5)
+ sass (3.7.4)
+ sass-listen (~> 4.0.0)
+ sass-listen (4.0.0)
+ rb-fsevent (~> 0.9, >= 0.9.4)
+ rb-inotify (~> 0.9, >= 0.9.7)
+ sawyer (0.9.2)
+ addressable (>= 2.3.5)
+ faraday (>= 0.17.3, < 3)
+ simpleidn (0.2.1)
+ unf (~> 0.1.4)
+ terminal-table (1.8.0)
+ unicode-display_width (~> 1.1, >= 1.1.1)
+ typhoeus (1.4.0)
+ ethon (>= 0.9.0)
+ tzinfo (2.0.6)
+ concurrent-ruby (~> 1.0)
+ unf (0.1.4)
+ unf_ext
+ unf_ext (0.0.8.2)
+ unicode-display_width (1.8.0)
+ webrick (1.8.1)
+
+PLATFORMS
+ x86_64-linux
+
+DEPENDENCIES
+ github-pages
+ http_parser.rb (~> 0.6.0)
+ jekyll-feed
+ jekyll-glossary_tooltip
+ jekyll-liquify
+ jekyll-remote-theme
+ jekyll-sitemap
+ just-the-docs
+ tzinfo (>= 1, < 3)
+ tzinfo-data
+ wdm (~> 0.1.1)
+ webrick
+
+BUNDLED WITH
+ 2.3.25
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000..2fa9462992
--- /dev/null
+++ b/README.md
@@ -0,0 +1,26 @@
+# Recoil Site
+
+The recoil site is a jekyll application, usually hosted on github pages.
+
+## Testing locally
+
+Have a reasonably recent version of Ruby. Inside `doc/site` run:
+
+```bash
+bundle
+bundle exec jekyll build && bundle exec jekyll serve
+```
+
+Navigate to http://localhost:4000/spring
+
+## Generating LDoc
+
+Have [LDoc](https://github.com/lunarmodules/LDoc) installed or available at your `$PATH`.
+
+Inside `doc/LDoc` run:
+
+```bash
+ldoc -c config.ld .
+```
+
+Keep in mind to see changes on the site you might have to restart jekyll.
diff --git a/_authors/badosu.markdown b/_authors/badosu.markdown
new file mode 100644
index 0000000000..308fb4cd38
--- /dev/null
+++ b/_authors/badosu.markdown
@@ -0,0 +1,4 @@
+---
+short_name: badosu
+github: badosu
+---
diff --git a/_authors/lhog.markdown b/_authors/lhog.markdown
new file mode 100644
index 0000000000..7a96955e35
--- /dev/null
+++ b/_authors/lhog.markdown
@@ -0,0 +1,4 @@
+---
+short_name: lhog
+github: lhog
+---
diff --git a/_authors/p2004a.markdown b/_authors/p2004a.markdown
new file mode 100644
index 0000000000..3d31064b8e
--- /dev/null
+++ b/_authors/p2004a.markdown
@@ -0,0 +1,4 @@
+---
+short_name: p2004a
+github: p2004a
+---
diff --git a/_authors/sprunk.markdown b/_authors/sprunk.markdown
new file mode 100644
index 0000000000..8002876154
--- /dev/null
+++ b/_authors/sprunk.markdown
@@ -0,0 +1,4 @@
+---
+short_name: sprunk
+github: sprunk
+---
diff --git a/_authors/verybadsoldier.markdown b/_authors/verybadsoldier.markdown
new file mode 100644
index 0000000000..eb91f72af1
--- /dev/null
+++ b/_authors/verybadsoldier.markdown
@@ -0,0 +1,4 @@
+---
+short_name: verybadsoldier
+github: verybadsoldier
+---
diff --git a/_config.yml b/_config.yml
new file mode 100644
index 0000000000..2d90a13e69
--- /dev/null
+++ b/_config.yml
@@ -0,0 +1,175 @@
+# Welcome to Jekyll!
+#
+# This config file is meant for settings that affect your whole blog, values
+# which you are expected to set up once and rarely edit after that. If you find
+# yourself editing this file very often, consider using Jekyll's data files
+# feature for the data you need to update frequently.
+#
+# For technical reasons, this file is *NOT* reloaded automatically when you use
+# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
+#
+# If you need help with YAML syntax, here are some quick references for you:
+# https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml
+# https://learnxinyminutes.com/docs/yaml/
+#
+# Site settings
+# These are used to personalize your new site. If you look in the HTML files,
+# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
+# You can create any custom variable you would like, and they will be accessible
+# in the templates via {{ site.myvariable }}.
+
+title: Recoil
+email: amadeusfolego@gmail.com
+description: >- # this means to ignore newlines until "baseurl:"
+ Recoil RTS Engine
+baseurl: "/spring" # the subpath of your site, e.g. /blog
+url: "https://beyond-all-reason.github.io" # the base hostname & protocol for your site, e.g. http://example.com
+#twitter_username: jekyllrb
+github_username: beyond-all-reason
+permalink: pretty
+repository: beyond-all-reason/spring # for github-metadata
+
+# Build settings
+#theme: minima
+#theme: just-the-docs
+remote_theme: just-the-docs/just-the-docs
+plugins:
+ - jekyll-feed
+ - jekyll-github-metadata
+ - jekyll-glossary_tooltip
+ - jekyll-remote-theme
+ - jekyll-sitemap
+ - jekyll-seo-tag
+
+search:
+ # Split pages into sections that can be searched individually
+ # Supports 1 - 6, default: 2
+ heading_level: 3
+ # Maximum amount of previews per search result
+ # Default: 3
+ previews: 3
+ # Maximum amount of words to display before a matched word in the preview
+ # Default: 5
+ preview_words_before: 5
+ # Maximum amount of words to display after a matched word in the preview
+ # Default: 10
+ preview_words_after: 10
+ # Set the search token separator
+ # Default: /[\s\-/]+/
+ # Example: enable support for hyphenated search words
+ tokenizer_separator: /[\s/]+/
+ # Display the relative url in search results
+ # Supports true (default) or false
+ rel_url: true
+ # Enable or disable the search button that appears in the bottom right corner of every page
+ # Supports true or false (default)
+ button: false
+
+# External navigation links
+#nav_external_links:
+# - title: Just the Docs on GitHub
+# url: https://github.com/just-the-docs/just-the-docs
+
+# Makes Aux links open in a new tab. Default is false
+aux_links_new_tab: true
+
+# For copy button on code
+enable_copy_code_button: true
+
+# Footer content
+# appears at the bottom of every page's main content
+
+# Back to top link
+back_to_top: true
+back_to_top_text: "Back to top"
+
+footer_content: "Copyright © 2022 Recoil team. Distributed by an GPL2 license. "
+
+# Footer last edited timestamp
+last_edit_timestamp: true # show or hide edit time - page must have `last_modified_date` defined in the frontmatter
+last_edit_time_format: "%b %e %Y at %I:%M %p" # uses ruby's time format: https://ruby-doc.org/stdlib-2.7.0/libdoc/time/rdoc/Time.html
+
+
+
+# Footer "Edit this page on GitHub" link text
+gh_edit_link: true # show or hide edit this page link
+gh_edit_link_text: "Edit this page on GitHub"
+gh_edit_repository: "https://github.com/beyond-all-reason/spring" # the github URL for your repo
+gh_edit_branch: "BAR105" # the branch that your docs is served from
+gh_edit_source: doc/site # the source that your files originate from
+gh_edit_view_mode: "tree" # "tree" or "edit" if you want the user to jump into the editor immediately
+
+# Color scheme currently only supports "dark", "light"/nil (default), or a custom scheme that you define
+color_scheme: nil
+
+callouts_level: quiet # or loud
+callouts:
+ highlight:
+ color: yellow
+ important:
+ title: Important
+ color: blue
+ new:
+ title: New
+ color: green
+ note:
+ title: Note
+ color: purple
+ warning:
+ title: Warning
+ color: red
+
+# Google Analytics Tracking (optional)
+# Supports a CSV of tracking ID strings (eg. "UA-1234567-89,G-1AB234CDE5")
+# Note: the main Just the Docs site does *not* use Google Analytics.
+# ga_tracking: UA-2709176-10,G-5FG1HLH3XQ
+# ga_tracking_anonymize_ip: true # Use GDPR compliant Google Analytics settings (true/nil by default)
+
+kramdown:
+ syntax_highlighter_opts:
+ block:
+ line_numbers: false
+
+compress_html:
+ clippings: all
+ comments: all
+ endings: all
+ startings: []
+ blanklines: false
+ profile: false
+ # ignore:
+ # envs: all
+
+collections:
+ authors:
+
+# Exclude from processing.
+# The following items will not be processed, by default.
+# Any item listed under the `exclude:` key here will be automatically added to
+# the internal "default list".
+#
+# Excluded items can be processed by explicitly listing the directories or
+# their entries' file path in the `include:` list.
+#
+exclude:
+ # from https://github.com/jekyll/jekyll/blob/master/lib/site_template/_config.yml:
+ - .sass-cache/
+ - .jekyll-cache/
+ - gemfiles/
+ - Gemfile
+ - Gemfile.lock
+ - node_modules/
+ - vendor/bundle/
+ - vendor/cache/
+ - vendor/gems/
+ - vendor/ruby/
+ # specific to the theme website:
+ - bin/
+ - lib/
+ - "*.gemspec"
+ - "*.gem"
+ - LICENSE.txt
+ - package.json
+ - package-lock.json
+ - Rakefile
+ - README.md
diff --git a/_data/configs.json b/_data/configs.json
new file mode 100644
index 0000000000..3b8dc3bac7
--- /dev/null
+++ b/_data/configs.json
@@ -0,0 +1,2082 @@
+{
+ "AdvMapShading": {
+ "declarationFile": "/spring/rts/Map/SMF/SMFGroundDrawer.cpp",
+ "declarationLine": 43,
+ "description": "Enable shaders for terrain rendering.",
+ "defaultValue": 1,
+ "safemodeValue": 0,
+ "type": "bool"
+ },
+ "AdvSky": {
+ "declarationFile": "/spring/rts/Rendering/Env/ISky.cpp",
+ "declarationLine": 19,
+ "deprecated": 1,
+ "type": "bool"
+ },
+ "AdvUnitShading": {
+ "declarationFile": "/spring/rts/Rendering/Units/UnitDrawer.cpp",
+ "declarationLine": 67,
+ "description": "Determines whether specular highlights and other lighting effects are rendered for units.",
+ "defaultValue": 1,
+ "safemodeValue": 0,
+ "headlessValue": 0,
+ "type": "bool"
+ },
+ "AllowDeferredMapRendering": {
+ "declarationFile": "/spring/rts/Map/SMF/SMFGroundDrawer.cpp",
+ "declarationLine": 44,
+ "defaultValue": 0,
+ "safemodeValue": 0,
+ "type": "bool"
+ },
+ "AllowDeferredModelBufferClear": {
+ "declarationFile": "/spring/rts/Rendering/LuaObjectDrawer.cpp",
+ "declarationLine": 32,
+ "defaultValue": 0,
+ "safemodeValue": 0,
+ "type": "bool"
+ },
+ "AllowDeferredModelRendering": {
+ "declarationFile": "/spring/rts/Rendering/LuaObjectDrawer.cpp",
+ "declarationLine": 31,
+ "defaultValue": 0,
+ "safemodeValue": 0,
+ "type": "bool"
+ },
+ "AllowDrawMapDeferredEvents": {
+ "declarationFile": "/spring/rts/Map/SMF/SMFGroundDrawer.cpp",
+ "declarationLine": 46,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "AllowDrawMapPostDeferredEvents": {
+ "declarationFile": "/spring/rts/Map/SMF/SMFGroundDrawer.cpp",
+ "declarationLine": 45,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "AllowDrawModelPostDeferredEvents": {
+ "declarationFile": "/spring/rts/Rendering/LuaObjectDrawer.cpp",
+ "declarationLine": 33,
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "AllowMultiSampledFrameBuffers": {
+ "declarationFile": "/spring/rts/Rendering/LuaObjectDrawer.cpp",
+ "declarationLine": 34,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "AllowSpectatorJoin": {
+ "declarationFile": "/spring/rts/Net/GameServer.cpp",
+ "declarationLine": 73,
+ "description": "allow any unauthenticated clients to join as spectator with any name, name will be prefixed with ~",
+ "defaultValue": 1,
+ "dedicatedValue": 0,
+ "type": "bool"
+ },
+ "AlwaysSendDrawGroundEvents": {
+ "declarationFile": "/spring/rts/Map/SMF/SMFGroundDrawer.cpp",
+ "declarationLine": 55,
+ "description": "Always send DrawGround{Pre,Post}{Forward,Deferred} events",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "AtiHacks": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 57,
+ "description": "Enables graphics drivers workarounds for users with AMD proprietary drivers.\n -1:=runtime detect, 0:=off, 1:=on",
+ "defaultValue": -1,
+ "minimumValue": -1,
+ "maximumValue": 1,
+ "headlessValue": 0,
+ "type": "int"
+ },
+ "AtiSwapRBFix": {
+ "declarationFile": "/spring/rts/Rendering/GL/FBO.cpp",
+ "declarationLine": 16,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "AutoAddBuiltUnitsToFactoryGroup": {
+ "declarationFile": "/spring/rts/Game/SelectedUnitsHandler.cpp",
+ "declarationLine": 49,
+ "description": "Controls whether or not units built by factories will inherit that factory's unit group.",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "AutoAddBuiltUnitsToSelectedGroup": {
+ "declarationFile": "/spring/rts/Game/SelectedUnitsHandler.cpp",
+ "declarationLine": 50,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "AutohostIP": {
+ "declarationFile": "/spring/rts/Net/GameServer.cpp",
+ "declarationLine": 78,
+ "defaultValue": "127.0.0.1",
+ "type": "std::string"
+ },
+ "AutohostPort": {
+ "declarationFile": "/spring/rts/Net/GameServer.cpp",
+ "declarationLine": 69,
+ "defaultValue": 0,
+ "type": "int"
+ },
+ "BlockCompositing": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 69,
+ "description": "Disables kwin compositing to fix tearing, possible fixes low FPS in windowed mode, too.",
+ "defaultValue": 0,
+ "safemodeValue": 1,
+ "type": "bool"
+ },
+ "BuildIconsFirst": {
+ "declarationFile": "/spring/rts/Game/SelectedUnitsHandler.cpp",
+ "declarationLine": 48,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "BumpWaterAnisotropy": {
+ "declarationFile": "/spring/rts/Rendering/Env/BumpWater.cpp",
+ "declarationLine": 45,
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "type": "float"
+ },
+ "BumpWaterBlurReflection": {
+ "declarationFile": "/spring/rts/Rendering/Env/BumpWater.cpp",
+ "declarationLine": 48,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "BumpWaterDepthBits": {
+ "declarationFile": "/spring/rts/Rendering/Env/BumpWater.cpp",
+ "declarationLine": 47,
+ "defaultValue": 24,
+ "minimumValue": 16,
+ "maximumValue": 32,
+ "type": "int"
+ },
+ "BumpWaterDynamicWaves": {
+ "declarationFile": "/spring/rts/Rendering/Env/BumpWater.cpp",
+ "declarationLine": 51,
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "BumpWaterEndlessOcean": {
+ "declarationFile": "/spring/rts/Rendering/Env/BumpWater.cpp",
+ "declarationLine": 50,
+ "description": "Sets whether Bumpmapped water will be drawn beyond the map edge.",
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "BumpWaterOcclusionQuery": {
+ "declarationFile": "/spring/rts/Rendering/Env/BumpWater.cpp",
+ "declarationLine": 53,
+ "deprecated": 1,
+ "type": "bool"
+ },
+ "BumpWaterReflection": {
+ "declarationFile": "/spring/rts/Rendering/Env/BumpWater.cpp",
+ "declarationLine": 43,
+ "description": "Determines the amount of objects reflected in Bumpmapped water.\n0:=off, 1:=fast (skip terrain), 2:=full",
+ "defaultValue": 1,
+ "minimumValue": 0,
+ "maximumValue": 2,
+ "headlessValue": 0,
+ "type": "int"
+ },
+ "BumpWaterRefraction": {
+ "declarationFile": "/spring/rts/Rendering/Env/BumpWater.cpp",
+ "declarationLine": 44,
+ "description": "Determines the method of refraction with Bumpmapped water.\n0:=off, 1:=screencopy, 2:=own rendering cycle (disabled)",
+ "defaultValue": 1,
+ "minimumValue": 0,
+ "maximumValue": 1,
+ "headlessValue": 0,
+ "type": "int"
+ },
+ "BumpWaterShoreWaves": {
+ "declarationFile": "/spring/rts/Rendering/Env/BumpWater.cpp",
+ "declarationLine": 49,
+ "description": "Enables rendering of shorewaves.",
+ "defaultValue": 1,
+ "safemodeValue": 0,
+ "headlessValue": 0,
+ "type": "bool"
+ },
+ "BumpWaterTexSizeReflection": {
+ "declarationFile": "/spring/rts/Rendering/Env/BumpWater.cpp",
+ "declarationLine": 42,
+ "description": "Sets the size of the framebuffer texture used to store the reflection in Bumpmapped water.",
+ "defaultValue": 512,
+ "minimumValue": 32,
+ "headlessValue": 32,
+ "type": "int"
+ },
+ "BumpWaterUseDepthTexture": {
+ "declarationFile": "/spring/rts/Rendering/Env/BumpWater.cpp",
+ "declarationLine": 46,
+ "defaultValue": 1,
+ "headlessValue": 0,
+ "type": "bool"
+ },
+ "BumpWaterUseUniforms": {
+ "declarationFile": "/spring/rts/Rendering/Env/BumpWater.cpp",
+ "declarationLine": 52,
+ "deprecated": 1,
+ "type": "bool"
+ },
+ "CamFrameTimeCorrection": {
+ "declarationFile": "/spring/rts/Game/Camera.cpp",
+ "declarationLine": 33,
+ "description": "Sets wether the camera interpolation factor should be the inverse of fps or last draw frame time (0 = lastdrawframetime, 1 = fpsinv)",
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "type": "int"
+ },
+ "CamFreeAngVelTime": {
+ "declarationFile": "/spring/rts/Game/Camera/FreeController.cpp",
+ "declarationLine": 29,
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "CamFreeAutoTilt": {
+ "declarationFile": "/spring/rts/Game/Camera/FreeController.cpp",
+ "declarationLine": 27,
+ "description": "When free camera is locked, AutoTilt will point the camera in the direction of the ground's slope",
+ "defaultValue": 150,
+ "type": "float"
+ },
+ "CamFreeEnabled": {
+ "declarationFile": "/spring/rts/Game/Camera/FreeController.cpp",
+ "declarationLine": 18,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "CamFreeFOV": {
+ "declarationFile": "/spring/rts/Game/Camera/FreeController.cpp",
+ "declarationLine": 21,
+ "defaultValue": 45,
+ "type": "float"
+ },
+ "CamFreeGoForward": {
+ "declarationFile": "/spring/rts/Game/Camera/FreeController.cpp",
+ "declarationLine": 20,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "CamFreeGravity": {
+ "declarationFile": "/spring/rts/Game/Camera/FreeController.cpp",
+ "declarationLine": 23,
+ "description": "When free camera is locked, Gravity will be used if you jump off of a ground ramp.",
+ "defaultValue": -500,
+ "type": "float"
+ },
+ "CamFreeGroundOffset": {
+ "declarationFile": "/spring/rts/Game/Camera/FreeController.cpp",
+ "declarationLine": 25,
+ "description": "Determines ground handling for the free camera.\n0 - the camera can move anywhere,\n< 0 - the camera is always offset from the ground height by -CamFreeGroundOffset\n> 0 - the camera can be \"locked\" to the ground by using SHIFT UP_ARROW. (and will use CamFreeGroundOffset as the offset). To release the lock, simply press SHIFT DOWN_ARROW.",
+ "defaultValue": 16,
+ "type": "float"
+ },
+ "CamFreeInvertAlt": {
+ "declarationFile": "/spring/rts/Game/Camera/FreeController.cpp",
+ "declarationLine": 19,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "CamFreeScrollSpeed": {
+ "declarationFile": "/spring/rts/Game/Camera/FreeController.cpp",
+ "declarationLine": 22,
+ "defaultValue": 500,
+ "type": "float"
+ },
+ "CamFreeSlide": {
+ "declarationFile": "/spring/rts/Game/Camera/FreeController.cpp",
+ "declarationLine": 24,
+ "defaultValue": 0.5,
+ "type": "float"
+ },
+ "CamFreeTiltSpeed": {
+ "declarationFile": "/spring/rts/Game/Camera/FreeController.cpp",
+ "declarationLine": 26,
+ "defaultValue": 150,
+ "type": "float"
+ },
+ "CamFreeVelTime": {
+ "declarationFile": "/spring/rts/Game/Camera/FreeController.cpp",
+ "declarationLine": 28,
+ "defaultValue": 1.5,
+ "type": "float"
+ },
+ "CamMode": {
+ "declarationFile": "/spring/rts/Game/CameraHandler.cpp",
+ "declarationLine": 41,
+ "description": "Defines the used camera. Options are:\n0 = FPS\n1 = Overhead\n2 = Spring\n3 = RotOverhead\n4 = Free\n5 = Overview",
+ "defaultValue": 2,
+ "minimumValue": 0,
+ "maximumValue": 5,
+ "type": "int"
+ },
+ "CamModeName": {
+ "declarationFile": "/spring/rts/Game/CameraHandler.cpp",
+ "declarationLine": 39,
+ "defaultValue": "",
+ "type": "std::string"
+ },
+ "CamOverheadFastScale": {
+ "declarationFile": "/spring/rts/Game/Camera/OverheadController.cpp",
+ "declarationLine": 24,
+ "description": "Scaling for CameraMoveFastMult.",
+ "defaultValue": 0.3,
+ "type": "float"
+ },
+ "CamSpringEdgeRotate": {
+ "declarationFile": "/spring/rts/Game/Camera/SpringController.cpp",
+ "declarationLine": 24,
+ "description": "Rotate camera when cursor touches screen borders.",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "CamSpringEnabled": {
+ "declarationFile": "/spring/rts/Game/Camera/SpringController.cpp",
+ "declarationLine": 18,
+ "defaultValue": 1,
+ "headlessValue": 0,
+ "type": "bool"
+ },
+ "CamSpringFOV": {
+ "declarationFile": "/spring/rts/Game/Camera/SpringController.cpp",
+ "declarationLine": 20,
+ "defaultValue": 45,
+ "type": "float"
+ },
+ "CamSpringFastScaleMouseMove": {
+ "declarationFile": "/spring/rts/Game/Camera/SpringController.cpp",
+ "declarationLine": 25,
+ "description": "Scaling for CameraMoveFastMult in spring camera mode while moving mouse.",
+ "defaultValue": 0.3,
+ "type": "float"
+ },
+ "CamSpringFastScaleMousewheelMove": {
+ "declarationFile": "/spring/rts/Game/Camera/SpringController.cpp",
+ "declarationLine": 26,
+ "description": "Scaling for CameraMoveFastMult in spring camera mode while scrolling with mouse.",
+ "defaultValue": 0.2,
+ "type": "float"
+ },
+ "CamSpringLockCardinalDirections": {
+ "declarationFile": "/spring/rts/Game/Camera/SpringController.cpp",
+ "declarationLine": 21,
+ "description": "Whether cardinal directions should be `locked` for a short time when rotating.",
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "CamSpringScrollSpeed": {
+ "declarationFile": "/spring/rts/Game/Camera/SpringController.cpp",
+ "declarationLine": 19,
+ "defaultValue": 10,
+ "type": "int"
+ },
+ "CamSpringZoomInToMousePos": {
+ "declarationFile": "/spring/rts/Game/Camera/SpringController.cpp",
+ "declarationLine": 22,
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "CamSpringZoomOutFromMousePos": {
+ "declarationFile": "/spring/rts/Game/Camera/SpringController.cpp",
+ "declarationLine": 23,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "CamTimeExponent": {
+ "declarationFile": "/spring/rts/Game/CameraHandler.cpp",
+ "declarationLine": 59,
+ "description": "Camera transitions happen at lerp(old, new, timeNorm ^ CamTimeExponent).",
+ "defaultValue": 4,
+ "minimumValue": 0,
+ "type": "float"
+ },
+ "CamTimeFactor": {
+ "declarationFile": "/spring/rts/Game/CameraHandler.cpp",
+ "declarationLine": 54,
+ "description": "Scales the speed of camera transitions, e.g. zooming or position change.",
+ "defaultValue": 1,
+ "minimumValue": 0,
+ "type": "float"
+ },
+ "CameraMoveFastMult": {
+ "declarationFile": "/spring/rts/Game/Camera.cpp",
+ "declarationLine": 25,
+ "description": "The multiplier applied to speed when camera is in movefast state.",
+ "defaultValue": 10,
+ "minimumValue": 1,
+ "type": "float"
+ },
+ "CameraMoveSlowMult": {
+ "declarationFile": "/spring/rts/Game/Camera.cpp",
+ "declarationLine": 29,
+ "description": "The multiplier applied to speed when camera is in moveslow state.",
+ "defaultValue": 0.1,
+ "maximumValue": 1,
+ "type": "float"
+ },
+ "ColorElev": {
+ "declarationFile": "/spring/rts/Map/HeightLinePalette.cpp",
+ "declarationLine": 8,
+ "description": "If heightmap (default hotkey [F1]) should be colored or not.",
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "CompressTextures": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 60,
+ "description": "Runtime compress most textures to save VideoRAM.",
+ "defaultValue": 0,
+ "safemodeValue": 1,
+ "type": "bool"
+ },
+ "CrossAlpha": {
+ "declarationFile": "/spring/rts/Game/UI/MouseHandler.cpp",
+ "declarationLine": 56,
+ "defaultValue": 0.5,
+ "type": "float"
+ },
+ "CrossMoveScale": {
+ "declarationFile": "/spring/rts/Game/UI/MouseHandler.cpp",
+ "declarationLine": 57,
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "CrossSize": {
+ "declarationFile": "/spring/rts/Game/UI/MouseHandler.cpp",
+ "declarationLine": 55,
+ "defaultValue": 12,
+ "type": "float"
+ },
+ "CubeTexGenerateMipMaps": {
+ "declarationFile": "/spring/rts/Rendering/Env/CubeMapHandler.cpp",
+ "declarationLine": 21,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "CubeTexSizeReflection": {
+ "declarationFile": "/spring/rts/Rendering/Env/CubeMapHandler.cpp",
+ "declarationLine": 20,
+ "defaultValue": 128,
+ "minimumValue": 1,
+ "type": "int"
+ },
+ "CubeTexSizeSpecular": {
+ "declarationFile": "/spring/rts/Rendering/Env/CubeMapHandler.cpp",
+ "declarationLine": 19,
+ "defaultValue": 128,
+ "minimumValue": 1,
+ "type": "int"
+ },
+ "DebugGL": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 42,
+ "description": "Enables GL debug-context and output. (see GL_ARB_debug_output)",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "DebugGLStacktraces": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 43,
+ "description": "Create a stacktrace when an OpenGL error occurs",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "DefaultLuaMenu": {
+ "declarationFile": "/spring/rts/Menu/LuaMenuController.cpp",
+ "declarationLine": 18,
+ "description": "Sets the default menu to be used when spring is started.",
+ "defaultValue": "",
+ "type": "std::string"
+ },
+ "DefaultStartScript": {
+ "declarationFile": "/spring/rts/System/SpringApp.cpp",
+ "declarationLine": 112,
+ "description": "filename of script.txt to use when no command line parameters are specified.",
+ "defaultValue": "",
+ "type": "std::string"
+ },
+ "DemoFromDemo": {
+ "declarationFile": "/spring/rts/Game/PreGame.cpp",
+ "declarationLine": 60,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "DeprecatedGLWarnLevel": {
+ "declarationFile": "/spring/rts/Lua/LuaOpenGL.cpp",
+ "declarationLine": 83,
+ "defaultValue": 0,
+ "safemodeValue": 0,
+ "headlessValue": 0,
+ "type": "int"
+ },
+ "DisableDemoVersionCheck": {
+ "declarationFile": "/spring/rts/System/LoadSave/DemoReader.cpp",
+ "declarationLine": 10,
+ "description": "Allow to play every replay file (may crash / cause undefined behaviour in replays)",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "DoubleClickTime": {
+ "declarationFile": "/spring/rts/Game/UI/MouseHandler.cpp",
+ "declarationLine": 59,
+ "description": "Double click time in milliseconds.",
+ "defaultValue": 200,
+ "type": "float"
+ },
+ "DualScreenMiniMapAspectRatio": {
+ "declarationFile": "/spring/rts/Game/UI/MiniMap.cpp",
+ "declarationLine": 71,
+ "description": "Whether minimap preserves aspect ratio on dual screen mode.",
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "DualScreenMiniMapOnLeft": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 62,
+ "description": "When set, will make the left half of the screen the minimap when DualScreenMode is set.",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "DualScreenMode": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 61,
+ "description": "Sets whether to split the screen in half, with one half for minimap and one for main screen. Right side is for minimap unless DualScreenMiniMapOnLeft is set.",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "DumpGameStateOnDesync": {
+ "declarationFile": "/spring/rts/System/GlobalConfig.cpp",
+ "declarationLine": 63,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "EdgeMoveDynamic": {
+ "declarationFile": "/spring/rts/Game/Camera.cpp",
+ "declarationLine": 22,
+ "description": "If EdgeMove scrolling speed should fade with edge distance.",
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "EdgeMoveWidth": {
+ "declarationFile": "/spring/rts/Game/Camera.cpp",
+ "declarationLine": 18,
+ "description": "The width (in percent of screen size) of the EdgeMove scrolling area.",
+ "defaultValue": 0.02,
+ "minimumValue": 0,
+ "type": "float"
+ },
+ "ExtraTextureUpdateRate": {
+ "declarationFile": "/spring/rts/Rendering/Map/InfoTexture/Legacy/LegacyInfoTextureHandler.cpp",
+ "declarationLine": 22,
+ "description": "EXTREME CPU-HEAVY ON MEDIUM/BIG MAPS! DON'T CHANGE DEFAULT!",
+ "defaultValue": 45,
+ "type": "int"
+ },
+ "FPSClampPos": {
+ "declarationFile": "/spring/rts/Game/Camera/FPSController.cpp",
+ "declarationLine": 18,
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "FPSEnabled": {
+ "declarationFile": "/spring/rts/Game/Camera/FPSController.cpp",
+ "declarationLine": 16,
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "FPSFOV": {
+ "declarationFile": "/spring/rts/Game/Camera/FPSController.cpp",
+ "declarationLine": 17,
+ "defaultValue": 45,
+ "type": "float"
+ },
+ "FPSMouseScale": {
+ "declarationFile": "/spring/rts/Game/Camera/FPSController.cpp",
+ "declarationLine": 15,
+ "defaultValue": 0.01,
+ "type": "float"
+ },
+ "FPSScrollSpeed": {
+ "declarationFile": "/spring/rts/Game/Camera/FPSController.cpp",
+ "declarationLine": 14,
+ "defaultValue": 10,
+ "type": "int"
+ },
+ "FSAA": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 80,
+ "deprecated": 1,
+ "type": "bool"
+ },
+ "FSAALevel": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 81,
+ "deprecated": 1,
+ "type": "int"
+ },
+ "FeatureDrawDistance": {
+ "declarationFile": "/spring/rts/Rendering/Features/FeatureDrawerData.cpp",
+ "declarationLine": 14,
+ "description": "Maximum distance at which features will be drawn.",
+ "defaultValue": 6000,
+ "minimumValue": 0,
+ "type": "float"
+ },
+ "FeatureFadeDistance": {
+ "declarationFile": "/spring/rts/Rendering/Features/FeatureDrawerData.cpp",
+ "declarationLine": 19,
+ "description": "Distance at which features will begin to fade from view.",
+ "defaultValue": 4500,
+ "minimumValue": 0,
+ "type": "float"
+ },
+ "FontFile": {
+ "declarationFile": "/spring/rts/Rendering/Fonts/glFont.cpp",
+ "declarationLine": 22,
+ "description": "Sets the font of Spring engine text.",
+ "defaultValue": "fonts/FreeSansBold.otf",
+ "type": "std::string"
+ },
+ "FontOutlineWeight": {
+ "declarationFile": "/spring/rts/Rendering/Fonts/glFont.cpp",
+ "declarationLine": 29,
+ "description": "Sets the opacity of Spring engine text, such as the title screen version number, clock, and basic UI. Does not affect LuaUI elements.",
+ "defaultValue": 25,
+ "type": "float"
+ },
+ "FontOutlineWidth": {
+ "declarationFile": "/spring/rts/Rendering/Fonts/glFont.cpp",
+ "declarationLine": 27,
+ "description": "Sets the width of the black outline around Spring engine text, such as the title screen version number, clock, and basic UI. Does not affect LuaUI elements.",
+ "defaultValue": 3,
+ "type": "int"
+ },
+ "FontSize": {
+ "declarationFile": "/spring/rts/Rendering/Fonts/glFont.cpp",
+ "declarationLine": 25,
+ "description": "Sets the font size (in pixels) of the MainMenu and more.",
+ "defaultValue": 23,
+ "type": "int"
+ },
+ "ForceCoreContext": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 55,
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "maximumValue": 1,
+ "type": "int"
+ },
+ "ForceDisableClipCtrl": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 51,
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "maximumValue": 1,
+ "type": "int"
+ },
+ "ForceDisableExplicitAttribLocs": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 50,
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "maximumValue": 1,
+ "type": "int"
+ },
+ "ForceDisableGL4": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 53,
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "maximumValue": 1,
+ "safemodeValue": 1,
+ "type": "int"
+ },
+ "ForceDisablePersistentMapping": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 49,
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "maximumValue": 1,
+ "type": "int"
+ },
+ "ForceDisableShaders": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 82,
+ "deprecated": 1,
+ "type": "bool"
+ },
+ "ForceSwapBuffers": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 56,
+ "defaultValue": 1,
+ "minimumValue": 0,
+ "maximumValue": 1,
+ "type": "int"
+ },
+ "Fullscreen": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 67,
+ "description": "Sets whether the game will run in fullscreen, as opposed to a window. For Windowed Fullscreen of Borderless Window, set this to 0, WindowBorderless to 1, and WindowPosX and WindowPosY to 0.",
+ "defaultValue": 1,
+ "headlessValue": 0,
+ "type": "bool"
+ },
+ "FullscreenEdgeMove": {
+ "declarationFile": "/spring/rts/Game/Game.cpp",
+ "declarationLine": 136,
+ "description": "see WindowedEdgeMove, just for fullscreen mode",
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "GLContextMajorVersion": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 45,
+ "defaultValue": 3,
+ "minimumValue": 3,
+ "maximumValue": 4,
+ "type": "int"
+ },
+ "GLContextMinorVersion": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 46,
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "maximumValue": 5,
+ "type": "int"
+ },
+ "GameEndOnConnectionLoss": {
+ "declarationFile": "/spring/rts/Game/Game.cpp",
+ "declarationLine": 132,
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "GrassDetail": {
+ "declarationFile": "/spring/rts/Rendering/Env/GrassDrawer.cpp",
+ "declarationLine": 35,
+ "description": "Sets how detailed the engine rendered grass will be on any given map.",
+ "defaultValue": 7,
+ "minimumValue": 0,
+ "headlessValue": 0,
+ "type": "int"
+ },
+ "GroundDecals": {
+ "declarationFile": "/spring/rts/Rendering/Env/IGroundDecalDrawer.cpp",
+ "declarationLine": 12,
+ "description": "Controls whether ground decals underneath buildings and ground scars from explosions will be rendered. Values >1 define how long such decals will stay.",
+ "defaultValue": 3,
+ "headlessValue": 0,
+ "type": "int"
+ },
+ "GroundDecalsParallaxMapping": {
+ "declarationFile": "/spring/rts/Rendering/Env/Decals/DecalsDrawerGL4.cpp",
+ "declarationLine": 47,
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "GroundDetail": {
+ "declarationFile": "/spring/rts/Map/SMF/SMFGroundDrawer.cpp",
+ "declarationLine": 30,
+ "description": "Controls how detailed the map geometry will be. On lowered settings, cliffs may appear to be jagged or \"melting\".",
+ "defaultValue": 60,
+ "minimumValue": 4,
+ "maximumValue": 200,
+ "headlessValue": 0,
+ "type": "int"
+ },
+ "GroundLODScaleReflection": {
+ "declarationFile": "/spring/rts/Map/BaseGroundDrawer.cpp",
+ "declarationLine": 7,
+ "defaultValue": 1,
+ "headlessValue": 0,
+ "type": "float"
+ },
+ "GroundLODScaleRefraction": {
+ "declarationFile": "/spring/rts/Map/BaseGroundDrawer.cpp",
+ "declarationLine": 8,
+ "defaultValue": 1,
+ "headlessValue": 0,
+ "type": "float"
+ },
+ "GroundLODScaleTerrainReflection": {
+ "declarationFile": "/spring/rts/Map/BaseGroundDrawer.cpp",
+ "declarationLine": 9,
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "GroundNormalTextureHighPrecision": {
+ "declarationFile": "/spring/rts/Map/SMF/SMFReadMap.cpp",
+ "declarationLine": 35,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "GroundScarAlphaFade": {
+ "declarationFile": "/spring/rts/Rendering/Env/Decals/GroundDecalHandler.cpp",
+ "declarationLine": 55,
+ "defaultValue": 0,
+ "type": "int"
+ },
+ "GuiOpacity": {
+ "declarationFile": "/spring/rts/Game/Game.cpp",
+ "declarationLine": 142,
+ "description": "Sets the opacity of the built-in Spring UI. Generally has no effect on LuaUI widgets. Can be set in-game using shift+, to decrease and shift+. to increase.",
+ "defaultValue": 0.8,
+ "minimumValue": 0,
+ "maximumValue": 1,
+ "type": "float"
+ },
+ "HangTimeout": {
+ "declarationFile": "/spring/rts/System/Platform/Watchdog.cpp",
+ "declarationLine": 24,
+ "description": "Number of seconds that, if spent in the same code segment, indicate a hang; -1 to disable.",
+ "defaultValue": 60,
+ "minimumValue": -1,
+ "maximumValue": 600,
+ "type": "int"
+ },
+ "HardwareCursor": {
+ "declarationFile": "/spring/rts/Game/UI/MouseHandler.cpp",
+ "declarationLine": 50,
+ "description": "Sets hardware mouse cursor rendering. If you have a low framerate, your mouse cursor will seem \"laggy\". Setting hardware cursor will render the mouse cursor separately from spring and the mouse will behave normally. Note, not all GPU drivers support it in fullscreen mode!",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "HighResInfoTexture": {
+ "declarationFile": "/spring/rts/Rendering/Map/InfoTexture/Modern/Combiner.cpp",
+ "declarationLine": 14,
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "HighResLos": {
+ "declarationFile": "/spring/rts/Rendering/Map/InfoTexture/Legacy/LegacyInfoTextureHandler.cpp",
+ "declarationLine": 21,
+ "description": "Controls whether LOS (\"L view\") edges are rendered in high resolution. Resource heavy!",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "HostIPDefault": {
+ "declarationFile": "/spring/rts/Game/ClientSetup.cpp",
+ "declarationLine": 16,
+ "description": "Default IP to use for hosting if not specified in script.txt",
+ "defaultValue": "localhost",
+ "dedicatedValue": "",
+ "type": "std::string"
+ },
+ "HostPortDefault": {
+ "declarationFile": "/spring/rts/Game/ClientSetup.cpp",
+ "declarationLine": 17,
+ "description": "Default Port to use for hosting if not specified in script.txt",
+ "defaultValue": 8452,
+ "minimumValue": 0,
+ "maximumValue": 65535,
+ "type": "int"
+ },
+ "InfoConsoleGeometry": {
+ "declarationFile": "/spring/rts/Game/UI/InfoConsole.cpp",
+ "declarationLine": 14,
+ "defaultValue": "0.26 0.96 0.41 0.205",
+ "type": "std::string"
+ },
+ "InfoMessageTime": {
+ "declarationFile": "/spring/rts/Game/UI/InfoConsole.cpp",
+ "declarationLine": 13,
+ "description": "Time until old messages disappear from the ingame console.",
+ "defaultValue": 10,
+ "type": "int"
+ },
+ "InitialNetworkTimeout": {
+ "declarationFile": "/spring/rts/System/GlobalConfig.cpp",
+ "declarationLine": 15,
+ "defaultValue": 30,
+ "minimumValue": 10,
+ "type": "int"
+ },
+ "InputTextGeo": {
+ "declarationFile": "/spring/rts/Game/Game.cpp",
+ "declarationLine": 143,
+ "defaultValue": "",
+ "type": "std::string"
+ },
+ "InvertMouse": {
+ "declarationFile": "/spring/rts/Game/UI/MouseHandler.cpp",
+ "declarationLine": 51,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "InvertQueueKey": {
+ "declarationFile": "/spring/rts/Game/UI/GuiHandler.cpp",
+ "declarationLine": 60,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "KeyChainTimeout": {
+ "declarationFile": "/spring/rts/Game/UI/KeyBindings.cpp",
+ "declarationLine": 29,
+ "description": "Timeout in milliseconds waiting for a key chain shortcut.",
+ "defaultValue": 750,
+ "minimumValue": 0,
+ "type": "int"
+ },
+ "LODScale": {
+ "declarationFile": "/spring/rts/Rendering/LuaObjectDrawer.cpp",
+ "declarationLine": 36,
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "LODScaleReflection": {
+ "declarationFile": "/spring/rts/Rendering/LuaObjectDrawer.cpp",
+ "declarationLine": 38,
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "LODScaleRefraction": {
+ "declarationFile": "/spring/rts/Rendering/LuaObjectDrawer.cpp",
+ "declarationLine": 39,
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "LODScaleShadow": {
+ "declarationFile": "/spring/rts/Rendering/LuaObjectDrawer.cpp",
+ "declarationLine": 37,
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "LastSelectedMap": {
+ "declarationFile": "/spring/rts/Menu/SelectionWidget.cpp",
+ "declarationLine": 29,
+ "description": "Stores the previously played map.",
+ "defaultValue": "No map selected",
+ "type": "std::string"
+ },
+ "LastSelectedMod": {
+ "declarationFile": "/spring/rts/Menu/SelectionWidget.cpp",
+ "declarationLine": 28,
+ "description": "Stores the previously played game.",
+ "defaultValue": "No game selected",
+ "type": "std::string"
+ },
+ "LastSelectedScript": {
+ "declarationFile": "/spring/rts/Menu/SelectionWidget.cpp",
+ "declarationLine": 30,
+ "description": "Stores the previously played AI.",
+ "defaultValue": "No script selected",
+ "type": "std::string"
+ },
+ "LastSelectedSetting": {
+ "declarationFile": "/spring/rts/Menu/SelectMenu.cpp",
+ "declarationLine": 46,
+ "description": "Stores the previously selected setting, when editing settings within the Spring main menu.",
+ "defaultValue": "",
+ "type": "std::string"
+ },
+ "LinkIncomingMaxPacketRate": {
+ "declarationFile": "/spring/rts/System/GlobalConfig.cpp",
+ "declarationLine": 43,
+ "defaultValue": 64,
+ "minimumValue": 0,
+ "type": "int"
+ },
+ "LinkIncomingMaxWaitingPackets": {
+ "declarationFile": "/spring/rts/System/GlobalConfig.cpp",
+ "declarationLine": 49,
+ "defaultValue": 512,
+ "minimumValue": 0,
+ "type": "int"
+ },
+ "LinkIncomingPeakBandwidth": {
+ "declarationFile": "/spring/rts/System/GlobalConfig.cpp",
+ "declarationLine": 39,
+ "defaultValue": 32768,
+ "minimumValue": 0,
+ "type": "int"
+ },
+ "LinkIncomingSustainedBandwidth": {
+ "declarationFile": "/spring/rts/System/GlobalConfig.cpp",
+ "declarationLine": 35,
+ "defaultValue": 2048,
+ "minimumValue": 0,
+ "type": "int"
+ },
+ "LinkOutgoingBandwidth": {
+ "declarationFile": "/spring/rts/System/GlobalConfig.cpp",
+ "declarationLine": 31,
+ "defaultValue": 65536,
+ "minimumValue": 0,
+ "type": "int"
+ },
+ "LoadBadSaves": {
+ "declarationFile": "/spring/rts/Game/PreGame.cpp",
+ "declarationLine": 61,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "LoadingMT": {
+ "declarationFile": "/spring/rts/Game/LoadScreen.cpp",
+ "declarationLine": 46,
+ "description": "Experimental option to load the game in separate thread. Expect visual glitches, crashes and deadlocks",
+ "defaultValue": 0,
+ "safemodeValue": 0,
+ "type": "int"
+ },
+ "LogClientData": {
+ "declarationFile": "/spring/rts/Net/NetCommands.cpp",
+ "declarationLine": 43,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "LogFlushLevel": {
+ "declarationFile": "/spring/rts/System/LogOutput.cpp",
+ "declarationLine": 38,
+ "description": "Flush the logfile when a message's level exceeds this value. ERROR is flushed by default, WARNING is not.",
+ "defaultValue": 50,
+ "type": "int"
+ },
+ "LogRepeatLimit": {
+ "declarationFile": "/spring/rts/System/LogOutput.cpp",
+ "declarationLine": 42,
+ "description": "Allow at most this many consecutive identical messages to be logged.",
+ "defaultValue": 10,
+ "type": "int"
+ },
+ "LogSections": {
+ "declarationFile": "/spring/rts/System/LogOutput.cpp",
+ "declarationLine": 33,
+ "description": "Comma-separated list of enabled logsections, see infolog.txt / console output for possible values.",
+ "defaultValue": "",
+ "type": "std::string"
+ },
+ "LuaGarbageCollectionMemLoadMult": {
+ "declarationFile": "/spring/rts/Lua/LuaHandle.cpp",
+ "declarationLine": 59,
+ "defaultValue": 1.33,
+ "minimumValue": 1,
+ "maximumValue": 100,
+ "type": "float"
+ },
+ "LuaGarbageCollectionRunTimeMult": {
+ "declarationFile": "/spring/rts/Lua/LuaHandle.cpp",
+ "declarationLine": 60,
+ "description": "in milliseconds",
+ "defaultValue": 5,
+ "minimumValue": 1,
+ "type": "float"
+ },
+ "LuaShaders": {
+ "declarationFile": "/spring/rts/Lua/LuaOpenGL.cpp",
+ "declarationLine": 82,
+ "defaultValue": 1,
+ "safemodeValue": 0,
+ "headlessValue": 0,
+ "type": "bool"
+ },
+ "LuaSocketEnabled": {
+ "declarationFile": "/spring/rts/Lua/LuaUI.cpp",
+ "declarationLine": 47,
+ "description": "Enable LuaSocket support, allows Lua widgets to make TCP/UDP connections",
+ "readOnly": 1,
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "LuaWritableConfigFile": {
+ "declarationFile": "/spring/rts/System/GlobalConfig.cpp",
+ "declarationLine": 60,
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "MSAALevel": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 47,
+ "description": "Enables multisample anti-aliasing; 'level' is the number of samples used.",
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "maximumValue": 32,
+ "type": "int"
+ },
+ "MapBorder": {
+ "declarationFile": "/spring/rts/Map/SMF/SMFGroundDrawer.cpp",
+ "declarationLine": 36,
+ "description": "Draws a solid border at the edges of the map.",
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "MaxDynamicMapLights": {
+ "declarationFile": "/spring/rts/Map/SMF/SMFGroundDrawer.cpp",
+ "declarationLine": 39,
+ "defaultValue": 1,
+ "minimumValue": 0,
+ "type": "int"
+ },
+ "MaxDynamicModelLights": {
+ "declarationFile": "/spring/rts/Rendering/Units/UnitDrawer.cpp",
+ "declarationLine": 63,
+ "defaultValue": 1,
+ "minimumValue": 0,
+ "type": "int"
+ },
+ "MaxNanoParticles": {
+ "declarationFile": "/spring/rts/Sim/Projectiles/ProjectileHandler.cpp",
+ "declarationLine": 42,
+ "defaultValue": 2000,
+ "minimumValue": 0,
+ "headlessValue": 0,
+ "type": "int"
+ },
+ "MaxParticles": {
+ "declarationFile": "/spring/rts/Sim/Projectiles/ProjectileHandler.cpp",
+ "declarationLine": 41,
+ "defaultValue": 10000,
+ "minimumValue": 0,
+ "headlessValue": 0,
+ "type": "int"
+ },
+ "MaxSounds": {
+ "declarationFile": "/spring/rts/System/Sound/ISound.cpp",
+ "declarationLine": 30,
+ "description": "Maximum sounds played in parallel.",
+ "defaultValue": 128,
+ "minimumValue": 1,
+ "headlessValue": 1,
+ "type": "int"
+ },
+ "MaxTextureAtlasSizeX": {
+ "declarationFile": "/spring/rts/Rendering/Textures/TextureAtlas.cpp",
+ "declarationLine": 22,
+ "defaultValue": 2048,
+ "minimumValue": 512,
+ "maximumValue": 32768,
+ "type": "int"
+ },
+ "MaxTextureAtlasSizeY": {
+ "declarationFile": "/spring/rts/Rendering/Textures/TextureAtlas.cpp",
+ "declarationLine": 23,
+ "defaultValue": 2048,
+ "minimumValue": 512,
+ "maximumValue": 32768,
+ "type": "int"
+ },
+ "MaximumTransmissionUnit": {
+ "declarationFile": "/spring/rts/System/GlobalConfig.cpp",
+ "declarationLine": 27,
+ "defaultValue": 1400,
+ "minimumValue": 400,
+ "type": "int"
+ },
+ "MenuArchive": {
+ "declarationFile": "/spring/rts/Menu/SelectMenu.cpp",
+ "declarationLine": 47,
+ "description": "Archive name for the default Menu.",
+ "defaultValue": "Spring Bitmaps",
+ "type": "std::string"
+ },
+ "MiddleClickScrollSpeed": {
+ "declarationFile": "/spring/rts/Game/Camera/OverheadController.cpp",
+ "declarationLine": 18,
+ "defaultValue": 0.01,
+ "type": "float"
+ },
+ "MiniMapButtonSize": {
+ "declarationFile": "/spring/rts/Game/UI/MiniMap.cpp",
+ "declarationLine": 53,
+ "defaultValue": 16,
+ "type": "int"
+ },
+ "MiniMapCanDraw": {
+ "declarationFile": "/spring/rts/Game/InMapDraw.cpp",
+ "declarationLine": 28,
+ "description": "Enables drawing with cursor over MiniMap.",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "MiniMapCanFlip": {
+ "declarationFile": "/spring/rts/Game/UI/MiniMap.cpp",
+ "declarationLine": 73,
+ "description": "Whether minimap inverts coordinates when camera Y rotation is between 90 and 270 degrees.",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "MiniMapCursorScale": {
+ "declarationFile": "/spring/rts/Game/UI/MiniMap.cpp",
+ "declarationLine": 60,
+ "defaultValue": -0.5,
+ "type": "float"
+ },
+ "MiniMapDrawCommands": {
+ "declarationFile": "/spring/rts/Game/UI/MiniMap.cpp",
+ "declarationLine": 63,
+ "defaultValue": 1,
+ "minimumValue": 0,
+ "headlessValue": 0,
+ "type": "int"
+ },
+ "MiniMapDrawProjectiles": {
+ "declarationFile": "/spring/rts/Game/UI/MiniMap.cpp",
+ "declarationLine": 65,
+ "defaultValue": 1,
+ "headlessValue": 0,
+ "type": "bool"
+ },
+ "MiniMapFullProxy": {
+ "declarationFile": "/spring/rts/Game/UI/MiniMap.cpp",
+ "declarationLine": 52,
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "MiniMapGeometry": {
+ "declarationFile": "/spring/rts/Game/UI/MiniMap.cpp",
+ "declarationLine": 51,
+ "defaultValue": "2 2 200 200",
+ "type": "std::string"
+ },
+ "MiniMapIcons": {
+ "declarationFile": "/spring/rts/Game/UI/MiniMap.cpp",
+ "declarationLine": 61,
+ "defaultValue": 1,
+ "headlessValue": 0,
+ "type": "bool"
+ },
+ "MiniMapMarker": {
+ "declarationFile": "/spring/rts/Game/UI/GuiHandler.cpp",
+ "declarationLine": 59,
+ "defaultValue": 1,
+ "headlessValue": 0,
+ "type": "bool"
+ },
+ "MiniMapMouseWheel": {
+ "declarationFile": "/spring/rts/Game/UI/MouseHandler.cpp",
+ "declarationLine": 53,
+ "description": "Whether MiniMap responds to MouseWheel events",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "MiniMapRefreshRate": {
+ "declarationFile": "/spring/rts/Game/UI/MiniMap.cpp",
+ "declarationLine": 69,
+ "description": "The refresh rate of the async MiniMap texture. Needs MiniMapRenderToTexture to be true. Value of \"0\" autoselects between 10-60FPS.",
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "type": "int"
+ },
+ "MiniMapRenderToTexture": {
+ "declarationFile": "/spring/rts/Game/UI/MiniMap.cpp",
+ "declarationLine": 68,
+ "description": "Asynchronous render MiniMap to a texture independent of screen FPS.",
+ "defaultValue": 1,
+ "safemodeValue": 0,
+ "type": "bool"
+ },
+ "MiniMapUnitExp": {
+ "declarationFile": "/spring/rts/Game/UI/MiniMap.cpp",
+ "declarationLine": 59,
+ "defaultValue": 0.25,
+ "type": "float"
+ },
+ "MiniMapUnitSize": {
+ "declarationFile": "/spring/rts/Game/UI/MiniMap.cpp",
+ "declarationLine": 55,
+ "defaultValue": 2.5,
+ "minimumValue": 0,
+ "type": "float"
+ },
+ "MinimizeOnFocusLoss": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 65,
+ "description": "When set to 1 minimize Window if it loses key focus when in fullscreen mode.",
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "maximumValue": 1,
+ "type": "int"
+ },
+ "MouseDragBoxCommandThreshold": {
+ "declarationFile": "/spring/rts/Game/UI/MouseHandler.cpp",
+ "declarationLine": 65,
+ "description": "Distance in pixels which the mouse must be dragged to trigger a rectangular area command.",
+ "defaultValue": 16,
+ "type": "int"
+ },
+ "MouseDragCircleCommandThreshold": {
+ "declarationFile": "/spring/rts/Game/UI/MouseHandler.cpp",
+ "declarationLine": 64,
+ "description": "Distance in pixels which the mouse must be dragged to trigger a circular area command.",
+ "defaultValue": 4,
+ "type": "int"
+ },
+ "MouseDragFrontCommandThreshold": {
+ "declarationFile": "/spring/rts/Game/UI/MouseHandler.cpp",
+ "declarationLine": 66,
+ "description": "Distance in pixels which the mouse must be dragged to trigger a formation front command.",
+ "defaultValue": 30,
+ "type": "int"
+ },
+ "MouseDragScrollThreshold": {
+ "declarationFile": "/spring/rts/Game/UI/MouseHandler.cpp",
+ "declarationLine": 62,
+ "defaultValue": 0.3,
+ "type": "float"
+ },
+ "MouseDragSelectionThreshold": {
+ "declarationFile": "/spring/rts/Game/UI/MouseHandler.cpp",
+ "declarationLine": 63,
+ "description": "Distance in pixels which the mouse must be dragged to trigger a selection box.",
+ "defaultValue": 4,
+ "type": "int"
+ },
+ "MouseRelativeModeWarp": {
+ "declarationFile": "/spring/rts/Game/UI/MouseHandler.cpp",
+ "declarationLine": 52,
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "NetworkLossFactor": {
+ "declarationFile": "/spring/rts/System/GlobalConfig.cpp",
+ "declarationLine": 10,
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "maximumValue": 2,
+ "type": "int"
+ },
+ "NetworkTimeout": {
+ "declarationFile": "/spring/rts/System/GlobalConfig.cpp",
+ "declarationLine": 19,
+ "defaultValue": 120,
+ "minimumValue": 0,
+ "type": "int"
+ },
+ "NoHelperAIs": {
+ "declarationFile": "/spring/rts/System/StartScriptGen.cpp",
+ "declarationLine": 12,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "OverheadEnabled": {
+ "declarationFile": "/spring/rts/Game/Camera/OverheadController.cpp",
+ "declarationLine": 21,
+ "defaultValue": 1,
+ "headlessValue": 0,
+ "type": "bool"
+ },
+ "OverheadFOV": {
+ "declarationFile": "/spring/rts/Game/Camera/OverheadController.cpp",
+ "declarationLine": 22,
+ "defaultValue": 45,
+ "type": "float"
+ },
+ "OverheadMaxHeightFactor": {
+ "declarationFile": "/spring/rts/Game/Camera/OverheadController.cpp",
+ "declarationLine": 23,
+ "description": "float multiplier for maximum overhead camera height",
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "OverheadScrollSpeed": {
+ "declarationFile": "/spring/rts/Game/Camera/OverheadController.cpp",
+ "declarationLine": 19,
+ "defaultValue": 10,
+ "type": "int"
+ },
+ "OverheadTiltSpeed": {
+ "declarationFile": "/spring/rts/Game/Camera/OverheadController.cpp",
+ "declarationLine": 20,
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "PathingThreadCount": {
+ "declarationFile": "/spring/rts/Sim/Path/QTPFS/PathManager.cpp",
+ "declarationLine": 38,
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "safemodeValue": 1,
+ "type": "int"
+ },
+ "PitchAdjust": {
+ "declarationFile": "/spring/rts/System/Sound/ISound.cpp",
+ "declarationLine": 31,
+ "description": "Adjusts sound pitch proportional to [if set to 1, the square root of] game speed. Set to 2 for linear scaling.",
+ "defaultValue": 0,
+ "type": "int"
+ },
+ "PreloadModels": {
+ "declarationFile": "/spring/rts/Rendering/WorldDrawer.cpp",
+ "declarationLine": 53,
+ "description": "The engine will preload all models",
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "ROAM": {
+ "declarationFile": "/spring/rts/Map/SMF/SMFGroundDrawer.cpp",
+ "declarationLine": 49,
+ "description": "Use ROAM for terrain mesh rendering: 0 to disable, 1=VBO mode to enable.",
+ "defaultValue": 1,
+ "minimumValue": 0,
+ "maximumValue": 1,
+ "type": "int"
+ },
+ "RapidTagResolutionOrder": {
+ "declarationFile": "/spring/rts/System/FileSystem/RapidHandler.cpp",
+ "declarationLine": 91,
+ "description": "';' separated list of domains, preference order for resolving package from rapid tags",
+ "defaultValue": "",
+ "type": "std::string"
+ },
+ "ReconnectTimeout": {
+ "declarationFile": "/spring/rts/System/GlobalConfig.cpp",
+ "declarationLine": 23,
+ "defaultValue": 15,
+ "minimumValue": 0,
+ "type": "int"
+ },
+ "RendererHash": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 79,
+ "deprecated": 1,
+ "type": "int"
+ },
+ "RotOverheadClampMap": {
+ "declarationFile": "/spring/rts/Game/Camera/RotOverheadController.cpp",
+ "declarationLine": 19,
+ "defaultValue": 1,
+ "headlessValue": 1,
+ "type": "bool"
+ },
+ "RotOverheadEnabled": {
+ "declarationFile": "/spring/rts/Game/Camera/RotOverheadController.cpp",
+ "declarationLine": 17,
+ "defaultValue": 1,
+ "headlessValue": 0,
+ "type": "bool"
+ },
+ "RotOverheadFOV": {
+ "declarationFile": "/spring/rts/Game/Camera/RotOverheadController.cpp",
+ "declarationLine": 18,
+ "defaultValue": 45,
+ "type": "float"
+ },
+ "RotOverheadMouseScale": {
+ "declarationFile": "/spring/rts/Game/Camera/RotOverheadController.cpp",
+ "declarationLine": 15,
+ "defaultValue": 0.01,
+ "type": "float"
+ },
+ "RotOverheadScrollSpeed": {
+ "declarationFile": "/spring/rts/Game/Camera/RotOverheadController.cpp",
+ "declarationLine": 16,
+ "defaultValue": 10,
+ "type": "int"
+ },
+ "RotateLogFiles": {
+ "declarationFile": "/spring/rts/System/LogOutput.cpp",
+ "declarationLine": 29,
+ "description": "Rotate logfiles, old logfiles will be moved into the subfolder \"log\".",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "SMFTexAniso": {
+ "declarationFile": "/spring/rts/Map/SMF/SMFReadMap.cpp",
+ "declarationLine": 36,
+ "defaultValue": 4,
+ "minimumValue": 0,
+ "type": "float"
+ },
+ "SSMFTexAniso": {
+ "declarationFile": "/spring/rts/Map/SMF/SMFReadMap.cpp",
+ "declarationLine": 37,
+ "defaultValue": 4,
+ "minimumValue": 0,
+ "type": "float"
+ },
+ "ScreenshotCounter": {
+ "declarationFile": "/spring/rts/Rendering/Screenshot.cpp",
+ "declarationLine": 19,
+ "defaultValue": 0,
+ "type": "int"
+ },
+ "ScrollWheelSpeed": {
+ "declarationFile": "/spring/rts/Game/UI/MouseHandler.cpp",
+ "declarationLine": 60,
+ "defaultValue": -25,
+ "minimumValue": -255,
+ "maximumValue": 255,
+ "type": "float"
+ },
+ "ServerLogDebugMessages": {
+ "declarationFile": "/spring/rts/Net/GameServer.cpp",
+ "declarationLine": 77,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "ServerLogInfoMessages": {
+ "declarationFile": "/spring/rts/Net/GameServer.cpp",
+ "declarationLine": 76,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "ServerRecordDemos": {
+ "declarationFile": "/spring/rts/Net/GameServer.cpp",
+ "declarationLine": 75,
+ "defaultValue": 0,
+ "dedicatedValue": 1,
+ "type": "bool"
+ },
+ "ServerSleepTime": {
+ "declarationFile": "/spring/rts/Net/GameServer.cpp",
+ "declarationLine": 70,
+ "description": "number of milliseconds to sleep per tick",
+ "defaultValue": 5,
+ "type": "int"
+ },
+ "SetCoreAffinity": {
+ "declarationFile": "/spring/rts/System/SpringApp.cpp",
+ "declarationLine": 105,
+ "description": "Defines a bitmask indicating which CPU cores the main-thread should use.",
+ "defaultValue": "0",
+ "safemodeValue": "1",
+ "type": "unsigned"
+ },
+ "ShadowColorMode": {
+ "declarationFile": "/spring/rts/Rendering/ShadowHandler.cpp",
+ "declarationLine": 34,
+ "description": "Whether the colorbuffer of shadowmap FBO is RGB vs greyscale(to conserve some VRAM)",
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "ShadowMapSize": {
+ "declarationFile": "/spring/rts/Rendering/ShadowHandler.cpp",
+ "declarationLine": 32,
+ "description": "Sets the resolution of shadows. Higher numbers increase quality at the cost of performance.",
+ "defaultValue": 2048,
+ "minimumValue": 32,
+ "type": "int"
+ },
+ "ShadowProjectionMode": {
+ "declarationFile": "/spring/rts/Rendering/ShadowHandler.cpp",
+ "declarationLine": 33,
+ "defaultValue": 1,
+ "type": "int"
+ },
+ "Shadows": {
+ "declarationFile": "/spring/rts/Rendering/ShadowHandler.cpp",
+ "declarationLine": 31,
+ "description": "Sets whether shadows are rendered.\n-1:=forceoff, 0:=off, 1:=full, 2:=fast (skip terrain)",
+ "defaultValue": 2,
+ "minimumValue": -1,
+ "safemodeValue": -1,
+ "headlessValue": -1,
+ "type": "int"
+ },
+ "ShowClock": {
+ "declarationFile": "/spring/rts/Game/Game.cpp",
+ "declarationLine": 139,
+ "description": "Displays a clock on the top-right corner of the screen showing the elapsed time of the current game.",
+ "defaultValue": 1,
+ "headlessValue": 0,
+ "type": "bool"
+ },
+ "ShowFPS": {
+ "declarationFile": "/spring/rts/Game/Game.cpp",
+ "declarationLine": 138,
+ "description": "Displays current framerate.",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "ShowPlayerInfo": {
+ "declarationFile": "/spring/rts/Game/Game.cpp",
+ "declarationLine": 141,
+ "defaultValue": 1,
+ "headlessValue": 0,
+ "type": "int"
+ },
+ "ShowSpeed": {
+ "declarationFile": "/spring/rts/Game/Game.cpp",
+ "declarationLine": 140,
+ "description": "Displays current game speed.",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "SimpleMiniMapColors": {
+ "declarationFile": "/spring/rts/Game/UI/MiniMap.cpp",
+ "declarationLine": 66,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "SmallFontFile": {
+ "declarationFile": "/spring/rts/Rendering/Fonts/glFont.cpp",
+ "declarationLine": 23,
+ "description": "Sets the font of Spring engine small text.",
+ "defaultValue": "fonts/FreeSansBold.otf",
+ "type": "std::string"
+ },
+ "SmallFontOutlineWeight": {
+ "declarationFile": "/spring/rts/Rendering/Fonts/glFont.cpp",
+ "declarationLine": 30,
+ "description": "see FontOutlineWeight",
+ "defaultValue": 10,
+ "type": "float"
+ },
+ "SmallFontOutlineWidth": {
+ "declarationFile": "/spring/rts/Rendering/Fonts/glFont.cpp",
+ "declarationLine": 28,
+ "description": "see FontOutlineWidth",
+ "defaultValue": 2,
+ "type": "int"
+ },
+ "SmallFontSize": {
+ "declarationFile": "/spring/rts/Rendering/Fonts/glFont.cpp",
+ "declarationLine": 26,
+ "description": "Sets the font size (in pixels) of the engine GUIs and more.",
+ "defaultValue": 14,
+ "type": "int"
+ },
+ "SmoothTimeOffset": {
+ "declarationFile": "/spring/rts/Game/Game.cpp",
+ "declarationLine": 145,
+ "description": "Enables frametimeoffset smoothing, 0 = off (old version), -1 = forced 0.5, 1-20 smooth, recommended = 2-3",
+ "defaultValue": 0,
+ "headlessValue": 0,
+ "type": "int"
+ },
+ "SoftParticles": {
+ "declarationFile": "/spring/rts/Rendering/Env/Particles/ProjectileDrawer.cpp",
+ "declarationLine": 44,
+ "description": "Soften up CEG particles on clipping edges",
+ "defaultValue": 1,
+ "safemodeValue": 0,
+ "type": "int"
+ },
+ "Sound": {
+ "declarationFile": "/spring/rts/System/Sound/ISound.cpp",
+ "declarationLine": 24,
+ "description": "Enables (OpenAL) or disables sound.",
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "SourcePort": {
+ "declarationFile": "/spring/rts/Net/Protocol/NetProtocol.cpp",
+ "declarationLine": 21,
+ "defaultValue": 0,
+ "type": "int"
+ },
+ "SpeedControl": {
+ "declarationFile": "/spring/rts/Net/GameServer.cpp",
+ "declarationLine": 71,
+ "description": "Sets how server adjusts speed according to player's load (CPU), 1: use average, 2: use highest",
+ "defaultValue": 1,
+ "minimumValue": 1,
+ "maximumValue": 2,
+ "type": "int"
+ },
+ "SplashScreenDir": {
+ "declarationFile": "/spring/rts/System/SpringApp.cpp",
+ "declarationLine": 113,
+ "defaultValue": ".",
+ "type": "std::string"
+ },
+ "SpringData": {
+ "declarationFile": "/spring/rts/System/FileSystem/DataDirLocater.cpp",
+ "declarationLine": 34,
+ "description": "List of additional data-directories, separated by ';' on Windows and ':' on other OSs",
+ "readOnly": 1,
+ "defaultValue": "",
+ "type": "std::string"
+ },
+ "SpringDataRoot": {
+ "declarationFile": "/spring/rts/System/FileSystem/DataDirLocater.cpp",
+ "declarationLine": 39,
+ "description": "Optional custom data-directory content root ('base', 'maps', ...) to scan for archives",
+ "readOnly": 1,
+ "defaultValue": "",
+ "type": "std::string"
+ },
+ "TCPAllowConnect": {
+ "declarationFile": "/spring/rts/lib/luasocket/src/restrictions.cpp",
+ "declarationLine": 24,
+ "readOnly": 1,
+ "defaultValue": "*",
+ "type": "std::string"
+ },
+ "TCPAllowListen": {
+ "declarationFile": "/spring/rts/lib/luasocket/src/restrictions.cpp",
+ "declarationLine": 25,
+ "readOnly": 1,
+ "defaultValue": "*",
+ "type": "std::string"
+ },
+ "TeamHighlight": {
+ "declarationFile": "/spring/rts/System/GlobalConfig.cpp",
+ "declarationLine": 53,
+ "defaultValue": 1,
+ "minimumValue": 0,
+ "maximumValue": 2,
+ "type": "int"
+ },
+ "TeamNanoSpray": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 63,
+ "defaultValue": 1,
+ "headlessValue": 0,
+ "type": "bool"
+ },
+ "TextureMemPoolSize": {
+ "declarationFile": "/spring/rts/System/SpringApp.cpp",
+ "declarationLine": 106,
+ "description": "Set to 0 to disable, otherwise specify a predefined memory to serve Bitmap allocation requests",
+ "defaultValue": "512",
+ "minimumValue": "0",
+ "type": "unsigned"
+ },
+ "TooltipGeometry": {
+ "declarationFile": "/spring/rts/Game/UI/TooltipConsole.cpp",
+ "declarationLine": 28,
+ "defaultValue": "0.0 0.0 0.41 0.1",
+ "type": "std::string"
+ },
+ "TooltipOutlineFont": {
+ "declarationFile": "/spring/rts/Game/UI/TooltipConsole.cpp",
+ "declarationLine": 29,
+ "defaultValue": 1,
+ "headlessValue": 0,
+ "type": "bool"
+ },
+ "UDPAllowConnect": {
+ "declarationFile": "/spring/rts/lib/luasocket/src/restrictions.cpp",
+ "declarationLine": 26,
+ "readOnly": 1,
+ "defaultValue": "",
+ "type": "std::string"
+ },
+ "UDPAllowListen": {
+ "declarationFile": "/spring/rts/lib/luasocket/src/restrictions.cpp",
+ "declarationLine": 27,
+ "readOnly": 1,
+ "defaultValue": "*",
+ "type": "std::string"
+ },
+ "UDPConnectionLogDebugMessages": {
+ "declarationFile": "/spring/rts/System/Net/UDPConnection.cpp",
+ "declarationLine": 20,
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "UnitIconDist": {
+ "declarationFile": "/spring/rts/Rendering/Units/UnitDrawer.cpp",
+ "declarationLine": 55,
+ "defaultValue": 200,
+ "headlessValue": 0,
+ "type": "int"
+ },
+ "UnitIconFadeStart": {
+ "declarationFile": "/spring/rts/Rendering/Units/UnitDrawer.cpp",
+ "declarationLine": 57,
+ "defaultValue": 3000,
+ "minimumValue": 1,
+ "maximumValue": 10000,
+ "type": "float"
+ },
+ "UnitIconFadeVanish": {
+ "declarationFile": "/spring/rts/Rendering/Units/UnitDrawer.cpp",
+ "declarationLine": 58,
+ "defaultValue": 1000,
+ "minimumValue": 1,
+ "maximumValue": 10000,
+ "type": "float"
+ },
+ "UnitIconScaleUI": {
+ "declarationFile": "/spring/rts/Rendering/Units/UnitDrawer.cpp",
+ "declarationLine": 56,
+ "defaultValue": 1,
+ "minimumValue": 0.1,
+ "maximumValue": 10,
+ "type": "float"
+ },
+ "UnitIconsAsUI": {
+ "declarationFile": "/spring/rts/Rendering/Units/UnitDrawer.cpp",
+ "declarationLine": 60,
+ "description": "Draw unit icons like it is an UI element and not like unit's LOD.",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "UnitIconsHideWithUI": {
+ "declarationFile": "/spring/rts/Rendering/Units/UnitDrawer.cpp",
+ "declarationLine": 61,
+ "description": "Hide unit icons when UI is hidden.",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "UnitLodDist": {
+ "declarationFile": "/spring/rts/Rendering/Common/ModelDrawerData.cpp",
+ "declarationLine": 3,
+ "deprecated": 1,
+ "defaultValue": 1000,
+ "headlessValue": 0,
+ "type": "int"
+ },
+ "UnitTransparency": {
+ "declarationFile": "/spring/rts/Rendering/Units/UnitDrawer.cpp",
+ "declarationLine": 59,
+ "defaultValue": 0.7,
+ "type": "float"
+ },
+ "UseDistToGroundForIcons": {
+ "declarationFile": "/spring/rts/Game/Camera/CameraController.cpp",
+ "declarationLine": 11,
+ "defaultValue": 0.95,
+ "type": "float"
+ },
+ "UseEFX": {
+ "declarationFile": "/spring/rts/System/Sound/ISound.cpp",
+ "declarationLine": 26,
+ "defaultValue": 1,
+ "safemodeValue": 0,
+ "type": "bool"
+ },
+ "UseFontConfigLib": {
+ "declarationFile": "/spring/rts/System/SpringApp.cpp",
+ "declarationLine": 109,
+ "description": "Whether the system fontconfig library (if present and enabled at compile-time) should be used for handling fonts.",
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "UseHighResTimer": {
+ "declarationFile": "/spring/rts/System/SpringApp.cpp",
+ "declarationLine": 108,
+ "description": "On Windows, sets whether Spring will use low- or high-resolution timer functions for tasks like graphical interpolation between game frames.",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "UseLuaMemPools": {
+ "declarationFile": "/spring/rts/System/SpringApp.cpp",
+ "declarationLine": 107,
+ "description": "Whether Lua VM memory allocations are made from pools.",
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "UseNetMessageSmoothingBuffer": {
+ "declarationFile": "/spring/rts/System/GlobalConfig.cpp",
+ "declarationLine": 58,
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "UsePBO": {
+ "declarationFile": "/spring/rts/Rendering/GL/VBO.cpp",
+ "declarationLine": 21,
+ "defaultValue": 1,
+ "safemodeValue": 0,
+ "headlessValue": 0,
+ "type": "bool"
+ },
+ "UseSDLAudio": {
+ "declarationFile": "/spring/rts/System/Sound/ISound.cpp",
+ "declarationLine": 27,
+ "description": "If enabled, OpenAL-soft only renders audio into a SDL buffer and playback is done by the SDL audio layer, i.e. SDL handles the hardware",
+ "defaultValue": 1,
+ "safemodeValue": 0,
+ "headlessValue": 0,
+ "type": "bool"
+ },
+ "UseShaderCache": {
+ "declarationFile": "/spring/rts/Rendering/Shaders/Shader.cpp",
+ "declarationLine": 37,
+ "description": "If already compiled shaders should be shared via a cache, reducing compiles of already compiled shaders.",
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "UseVBO": {
+ "declarationFile": "/spring/rts/Rendering/GL/VBO.cpp",
+ "declarationLine": 20,
+ "deprecated": 1,
+ "type": "bool"
+ },
+ "VFSCacheArchiveFiles": {
+ "declarationFile": "/spring/rts/System/GlobalConfig.cpp",
+ "declarationLine": 61,
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "VSync": {
+ "declarationFile": "/spring/rts/Rendering/VerticalSync.cpp",
+ "declarationLine": 19,
+ "description": "Synchronize buffer swaps with vertical blanking interval. Modes are -N (adaptive), +N (standard), or 0 (disabled).",
+ "defaultValue": -1,
+ "minimumValue": -6,
+ "maximumValue": 6,
+ "type": "int"
+ },
+ "Water": {
+ "declarationFile": "/spring/rts/Rendering/Env/IWater.cpp",
+ "declarationLine": 24,
+ "description": "Defines the type of water rendering. Can be set in game. Options are: 0 = Basic water, 1 = Reflective water, 2 = Reflective and Refractive water, 3 = Dynamic water, 4 = Bumpmapped water",
+ "defaultValue": 1,
+ "minimumValue": 0,
+ "maximumValue": 4,
+ "safemodeValue": 0,
+ "headlessValue": 0,
+ "type": "int"
+ },
+ "WhiteListAdditionalPlayers": {
+ "declarationFile": "/spring/rts/Net/GameServer.cpp",
+ "declarationLine": 74,
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "WindowBorderless": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 68,
+ "description": "When set and Fullscreen is 0, will put the game in Borderless Window mode, also known as Windowed Fullscreen. When using this, it is generally best to also set WindowPosX and WindowPosY to 0",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "WindowPosX": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 75,
+ "description": "Sets the horizontal position of the game window, if Fullscreen is 0. When WindowBorderless is set, this should usually be 0.",
+ "defaultValue": 0,
+ "type": "int"
+ },
+ "WindowPosY": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 76,
+ "description": "Sets the vertical position of the game window, if Fullscreen is 0. When WindowBorderless is set, this should usually be 0.",
+ "defaultValue": 32,
+ "type": "int"
+ },
+ "WindowedEdgeMove": {
+ "declarationFile": "/spring/rts/Game/Game.cpp",
+ "declarationLine": 135,
+ "description": "Sets whether moving the mouse cursor to the screen edge will move the camera across the map.",
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "WorkerThreadCount": {
+ "declarationFile": "/spring/rts/System/Threading/ThreadPool.cpp",
+ "declarationLine": 43,
+ "description": "Number of workers (including the main thread!) used by ThreadPool.",
+ "defaultValue": -1,
+ "minimumValue": -1,
+ "safemodeValue": 0,
+ "type": "int"
+ },
+ "XResolution": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 71,
+ "description": "Sets the width of the game screen. If set to 0 Spring will autodetect the current resolution of your desktop.",
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "headlessValue": 8,
+ "type": "int"
+ },
+ "XResolutionWindowed": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 73,
+ "description": "See XResolution, just for windowed.",
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "headlessValue": 8,
+ "type": "int"
+ },
+ "YResolution": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 72,
+ "description": "Sets the height of the game screen. If set to 0 Spring will autodetect the current resolution of your desktop.",
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "headlessValue": 8,
+ "type": "int"
+ },
+ "YResolutionWindowed": {
+ "declarationFile": "/spring/rts/Rendering/GlobalRendering.cpp",
+ "declarationLine": 74,
+ "description": "See YResolution, just for windowed.",
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "headlessValue": 8,
+ "type": "int"
+ },
+ "address": {
+ "declarationFile": "/spring/rts/Menu/SelectMenu.cpp",
+ "declarationLine": 45,
+ "description": "Last Ip/hostname used as direct connect in the menu.",
+ "defaultValue": "",
+ "type": "std::string"
+ },
+ "name": {
+ "declarationFile": "/spring/rts/System/SpringApp.cpp",
+ "declarationLine": 111,
+ "description": "Sets your name in the game. Since this is overridden by lobbies with your lobby username when playing, it usually only comes up when viewing replays or starting the engine directly for testing purposes.",
+ "defaultValue": "UnnamedPlayer",
+ "type": "std::string"
+ },
+ "snd_airAbsorption": {
+ "declarationFile": "/spring/rts/System/Sound/ISound.cpp",
+ "declarationLine": 39,
+ "defaultValue": 0.1,
+ "type": "float"
+ },
+ "snd_device": {
+ "declarationFile": "/spring/rts/System/Sound/ISound.cpp",
+ "declarationLine": 41,
+ "description": "Sets the used output device. See \"Available Devices\" section in infolog.txt.",
+ "defaultValue": "",
+ "type": "std::string"
+ },
+ "snd_volbattle": {
+ "declarationFile": "/spring/rts/System/Sound/ISound.cpp",
+ "declarationLine": 36,
+ "description": "Volume for \"battle\" sound channel.",
+ "defaultValue": 100,
+ "minimumValue": 0,
+ "maximumValue": 200,
+ "type": "int"
+ },
+ "snd_volgeneral": {
+ "declarationFile": "/spring/rts/System/Sound/ISound.cpp",
+ "declarationLine": 34,
+ "description": "Volume for \"general\" sound channel.",
+ "defaultValue": 100,
+ "minimumValue": 0,
+ "maximumValue": 200,
+ "type": "int"
+ },
+ "snd_volmaster": {
+ "declarationFile": "/spring/rts/System/Sound/ISound.cpp",
+ "declarationLine": 33,
+ "description": "Master sound volume.",
+ "defaultValue": 60,
+ "minimumValue": 0,
+ "maximumValue": 200,
+ "type": "int"
+ },
+ "snd_volmusic": {
+ "declarationFile": "/spring/rts/System/Sound/ISound.cpp",
+ "declarationLine": 38,
+ "description": "Volume for \"music\" sound channel.",
+ "defaultValue": 100,
+ "minimumValue": 0,
+ "maximumValue": 200,
+ "type": "int"
+ },
+ "snd_volui": {
+ "declarationFile": "/spring/rts/System/Sound/ISound.cpp",
+ "declarationLine": 37,
+ "description": "Volume for \"ui\" sound channel.",
+ "defaultValue": 100,
+ "minimumValue": 0,
+ "maximumValue": 200,
+ "type": "int"
+ },
+ "snd_volunitreply": {
+ "declarationFile": "/spring/rts/System/Sound/ISound.cpp",
+ "declarationLine": 35,
+ "description": "Volume for \"unit reply\" sound channel.",
+ "defaultValue": 100,
+ "minimumValue": 0,
+ "maximumValue": 200,
+ "type": "int"
+ }
+}
diff --git a/_data/glossary.yml b/_data/glossary.yml
new file mode 100644
index 0000000000..3ca222a6ad
--- /dev/null
+++ b/_data/glossary.yml
@@ -0,0 +1,38 @@
+- term: Allyteam
+ definition: >
+ What most people would naturally call a team is called an “allyteam” in
+ Recoil terminology.
+ url: >
+ {% link articles/team-terminology.markdown %}#allyteam-vs-team
+- term: Team
+ definition: A team is generally controlled by a player or an AI.
+ url: >
+ {% link articles/team-terminology.markdown %}#team-vs-player
+- term: Spectator
+ definition: Spectators are players not controlling any team.
+ url: >
+ {% link articles/team-terminology.markdown %}#regular-player-vs-spectator
+- term: AI
+ definition: >
+ An AI fulfils a similar role to a player, being there to control a team.
+ url: >
+ {% link articles/team-terminology.markdown %}#player-vs-ai
+- term: Lua AI
+ definition: >
+ A Lua AI generally has two components: a piece of game mechanics, and the
+ AI instance itself which is just a handle to tell game mechanics which teams
+ are legal to control.
+ url: >
+ {% link articles/team-terminology.markdown %}#lua-ai-vs-skirmish-ai
+- term: Skirmish AI
+ definition: >
+ A “skirmish” AI is hosted by one of the players and generally acts very
+ similar to a player.
+ url: >
+ {% link articles/team-terminology.markdown %}#lua-ai-vs-skirmish-ai
+- term: Gaia
+ definition: >
+ Gaia is a special team that is always present, uncontrolled, and is always
+ in its own allyteam.
+ url: >
+ {% link articles/team-terminology.markdown %}#gaia
diff --git a/_data/latest_release.json b/_data/latest_release.json
new file mode 100644
index 0000000000..53209deac8
--- /dev/null
+++ b/_data/latest_release.json
@@ -0,0 +1,244 @@
+{
+ "url": "https://api.github.com/repos/beyond-all-reason/spring/releases/92924750",
+ "assets_url": "https://api.github.com/repos/beyond-all-reason/spring/releases/92924750/assets",
+ "upload_url": "https://uploads.github.com/repos/beyond-all-reason/spring/releases/92924750/assets{?name,label}",
+ "html_url": "https://github.com/beyond-all-reason/spring/releases/tag/spring_bar_%7BBAR105%7D105.1.1-1544-g058c8ea",
+ "id": 92924750,
+ "author": {
+ "login": "github-actions[bot]",
+ "id": 41898282,
+ "node_id": "MDM6Qm90NDE4OTgyODI=",
+ "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/github-actions%5Bbot%5D",
+ "html_url": "https://github.com/apps/github-actions",
+ "followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
+ "following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
+ "gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
+ "organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
+ "repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
+ "events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
+ "type": "Bot",
+ "site_admin": false
+ },
+ "node_id": "RE_kwDOEgT4Wc4FietO",
+ "tag_name": "spring_bar_{BAR105}105.1.1-1544-g058c8ea",
+ "target_commitish": "BAR105",
+ "name": "spring_bar_{BAR105}105.1.1-1544-g058c8ea",
+ "draft": false,
+ "prerelease": false,
+ "created_at": "2023-02-18T18:40:26Z",
+ "published_at": "2023-02-18T20:36:43Z",
+ "assets": [
+ {
+ "url": "https://api.github.com/repos/beyond-all-reason/spring/releases/assets/96209637",
+ "id": 96209637,
+ "node_id": "RA_kwDOEgT4Wc4FvArl",
+ "name": "buildoptions_linux-64.txt",
+ "label": "",
+ "uploader": {
+ "login": "github-actions[bot]",
+ "id": 41898282,
+ "node_id": "MDM6Qm90NDE4OTgyODI=",
+ "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/github-actions%5Bbot%5D",
+ "html_url": "https://github.com/apps/github-actions",
+ "followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
+ "following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
+ "gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
+ "organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
+ "repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
+ "events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
+ "type": "Bot",
+ "site_admin": false
+ },
+ "content_type": "binary/octet-stream",
+ "state": "uploaded",
+ "size": 662,
+ "download_count": 3,
+ "created_at": "2023-02-18T20:36:44Z",
+ "updated_at": "2023-02-18T20:36:44Z",
+ "browser_download_url": "https://github.com/beyond-all-reason/spring/releases/download/spring_bar_%7BBAR105%7D105.1.1-1544-g058c8ea/buildoptions_linux-64.txt"
+ },
+ {
+ "url": "https://api.github.com/repos/beyond-all-reason/spring/releases/assets/96209638",
+ "id": 96209638,
+ "node_id": "RA_kwDOEgT4Wc4FvArm",
+ "name": "buildoptions_windows-64.txt",
+ "label": "",
+ "uploader": {
+ "login": "github-actions[bot]",
+ "id": 41898282,
+ "node_id": "MDM6Qm90NDE4OTgyODI=",
+ "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/github-actions%5Bbot%5D",
+ "html_url": "https://github.com/apps/github-actions",
+ "followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
+ "following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
+ "gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
+ "organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
+ "repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
+ "events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
+ "type": "Bot",
+ "site_admin": false
+ },
+ "content_type": "binary/octet-stream",
+ "state": "uploaded",
+ "size": 551,
+ "download_count": 3,
+ "created_at": "2023-02-18T20:36:44Z",
+ "updated_at": "2023-02-18T20:36:45Z",
+ "browser_download_url": "https://github.com/beyond-all-reason/spring/releases/download/spring_bar_%7BBAR105%7D105.1.1-1544-g058c8ea/buildoptions_windows-64.txt"
+ },
+ {
+ "url": "https://api.github.com/repos/beyond-all-reason/spring/releases/assets/96209640",
+ "id": 96209640,
+ "node_id": "RA_kwDOEgT4Wc4FvAro",
+ "name": "spring_bar_.BAR105.105.1.1-1544-g058c8ea_linux-64-minimal-portable.7z",
+ "label": "",
+ "uploader": {
+ "login": "github-actions[bot]",
+ "id": 41898282,
+ "node_id": "MDM6Qm90NDE4OTgyODI=",
+ "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/github-actions%5Bbot%5D",
+ "html_url": "https://github.com/apps/github-actions",
+ "followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
+ "following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
+ "gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
+ "organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
+ "repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
+ "events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
+ "type": "Bot",
+ "site_admin": false
+ },
+ "content_type": "binary/octet-stream",
+ "state": "uploaded",
+ "size": 16976427,
+ "download_count": 830,
+ "created_at": "2023-02-18T20:36:45Z",
+ "updated_at": "2023-02-18T20:36:46Z",
+ "browser_download_url": "https://github.com/beyond-all-reason/spring/releases/download/spring_bar_%7BBAR105%7D105.1.1-1544-g058c8ea/spring_bar_.BAR105.105.1.1-1544-g058c8ea_linux-64-minimal-portable.7z"
+ },
+ {
+ "url": "https://api.github.com/repos/beyond-all-reason/spring/releases/assets/96209642",
+ "id": 96209642,
+ "node_id": "RA_kwDOEgT4Wc4FvArq",
+ "name": "spring_bar_.BAR105.105.1.1-1544-g058c8ea_linux-64-minimal-symbols.tgz",
+ "label": "",
+ "uploader": {
+ "login": "github-actions[bot]",
+ "id": 41898282,
+ "node_id": "MDM6Qm90NDE4OTgyODI=",
+ "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/github-actions%5Bbot%5D",
+ "html_url": "https://github.com/apps/github-actions",
+ "followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
+ "following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
+ "gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
+ "organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
+ "repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
+ "events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
+ "type": "Bot",
+ "site_admin": false
+ },
+ "content_type": "binary/octet-stream",
+ "state": "uploaded",
+ "size": 407813530,
+ "download_count": 3,
+ "created_at": "2023-02-18T20:36:46Z",
+ "updated_at": "2023-02-18T20:36:54Z",
+ "browser_download_url": "https://github.com/beyond-all-reason/spring/releases/download/spring_bar_%7BBAR105%7D105.1.1-1544-g058c8ea/spring_bar_.BAR105.105.1.1-1544-g058c8ea_linux-64-minimal-symbols.tgz"
+ },
+ {
+ "url": "https://api.github.com/repos/beyond-all-reason/spring/releases/assets/96209648",
+ "id": 96209648,
+ "node_id": "RA_kwDOEgT4Wc4FvArw",
+ "name": "spring_bar_.BAR105.105.1.1-1544-g058c8ea_windows-64-minimal-portable.7z",
+ "label": "",
+ "uploader": {
+ "login": "github-actions[bot]",
+ "id": 41898282,
+ "node_id": "MDM6Qm90NDE4OTgyODI=",
+ "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/github-actions%5Bbot%5D",
+ "html_url": "https://github.com/apps/github-actions",
+ "followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
+ "following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
+ "gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
+ "organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
+ "repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
+ "events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
+ "type": "Bot",
+ "site_admin": false
+ },
+ "content_type": "binary/octet-stream",
+ "state": "uploaded",
+ "size": 16499276,
+ "download_count": 6563,
+ "created_at": "2023-02-18T20:36:54Z",
+ "updated_at": "2023-02-18T20:36:55Z",
+ "browser_download_url": "https://github.com/beyond-all-reason/spring/releases/download/spring_bar_%7BBAR105%7D105.1.1-1544-g058c8ea/spring_bar_.BAR105.105.1.1-1544-g058c8ea_windows-64-minimal-portable.7z"
+ },
+ {
+ "url": "https://api.github.com/repos/beyond-all-reason/spring/releases/assets/96209651",
+ "id": 96209651,
+ "node_id": "RA_kwDOEgT4Wc4FvArz",
+ "name": "spring_bar_.BAR105.105.1.1-1544-g058c8ea_windows-64-minimal-symbols.tgz",
+ "label": "",
+ "uploader": {
+ "login": "github-actions[bot]",
+ "id": 41898282,
+ "node_id": "MDM6Qm90NDE4OTgyODI=",
+ "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/github-actions%5Bbot%5D",
+ "html_url": "https://github.com/apps/github-actions",
+ "followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
+ "following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
+ "gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
+ "organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
+ "repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
+ "events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
+ "type": "Bot",
+ "site_admin": false
+ },
+ "content_type": "binary/octet-stream",
+ "state": "uploaded",
+ "size": 435054551,
+ "download_count": 2,
+ "created_at": "2023-02-18T20:36:55Z",
+ "updated_at": "2023-02-18T20:37:04Z",
+ "browser_download_url": "https://github.com/beyond-all-reason/spring/releases/download/spring_bar_%7BBAR105%7D105.1.1-1544-g058c8ea/spring_bar_.BAR105.105.1.1-1544-g058c8ea_windows-64-minimal-symbols.tgz"
+ }
+ ],
+ "tarball_url": "https://api.github.com/repos/beyond-all-reason/spring/tarball/spring_bar_{BAR105}105.1.1-1544-g058c8ea",
+ "zipball_url": "https://api.github.com/repos/beyond-all-reason/spring/zipball/spring_bar_{BAR105}105.1.1-1544-g058c8ea",
+ "body": "Github Action Upload"
+}
diff --git a/_data/non_coder_contributors.yml b/_data/non_coder_contributors.yml
new file mode 100644
index 0000000000..7ce1157c10
--- /dev/null
+++ b/_data/non_coder_contributors.yml
@@ -0,0 +1,3 @@
+- login: 6AKU66
+ html_url: https://github.com/6AKU66
+ avatar_url: https://avatars.githubusercontent.com/u/89547444?v=4
diff --git a/_data/synced_commands.json b/_data/synced_commands.json
new file mode 100644
index 0000000000..7bb678e76e
--- /dev/null
+++ b/_data/synced_commands.json
@@ -0,0 +1,116 @@
+{
+ "atm" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "Atm",
+ "description" : "Gives 1000 metal and 1000 energy to the issuing player's team"
+ },
+ "cheat" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Cheat",
+ "description" : "Enables/Disables cheating, which is required for a lot of other commands to be usable"
+ },
+ "destroy" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "Destroy",
+ "description" : "Destroys one or multiple units by unit-ID, instantly"
+ },
+ "desync" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "Desync",
+ "description" : "Allows creating an artificial desync of the local client with the rest of the participating hosts"
+ },
+ "devlua" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "DevLua",
+ "description" : "Enables/Disables Lua dev-mode (can cause desyncs if enabled)"
+ },
+ "editdefs" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "EditDefs",
+ "description" : "Allows/Disallows editing of unit-, feature- and weapon-defs through Lua"
+ },
+ "give" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "Give",
+ "description" : "Places one or multiple units of a single or multiple types on the map, instantly; by default belonging to your own team"
+ },
+ "globallos" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "GlobalLOS",
+ "description" : "Enables/Disables global line-of-sight, which makes the whole map permanently visible to everyone or to a specific allyteam"
+ },
+ "godmode" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "GodMode",
+ "description" : "Enables/Disables god-mode, which allows all players (even spectators) to control all units (even during replays, which will DESYNC them)"
+ },
+ "luagaia" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "LuaGaia",
+ "description" : "Allows reloading or disabling LuaGaia, and to send a chat message to LuaGaia scripts"
+ },
+ "luarules" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "LuaRules",
+ "description" : "Allows reloading or disabling LuaRules, and to send a chat message to LuaRules scripts"
+ },
+ "nocost" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "NoCost",
+ "description" : "Enables/Disables everything-for-free, which allows everyone to build everything for zero resource costs"
+ },
+ "nohelp" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "NoHelp",
+ "description" : "Enables/Disables widgets (LuaUI control)"
+ },
+ "nospecdraw" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "NoSpecDraw",
+ "description" : "Allows/Disallows spectators to draw on the map"
+ },
+ "nospectatorchat" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "NoSpectatorChat",
+ "description" : "Enables/Disables spectators to use the chat"
+ },
+ "reloadcegs" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "ReloadCEGs",
+ "description" : "Reloads CEG scripts"
+ },
+ "reloadcob" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "ReloadCOB",
+ "description" : "Reloads COB scripts"
+ },
+ "skip" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Skip",
+ "description" : "Fast-forwards to a given frame, or stops fast-forwarding"
+ },
+ "take" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Take",
+ "description" : "Transfers all units of allied teams without any active players to the team of the issuing player"
+ }
+}
diff --git a/_data/unsynced_commands.json b/_data/unsynced_commands.json
new file mode 100644
index 0000000000..ae59b8b3ed
--- /dev/null
+++ b/_data/unsynced_commands.json
@@ -0,0 +1,1164 @@
+{
+ "advmapshading" : {
+ "arguments" : {
+ "" : "Toggles advanced map shading mode",
+ "" : "Set advanced map shading mode "
+ },
+ "cheatRequired" : false,
+ "command" : "AdvMapShading",
+ "description" : "Control advanced map shading mode"
+ },
+ "advmodelshading" : {
+ "arguments" : {
+ "" : "Toggles advanced model shading mode",
+ "" : "Set advanced model shading mode "
+ },
+ "cheatRequired" : false,
+ "command" : "AdvModelShading",
+ "description" : "Control advanced model shading mode"
+ },
+ "aicontrol" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "AIControl",
+ "description" : "Creates a new instance of a Skirmish AI, to let it control a specific team"
+ },
+ "aikill" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "AIKill",
+ "description" : "Kills the Skirmish AI controlling a specified team"
+ },
+ "ailist" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "AIList",
+ "description" : "Prints a list of all currently active Skirmish AIs"
+ },
+ "aireload" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "AIReload",
+ "description" : "Reloads the Skirmish AI controlling a specified team"
+ },
+ "airmesh" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "airmesh",
+ "description" : "Show/Hide the smooth air-mesh map overlay"
+ },
+ "allmapmarks" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "AllMapMarks",
+ "description" : "Show/Hide all map marks drawn so far"
+ },
+ "ally" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Ally",
+ "description" : "Starts/Ends alliance of the local player's ally-team with another ally-team"
+ },
+ "atm" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ATM",
+ "description" : "Redirects command /ATM to its synced processor"
+ },
+ "buffertext" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "BufferText",
+ "description" : "Write the argument string(s) directly to the console history"
+ },
+ "chat" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Chat",
+ "description" : "Starts waiting for intput to be sent to "
+ },
+ "chatall" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ChatAll",
+ "description" : "Starts waiting for intput to be sent to All"
+ },
+ "chatally" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ChatAlly",
+ "description" : "Starts waiting for intput to be sent to Ally"
+ },
+ "chatspec" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ChatSpec",
+ "description" : "Starts waiting for intput to be sent to Spec"
+ },
+ "clearmapmarks" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ClearMapMarks",
+ "description" : "Remove all map marks drawn so far"
+ },
+ "clock" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Clock",
+ "description" : "Shows a small digital clock indicating the local time"
+ },
+ "cmdcolors" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "CmdColors",
+ "description" : "Reloads cmdcolors.txt"
+ },
+ "commandhelp" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "CommandHelp",
+ "description" : "Prints info about a specific chat command"
+ },
+ "commandlist" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "CommandList",
+ "description" : "Prints all the available chat commands with description (if available) to the console"
+ },
+ "console" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Console",
+ "description" : "Enables/Disables the in-game console"
+ },
+ "controlunit" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ControlUnit",
+ "description" : "Start to first-person-control a unit"
+ },
+ "crash" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "Crash",
+ "description" : "Invoke an artificial crash through a NULL-pointer dereference (SIGSEGV)"
+ },
+ "createvideo" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "CreateVideo",
+ "description" : "Start/Stop capturing a video of the game in progress"
+ },
+ "cross" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Cross",
+ "description" : "Allows one to exchange and modify the appearance of the cross/mouse-pointer in first-person-control view"
+ },
+ "ctrlpanel" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "CtrlPanel",
+ "description" : "Reloads GUI config"
+ },
+ "debug" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Debug",
+ "description" : "Enable/Disable debug rendering mode"
+ },
+ "debugcolvol" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DebugColVol",
+ "description" : "Enable/Disable drawing of collision volumes"
+ },
+ "debugcubemap" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DebugCubeMap",
+ "description" : "Use debug cubemap texture instead of the sky"
+ },
+ "debugdrawai" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DebugDrawAI",
+ "description" : "Enables/Disables debug drawing for AIs"
+ },
+ "debuggl" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DebugGL",
+ "description" : "Enable/Disable OpenGL debug-context output"
+ },
+ "debugglerrors" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DebugGLErrors",
+ "description" : "Enable/Disable OpenGL debug-errors"
+ },
+ "debuginfo" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DebugInfo",
+ "description" : "Print debug info to the chat/log-file about either sound, profiling, or command-descriptions"
+ },
+ "debugpath" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DebugPath",
+ "description" : "Enable/Disable drawing of pathfinder debug-data"
+ },
+ "debugtraceray" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DebugTraceRay",
+ "description" : "Enable/Disable drawing of traceray debug-data"
+ },
+ "decguiopacity" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DecGUIOpacity",
+ "description" : "Decreases the the opacity(see-through-ness) of GUI elements"
+ },
+ "decreaseviewradius" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DecreaseViewRadius",
+ "description" : "Decrease the view radius (higher performance, uglier view)"
+ },
+ "deselect" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Deselect",
+ "description" : "Deselects all currently selected units"
+ },
+ "destroy" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "Destroy",
+ "description" : "Destroys one or multiple units by unit-ID, instantly"
+ },
+ "desync" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Desync",
+ "description" : "Redirects command /Desync to its synced processor"
+ },
+ "disticon" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DistIcon",
+ "description" : "Set the distance between units and camera, at which they turn into icons (Graphic setting)"
+ },
+ "distsortprojectiles" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DistSortProjectiles",
+ "description" : "Enable/Disable sorting drawn projectiles by camera distance"
+ },
+ "divbyzero" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "DivByZero",
+ "description" : "Invoke an artificial crash by performing a division-by-zero"
+ },
+ "drawinmap" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DrawInMap",
+ "description" : "Enables drawing on the map"
+ },
+ "drawlabel" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DrawLabel",
+ "description" : "Draws a label on the map at the current mouse-pointer position"
+ },
+ "draworderparticles" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DrawOrderParticles",
+ "description" : "Enable/Disable particles draw order: 0=disabled, 1=enabled"
+ },
+ "drawsky" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DrawSky",
+ "description" : "Whether to actually draw sky"
+ },
+ "dumpatlas" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DumpAtlas",
+ "description" : "Save Some Atlases"
+ },
+ "dumprng" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DumpRNG",
+ "description" : "dump SyncedRNG-state to file"
+ },
+ "dumpshadows" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DumpShadows",
+ "description" : "Save shadow map textures to files"
+ },
+ "dumpstate" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "DumpState",
+ "description" : "dump game-state to file"
+ },
+ "echo" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Echo",
+ "description" : "Write a string to the log file"
+ },
+ "endgraph" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "EndGraph",
+ "description" : "Enables/Disables the statistics graphs shown at the end of the game"
+ },
+ "exception" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "Exception",
+ "description" : "Invoke an artificial crash by throwing an std::runtime_error"
+ },
+ "featuredrawdistance" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "FeatureDrawDistance",
+ "description" : ""
+ },
+ "featuredrawer" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "FeatureDrawer",
+ "description" : "Forces particular Feature drawer type"
+ },
+ "featurefadedistance" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "FeatureFadeDistance",
+ "description" : ""
+ },
+ "font" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Font",
+ "description" : "Reloads default or custom fonts"
+ },
+ "fps" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "FPS",
+ "description" : "Shows/Hides the frames-per-second indicator"
+ },
+ "fpshud" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "FPSHud",
+ "description" : "Enables/Disables HUD (GUI interface) shown in first-person-control mode"
+ },
+ "fullscreen" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Fullscreen",
+ "description" : "Switches fullscreen mode"
+ },
+ "gameinfo" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "GameInfo",
+ "description" : "Enables/Disables game-info panel rendering"
+ },
+ "gathermode" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "GatherMode",
+ "description" : "Enter/Leave gather-wait command mode"
+ },
+ "give" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "Give",
+ "description" : "Places one or multiple units of a single or multiple types on the map, instantly; by default to your own team"
+ },
+ "grabinput" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "GrabInput",
+ "description" : "Prevents/Enables the mouse from leaving the game window (windowed mode only)"
+ },
+ "grounddecals" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "GroundDecals",
+ "description" : "Enable/Disable ground-decal rendering."
+ },
+ "grounddetail" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "GroundDetail",
+ "description" : "Set the level of ground detail"
+ },
+ "group" : {
+ "arguments" : {
+ "" : "Select group ",
+ "add " : "Add current selected units to group ",
+ "selectadd " : "Add members from group to currently selected units",
+ "selectclear " : "Remove members from group from currently selected units",
+ "selecttoggle " : "Toggle members from group from currently selected units",
+ "set " : "Set current selected units as group ",
+ "unset" : "Deassign control group for currently selected units"
+ },
+ "cheatRequired" : false,
+ "command" : "Group",
+ "description" : "Manage control groups"
+ },
+ "group0" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Group0",
+ "description" : "Allows modifying the members of group 0"
+ },
+ "group1" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Group1",
+ "description" : "Allows modifying the members of group 1"
+ },
+ "group2" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Group2",
+ "description" : "Allows modifying the members of group 2"
+ },
+ "group3" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Group3",
+ "description" : "Allows modifying the members of group 3"
+ },
+ "group4" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Group4",
+ "description" : "Allows modifying the members of group 4"
+ },
+ "group5" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Group5",
+ "description" : "Allows modifying the members of group 5"
+ },
+ "group6" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Group6",
+ "description" : "Allows modifying the members of group 6"
+ },
+ "group7" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Group7",
+ "description" : "Allows modifying the members of group 7"
+ },
+ "group8" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Group8",
+ "description" : "Allows modifying the members of group 8"
+ },
+ "group9" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Group9",
+ "description" : "Allows modifying the members of group 9"
+ },
+ "hang" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "Hang",
+ "description" : "Invoke an artificial hang"
+ },
+ "hardwarecursor" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "HardwareCursor",
+ "description" : "Enables/Disables hardware mouse-cursor support"
+ },
+ "hideinterface" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "HideInterface",
+ "description" : "Hide/Show the GUI controlls"
+ },
+ "iconfadestart" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "IconFadeStart",
+ "description" : "Set the distance where unit icons became completely opaque at"
+ },
+ "iconfadevanish" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "IconFadeVanish",
+ "description" : "Set the distance where unit icons fade out at"
+ },
+ "iconsasui" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "IconsAsUI",
+ "description" : "Set whether unit icons are drawn as an UI element (true) or old LOD-like style (false, default)."
+ },
+ "iconscaleui" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "IconScaleUI",
+ "description" : "Set the multiplier for the size of the UI unit icons"
+ },
+ "iconshidewithui" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "IconsHideWithUI",
+ "description" : "Set whether unit icons are hidden when UI is hidden."
+ },
+ "incguiopacity" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "IncGUIOpacity",
+ "description" : "Increases the the opacity(see-through-ness) of GUI elements"
+ },
+ "increaseviewradius" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "IncreaseViewRadius",
+ "description" : "Increase terrain tessellation level"
+ },
+ "info" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Info",
+ "description" : "Shows/Hides the player roster"
+ },
+ "inputtextgeo" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "InputTextGeo",
+ "description" : "Move and/or resize the input-text field (the \"Say: \" thing)"
+ },
+ "lastmsgpos" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "LastMsgPos",
+ "description" : "Moves the camera to show the position of the last message"
+ },
+ "lodscale" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "LODScale",
+ "description" : "Set the scale for either of: LOD (level-of-detail), shadow-LOD, reflection-LOD, refraction-LOD"
+ },
+ "luagaia" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "LuaGaia",
+ "description" : "Redirects command /LuaGaia to its synced processor"
+ },
+ "luagccontrol" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "LuaGCControl",
+ "description" : "Toggle between 1/f and 30/s Lua garbage collection rate"
+ },
+ "luamenu" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "LuaMenu",
+ "description" : "Allows one to reload or disable LuaMenu, or alternatively to send a chat message to LuaMenu"
+ },
+ "luarules" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "LuaRules",
+ "description" : "Redirects command /LuaRules to its synced processor"
+ },
+ "luasave" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "LuaSave",
+ "description" : "Save the game state to a specific file, add -y to overwrite when file is already present"
+ },
+ "luaui" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "LuaUI",
+ "description" : "Allows one to reload or disable LuaUI, or alternatively to send a chat message to LuaUI"
+ },
+ "mapborder" : {
+ "arguments" : {
+ "" : "Toggles map-border rendering",
+ "" : "Set map-border rendering "
+ },
+ "cheatRequired" : false,
+ "command" : "MapBorder",
+ "description" : "Control map-border rendering"
+ },
+ "mapmarks" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MapMarks",
+ "description" : "Enables/Disables map marks rendering"
+ },
+ "mapmeshdrawer" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "mapmeshdrawer",
+ "description" : "Switch map-mesh rendering modes: 0=GCM, 1=HLOD, 2=ROAM"
+ },
+ "mapshadowpolyoffset" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MapShadowPolyOffset",
+ "description" : ""
+ },
+ "maxnanoparticles" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MaxNanoParticles",
+ "description" : "Set the maximum number of nano-particles (Graphic setting)"
+ },
+ "maxparticles" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MaxParticles",
+ "description" : "Set the maximum number of particles (Graphics setting)"
+ },
+ "maxviewrange" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MaxViewRange",
+ "description" : "Set maximum view-distance"
+ },
+ "minimap" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MiniMap",
+ "description" : "FIXME document subcommands"
+ },
+ "minviewrange" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MinViewRange",
+ "description" : "Set minimum view-distance"
+ },
+ "mouse1" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Mouse1",
+ "description" : "Simulates a press of mouse-button 1"
+ },
+ "mouse2" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Mouse2",
+ "description" : "Simulates a press of mouse-button 2"
+ },
+ "mouse3" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Mouse3",
+ "description" : "Simulates a press of mouse-button 3"
+ },
+ "mouse4" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Mouse4",
+ "description" : "Simulates a press of mouse-button 4"
+ },
+ "mouse5" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Mouse5",
+ "description" : "Simulates a press of mouse-button 5"
+ },
+ "mousecancelselectionrectangle" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MouseCancelSelectionRectangle",
+ "description" : ""
+ },
+ "moveback" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MoveBack",
+ "description" : "Moves the camera Back a bit"
+ },
+ "movedown" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MoveDown",
+ "description" : "Moves the camera Down a bit"
+ },
+ "movefast" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MoveFast",
+ "description" : "Moves the camera Fast a bit"
+ },
+ "moveforward" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MoveForward",
+ "description" : "Moves the camera Forward a bit"
+ },
+ "moveleft" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MoveLeft",
+ "description" : "Moves the camera Left a bit"
+ },
+ "movereset" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MoveReset",
+ "description" : "Moves the camera Reset a bit"
+ },
+ "moveright" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MoveRight",
+ "description" : "Moves the camera Right a bit"
+ },
+ "moverotate" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MoveRotate",
+ "description" : "Moves the camera Rotate a bit"
+ },
+ "moveslow" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MoveSlow",
+ "description" : "Moves the camera Slow a bit"
+ },
+ "movetilt" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MoveTilt",
+ "description" : "Moves the camera Tilt a bit"
+ },
+ "moveup" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MoveUp",
+ "description" : "Moves the camera Up a bit"
+ },
+ "mutesound" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "MuteSound",
+ "description" : "Mute/Unmute the current sound system"
+ },
+ "netmsgsmoothing" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "NetMsgSmoothing",
+ "description" : "Toggles whether client will use net-message smoothing; better for unstable connections"
+ },
+ "netping" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "NetPing",
+ "description" : "Send a ping request to the server"
+ },
+ "noluadraw" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "NoLuaDraw",
+ "description" : "Allow/Disallow Lua to draw on the map"
+ },
+ "pastetext" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "PasteText",
+ "description" : "Paste either the argument string(s) or the content of the clip-board to chat input"
+ },
+ "pause" : {
+ "arguments" : {
+ "" : "Toggles tracking",
+ "" : "Set tracking "
+ },
+ "cheatRequired" : false,
+ "command" : "Pause",
+ "description" : "Pause/Unpause the game"
+ },
+ "quitforce" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "QuitForce",
+ "description" : "Exits game to system"
+ },
+ "quitmenu" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "QuitMenu",
+ "description" : "Opens the quit-menu, if it is not already open"
+ },
+ "quitmessage" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "QuitMessage",
+ "description" : "Deprecated, see /Quit instead (was used to quit the game immediately)"
+ },
+ "reloadforce" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ReloadForce",
+ "description" : "Exits game to menu"
+ },
+ "reloadshaders" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ReloadShaders",
+ "description" : "Reloads all engine shaders"
+ },
+ "reloadtextures" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ReloadTextures",
+ "description" : "Reloads textures"
+ },
+ "resbar" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ResBar",
+ "description" : "Shows/Hides team resource storage indicator bar"
+ },
+ "resync" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Resync",
+ "description" : "Redirects command /Resync to its synced processor"
+ },
+ "safegl" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "SafeGL",
+ "description" : "Enables/Disables OpenGL safe-mode"
+ },
+ "save" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Save",
+ "description" : "Save the game state to a specific file, add -y to overwrite when file is already present"
+ },
+ "say" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Say",
+ "description" : "Say something in (public) chat"
+ },
+ "screenshot" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ScreenShot",
+ "description" : "Take a screen-shot of the current view"
+ },
+ "select" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Select",
+ "description" : ""
+ },
+ "selectcycle" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "SelectCycle",
+ "description" : ""
+ },
+ "selectunits" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "SelectUnits",
+ "description" : ""
+ },
+ "send" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Send",
+ "description" : "Send a string as raw network message to the game host (for debugging only)"
+ },
+ "set" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Set",
+ "description" : "Set a config key=value pair"
+ },
+ "setspeed" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "SetSpeed",
+ "description" : "Set the simulation speed to any positive value, bounded by the minimum and maximum game speed settings."
+ },
+ "shadows" : {
+ "arguments" : {
+ "-1" : "Disabled",
+ "0" : "Off",
+ "1" : "Full shadows",
+ "2" : "Skip terrain shadows"
+ },
+ "cheatRequired" : false,
+ "command" : "Shadows",
+ "description" : "Control shadow rendering"
+ },
+ "sharedialog" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ShareDialog",
+ "description" : "Opens the share dialog for sending units and resources to other players"
+ },
+ "showelevation" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ShowElevation",
+ "description" : "Enable rendering of the auxiliary height-map overlay"
+ },
+ "showmetalmap" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ShowMetalMap",
+ "description" : "Enable rendering of the auxiliary metal-map overlay"
+ },
+ "showpathcost" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "ShowPathCost",
+ "description" : "Enable rendering of the path cost-map overlay"
+ },
+ "showpathflow" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "ShowPathFlow",
+ "description" : "Enable/Disable rendering of the path flow-map overlay"
+ },
+ "showpathheat" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "ShowPathHeat",
+ "description" : "Enable/Disable rendering of the path heat-map overlay"
+ },
+ "showpathtraversability" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ShowPathTraversability",
+ "description" : "Enable rendering of the path traversability-map overlay"
+ },
+ "showpathtype" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ShowPathType",
+ "description" : "Shows path traversability for a given MoveDefName, MoveDefID or UnitDefName"
+ },
+ "showstandard" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ShowStandard",
+ "description" : "Disable rendering of all auxiliary map overlays"
+ },
+ "slowdown" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "SlowDown",
+ "description" : "Decreases the simulation speed. The engine will try to simulate less frames per second"
+ },
+ "softparticles" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "SoftParticles",
+ "description" : "Enable/Disable particles softening: 0=disabled, 1=enabled"
+ },
+ "soundchannelenable" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "SoundChannelEnable",
+ "description" : "Enable/Disable specific sound channels: UnitReply, General, Battle, UserInterface, Music"
+ },
+ "sounddevice" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "SoundDevice",
+ "description" : "Switch the sound output system (currently only OpenAL / NullAudio)"
+ },
+ "specfullview" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "SpecFullView",
+ "description" : "Sets or toggles between full LOS or ally-team LOS if the local user is a spectator"
+ },
+ "spectator" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Spectator",
+ "description" : "Lets the local user give up control over a team and start spectating"
+ },
+ "specteam" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "SpecTeam",
+ "description" : "Lets the local user specify the team to follow if he is a spectator"
+ },
+ "speed" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Speed",
+ "description" : "Shows/Hides the simulation speed indicator"
+ },
+ "speedcontrol" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "SpeedControl",
+ "description" : "Sets how server adjusts speed according to player's CPU load, 1: use average, 0: use highest"
+ },
+ "speedup" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "SpeedUp",
+ "description" : "Increases the simulation speed. The engine will try to simulate more frames per second"
+ },
+ "take" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "Take",
+ "description" : "Redirects command /Take to its synced processor"
+ },
+ "team" : {
+ "arguments" : {},
+ "cheatRequired" : true,
+ "command" : "Team",
+ "description" : "Lets the local user change to another team"
+ },
+ "teamhighlight" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "TeamHighlight",
+ "description" : "Enables/Disables uncontrolled team blinking"
+ },
+ "toggleinfo" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ToggleInfo",
+ "description" : "Toggles current info texture view"
+ },
+ "togglelos" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ToggleLOS",
+ "description" : "Enable rendering of the auxiliary LOS-map overlay"
+ },
+ "tooltip" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ToolTip",
+ "description" : "Enables/Disables the general tool-tips, displayed when hovering over units. features or the map"
+ },
+ "track" : {
+ "arguments" : {
+ "" : "Toggles tracking",
+ "" : "Set tracking "
+ },
+ "cheatRequired" : false,
+ "command" : "Track",
+ "description" : "Start/stop following the selected unit(s) with the camera"
+ },
+ "trackmode" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "TrackMode",
+ "description" : "Shift through different ways of following selected unit(s)"
+ },
+ "tset" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "TSet",
+ "description" : "Set a config key=value pair in the overlay, meaning it will not be persisted for future games"
+ },
+ "unitdrawer" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "UnitDrawer",
+ "description" : "Forces particular Unit drawer type"
+ },
+ "viewselection" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "ViewSelection",
+ "description" : "Moves the camera to the center of the currently selected units"
+ },
+ "vsync" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "VSync",
+ "description" : "Enables/Disables vertical-sync (Graphics setting)"
+ },
+ "w" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "W",
+ "description" : "Say something in private to a specific player, by player-name"
+ },
+ "water" : {
+ "arguments" : {
+ "0" : "Basic",
+ "1" : "Reflective",
+ "2" : "Dynamic",
+ "3" : "Reflective & Refractive",
+ "4" : "Bump-mapped"
+ },
+ "cheatRequired" : false,
+ "command" : "Water",
+ "description" : "Set water rendering mode"
+ },
+ "wbynum" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "WByNum",
+ "description" : "Say something in private to a specific player, by player-ID"
+ },
+ "windowborderless" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "WindowBorderless",
+ "description" : "Switches borderless/decorated mode"
+ },
+ "wiremap" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "WireMap",
+ "description" : "Toggle wireframe-mode drawing of map geometry"
+ },
+ "wiremodel" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "WireModel",
+ "description" : "Toggle wireframe-mode drawing of model geometry"
+ },
+ "wiresky" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "WireSky",
+ "description" : "Toggle wireframe-mode drawing of skydome geometry"
+ },
+ "wirewater" : {
+ "arguments" : {},
+ "cheatRequired" : false,
+ "command" : "WireWater",
+ "description" : "Toggle wireframe-mode drawing of water geometry"
+ }
+}
diff --git a/_data/weapondefs.json b/_data/weapondefs.json
new file mode 100644
index 0000000000..f9851ed553
--- /dev/null
+++ b/_data/weapondefs.json
@@ -0,0 +1,819 @@
+{
+ "WeaponDefs": {
+ "name": {
+ "internalName": "description",
+ "description": "The descriptive name of the weapon as listed in FPS mode.",
+ "defaultValue": Weapon,
+ "type": "std::__cxx11::basic_string, std::allocator >"
+ },
+ "weaponType": {
+ "internalName": "type",
+ "defaultValue": Cannon,
+ "type": "std::__cxx11::basic_string, std::allocator >"
+ },
+ "id": {
+ "internalName": "tdfId",
+ "defaultValue": 0,
+ "type": "int"
+ },
+ "customParams": {
+ "type": "table"
+ },
+ "avoidFriendly": {
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "avoidFeature": {
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "avoidNeutral": {
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "avoidGround": {
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "avoidCloaked": {
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "collideEnemy": {
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "collideFriendly": {
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "collideFeature": {
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "collideNeutral": {
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "collideGround": {
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "damage": {
+ "type": "table"
+ },
+ "damage.default": {
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "size": {
+ "type": "float"
+ },
+ "explosionSpeed": {
+ "type": "float"
+ },
+ "impactOnly": {
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "noSelfDamage": {
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "noExplode": {
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "burnblow": {
+ "internalName": "selfExplode",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "damageAreaOfEffect": {
+ "fallbackName": "areaOfEffect",
+ "defaultValue": 8,
+ "scaleValue": 0.5,
+ "scaleValueString": "0.5f",
+ "type": "float"
+ },
+ "edgeEffectiveness": {
+ "defaultValue": 0,
+ "maximumValue": 1,
+ "type": "float"
+ },
+ "collisionSize": {
+ "defaultValue": 0.05,
+ "type": "float"
+ },
+ "weaponVelocity": {
+ "internalName": "projectilespeed",
+ "fallbackName": "maxVelocity",
+ "defaultValue": 0,
+ "minimumValue": 0.01,
+ "scaleValue": 0.0333333,
+ "scaleValueString": "1.0f / GAME_SPEED",
+ "type": "float"
+ },
+ "startvelocity": {
+ "defaultValue": 0,
+ "minimumValue": 0.01,
+ "scaleValue": 0.0333333,
+ "scaleValueString": "1.0f / GAME_SPEED",
+ "type": "float"
+ },
+ "weaponacceleration": {
+ "fallbackName": "acceleration",
+ "defaultValue": 0,
+ "scaleValue": 0.00111111,
+ "scaleValueString": "1.0f / (GAME_SPEED * GAME_SPEED)",
+ "type": "float"
+ },
+ "reloadTime": {
+ "internalName": "reload",
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "burstRate": {
+ "internalName": "salvodelay",
+ "defaultValue": 0.1,
+ "type": "float"
+ },
+ "burst": {
+ "internalName": "salvosize",
+ "defaultValue": 1,
+ "type": "int"
+ },
+ "projectiles": {
+ "internalName": "projectilespershot",
+ "defaultValue": 1,
+ "type": "int"
+ },
+ "waterBounce": {
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "groundBounce": {
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "bounceSlip": {
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "bounceRebound": {
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "numBounce": {
+ "defaultValue": -1,
+ "type": "int"
+ },
+ "impulseFactor": {
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "impulseBoost": {
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "craterMult": {
+ "fallbackName": "impulseFactor",
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "craterBoost": {
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "craterAreaOfEffect": {
+ "fallbackName": "areaOfEffect",
+ "defaultValue": 8,
+ "scaleValue": 0.5,
+ "scaleValueString": "0.5f",
+ "type": "float"
+ },
+ "waterweapon": {
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "submissile": {
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "fireSubmersed": {
+ "fallbackName": "waterweapon",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "commandfire": {
+ "internalName": "manualfire",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "range": {
+ "defaultValue": 10,
+ "type": "float"
+ },
+ "heightmod": {
+ "defaultValue": 0.2,
+ "type": "float"
+ },
+ "targetBorder": {
+ "defaultValue": 0,
+ "minimumValue": -1,
+ "maximumValue": 1,
+ "type": "float"
+ },
+ "cylinderTargeting": {
+ "fallbackName": "cylinderTargetting",
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "maximumValue": 128,
+ "type": "float"
+ },
+ "turret": {
+ "description": "Does the unit aim within an arc (up-to and including full 360° turret traverse) or always aim along the owner's heading?",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "fixedLauncher": {
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "tolerance": {
+ "internalName": "maxAngle",
+ "defaultValue": 3000,
+ "scaleValue": 9.58738e-05,
+ "scaleValueString": "TAANG2RAD",
+ "type": "float"
+ },
+ "firetolerance": {
+ "internalName": "maxFireAngle",
+ "defaultValue": 3640,
+ "scaleValue": 9.58738e-05,
+ "scaleValueString": "TAANG2RAD",
+ "type": "float"
+ },
+ "highTrajectory": {
+ "defaultValue": 2,
+ "type": "int"
+ },
+ "trajectoryHeight": {
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "tracks": {
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "wobble": {
+ "defaultValue": 0,
+ "scaleValue": 3.19579e-06,
+ "scaleValueString": "float(TAANG2RAD) / GAME_SPEED",
+ "type": "float"
+ },
+ "dance": {
+ "defaultValue": 0,
+ "scaleValue": 0.0333333,
+ "scaleValueString": "1.0f / GAME_SPEED",
+ "type": "float"
+ },
+ "gravityAffected": {
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "myGravity": {
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "canAttackGround": {
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "weaponTimer": {
+ "internalName": "uptime",
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "flighttime": {
+ "description": "Flighttime of missiles in seconds.",
+ "defaultValue": 0,
+ "scaleValue": 30,
+ "scaleValueString": "GAME_SPEED",
+ "type": "float"
+ },
+ "turnrate": {
+ "defaultValue": 0,
+ "scaleValue": 3.19579e-06,
+ "scaleValueString": "float(TAANG2RAD) / GAME_SPEED",
+ "type": "float"
+ },
+ "heightBoostFactor": {
+ "defaultValue": -1,
+ "type": "float"
+ },
+ "proximityPriority": {
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "allowNonBlockingAim": {
+ "description": "When false, the weapon is blocked from firing until AimWeapon() returns.",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "accuracy": {
+ "defaultValue": 0,
+ "tagFunction": "math::sin(x * math::PI / 0xafff)",
+ "type": "float"
+ },
+ "sprayAngle": {
+ "defaultValue": 0,
+ "tagFunction": "math::sin(x * math::PI / 0xafff)",
+ "type": "float"
+ },
+ "movingAccuracy": {
+ "fallbackName": "accuracy",
+ "defaultValue": 0,
+ "tagFunction": "math::sin(x * math::PI / 0xafff)",
+ "type": "float"
+ },
+ "targetMoveError": {
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "leadLimit": {
+ "defaultValue": -1,
+ "type": "float"
+ },
+ "leadBonus": {
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "predictBoost": {
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "ownerExpAccWeight": {
+ "type": "float"
+ },
+ "minIntensity": {
+ "description": "The minimum percentage the weapon's damage can fall-off to over its range. Setting to 1.0 will disable fall off entirely. Unrelated to the visual-only intensity tag.",
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "duration": {
+ "defaultValue": 0.05,
+ "type": "float"
+ },
+ "beamtime": {
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "beamburst": {
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "beamTTL": {
+ "internalName": "beamLaserTTL",
+ "defaultValue": 0,
+ "type": "int"
+ },
+ "sweepFire": {
+ "description": "Makes BeamLasers continue firing while aiming for a new target, 'sweeping' across the terrain.",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "largeBeamLaser": {
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "sizeGrowth": {
+ "defaultValue": 0.5,
+ "type": "float"
+ },
+ "flameGfxTime": {
+ "type": "float"
+ },
+ "metalPerShot": {
+ "internalName": "metalcost",
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "energyPerShot": {
+ "internalName": "energycost",
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "fireStarter": {
+ "description": "The percentage chance of the weapon setting fire to static map features on impact.",
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "scaleValue": 0.01,
+ "scaleValueString": "0.01f",
+ "type": "float"
+ },
+ "paralyzer": {
+ "description": "Is the weapon a paralyzer? If true the weapon only stuns enemy units and does not cause damage in the form of lost hit-points.",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "paralyzeTime": {
+ "description": "Determines the maximum length of time in seconds that the target will be paralyzed. The timer is restarted every time the target is hit by the weapon. Cannot be less than 0.",
+ "defaultValue": 10,
+ "minimumValue": 0,
+ "type": "int"
+ },
+ "stockpile": {
+ "description": "Does each round of the weapon have to be built and stockpiled by the player? Will only correctly function for the first of each stockpiled weapons a unit has.",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "stockpileTime": {
+ "fallbackName": "reload",
+ "description": "The time in seconds taken to stockpile one round of the weapon.",
+ "defaultValue": 1,
+ "scaleValue": 30,
+ "scaleValueString": "GAME_SPEED",
+ "type": "float"
+ },
+ "targetable": {
+ "description": "Bitmask representing the types of weapon that can intercept this weapon. Each digit of binary that is set to one means that a weapon with the corresponding digit in its interceptor tag will intercept this weapon. Instant-hitting weapons such as [#BeamLaser], [#LightningCannon] and [#Rifle] cannot be targeted.",
+ "defaultValue": 0,
+ "type": "int"
+ },
+ "interceptor": {
+ "description": "Bitmask representing the types of weapons that this weapon can intercept. Each digit of binary that is set to one means that a weapon with the corresponding digit in its targetable tag will be intercepted by this weapon.",
+ "defaultValue": 0,
+ "type": "int"
+ },
+ "interceptedByShieldType": {
+ "description": "",
+ "type": "unsigned int"
+ },
+ "coverage": {
+ "internalName": "coverageRange",
+ "description": "The radius in elmos within which an interceptor weapon will fire on targetable weapons.",
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "interceptSolo": {
+ "description": "If true no other interceptors may target the same projectile.",
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "dynDamageInverted": {
+ "description": "If true the damage curve is inverted i.e. the weapon does more damage at greater ranges as opposed to less.",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "dynDamageExp": {
+ "description": "Exponent of the range-dependent damage formula, the default of 0.0 disables dynamic damage, 1.0 means linear scaling, 2.0 quadratic and so on.",
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "dynDamageMin": {
+ "description": "The minimum floor value that range-dependent damage can drop to.",
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "dynDamageRange": {
+ "description": "If set to non-zero values the weapon will use this value in the range-dependant damage formula instead of the actual range.",
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "shield.repulser": {
+ "internalName": "shieldRepulser",
+ "fallbackName": "shieldRepulser",
+ "description": "Does the shield repulse (deflect) projectiles or absorb them?",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "shield.smart": {
+ "internalName": "smartShield",
+ "fallbackName": "smartShield",
+ "description": "Determines whether or not projectiles fired by allied units can pass through the shield (true) or are intercepted as enemy weapons are (false).",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "shield.exterior": {
+ "internalName": "exteriorShield",
+ "fallbackName": "exteriorShield",
+ "description": "Determines whether or not projectiles fired within the shield's radius can pass through the shield (true) or are intercepted (false).",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "shield.maxSpeed": {
+ "internalName": "shieldMaxSpeed",
+ "fallbackName": "shieldMaxSpeed",
+ "description": "The maximum speed the repulsor will impart to deflected projectiles.",
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "shield.force": {
+ "internalName": "shieldForce",
+ "fallbackName": "shieldForce",
+ "description": "The force applied by the repulsor to the weapon - higher values will deflect weapons away at higher velocities.",
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "shield.radius": {
+ "internalName": "shieldRadius",
+ "fallbackName": "shieldRadius",
+ "description": "The radius of the circular area the shield covers.",
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "shield.power": {
+ "internalName": "shieldPower",
+ "fallbackName": "shieldPower",
+ "description": "Essentially the maximum allowed hit-points of the shield - reduced by the damage of a weapon upon impact.",
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "shield.startingPower": {
+ "internalName": "shieldStartingPower",
+ "fallbackName": "shieldStartingPower",
+ "description": "How many hit-points the shield starts with - otherwise the shield must regenerate from 0 until it reaches maximum power.",
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "shield.powerRegen": {
+ "internalName": "shieldPowerRegen",
+ "fallbackName": "shieldPowerRegen",
+ "description": "How many hit-points the shield regenerates each second.",
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "shield.powerRegenEnergy": {
+ "internalName": "shieldPowerRegenEnergy",
+ "fallbackName": "shieldPowerRegenEnergy",
+ "description": "How much energy resource is consumed to regenerate each hit-point.",
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "shield.energyUse": {
+ "internalName": "shieldEnergyUse",
+ "fallbackName": "shieldEnergyUse",
+ "description": "The amount of the energy resource consumed by the shield to absorb or repulse weapons, continually drained by a repulsor as long as the projectile is in range.",
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "rechargeDelay": {
+ "internalName": "shieldRechargeDelay",
+ "fallbackName": "shieldRechargeDelay",
+ "description": "The delay in seconds before a shield begins to regenerate after it is hit.",
+ "defaultValue": 0,
+ "scaleValue": 30,
+ "scaleValueString": "GAME_SPEED",
+ "type": "float"
+ },
+ "shield.interceptType": {
+ "internalName": "shieldInterceptType",
+ "fallbackName": "shieldInterceptType",
+ "description": "Bitmask representing the types of weapons that this shield can intercept. Each digit of binary that is set to one means that a weapon with the corresponding digit in its interceptedByShieldType will be intercepted by this shield (See [[Shield Interception Tag]] Use).",
+ "defaultValue": 0,
+ "type": "unsigned int"
+ },
+ "shield.visible": {
+ "internalName": "visibleShield",
+ "fallbackName": "visibleShield",
+ "description": "Is the shield visible or not?",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "shield.visibleRepulse": {
+ "internalName": "visibleShieldRepulse",
+ "fallbackName": "visibleShieldRepulse",
+ "description": "Is the (hard-coded) repulse effect rendered or not?",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "shield.visibleHitFrames": {
+ "internalName": "visibleShieldHitFrames",
+ "fallbackName": "visibleShieldHitFrames",
+ "description": "The number of frames a shield becomes visible for when hit.",
+ "defaultValue": 0,
+ "type": "int"
+ },
+ "shield.badColor": {
+ "internalName": "shieldBadColor",
+ "fallbackName": "shieldBadColor",
+ "description": "The RGBA colour the shield transitions to as its hit-points are reduced towards 0.",
+ "defaultValue": [ 1, 0.5, 0.5 ],
+ "type": "float4"
+ },
+ "shield.goodColor": {
+ "internalName": "shieldGoodColor",
+ "fallbackName": "shieldGoodColor",
+ "description": "The RGBA colour the shield transitions to as its hit-points are regenerated towards its maximum power.",
+ "defaultValue": [ 0.5, 0.5, 1 ],
+ "type": "float4"
+ },
+ "shield.alpha": {
+ "internalName": "shieldAlpha",
+ "fallbackName": "shieldAlpha",
+ "description": "The alpha transparency of the shield whilst it is visible.",
+ "defaultValue": 0.2,
+ "type": "float"
+ },
+ "shield.armorType": {
+ "internalName": "shieldArmorTypeName",
+ "fallbackName": "shieldArmorType",
+ "description": "Specifies the armorclass of the shield; you can input either an armorclass name OR a unitdef name to share that unit's armorclass",
+ "defaultValue": default,
+ "type": "std::__cxx11::basic_string, std::allocator >"
+ },
+ "model": {
+ "defaultValue": ,
+ "type": "std::__cxx11::basic_string, std::allocator >"
+ },
+ "explosionScar": {
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "alwaysVisible": {
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "cameraShake": {
+ "fallbackName": "damage.default",
+ "defaultValue": 0,
+ "minimumValue": 0,
+ "type": "float"
+ },
+ "smokeTrail": {
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "smokeTrailCastShadow": {
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "smokePeriod": {
+ "defaultValue": 8,
+ "type": "int"
+ },
+ "smokeTime": {
+ "defaultValue": 60,
+ "type": "int"
+ },
+ "smokeSize": {
+ "defaultValue": 7,
+ "type": "float"
+ },
+ "smokeColor": {
+ "defaultValue": 0.65,
+ "type": "float"
+ },
+ "castShadow": {
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "sizeDecay": {
+ "defaultValue": 0,
+ "type": "float"
+ },
+ "alphaDecay": {
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "separation": {
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "noGap": {
+ "defaultValue": 1,
+ "type": "bool"
+ },
+ "stages": {
+ "defaultValue": 5,
+ "type": "int"
+ },
+ "lodDistance": {
+ "defaultValue": 1000,
+ "type": "int"
+ },
+ "thickness": {
+ "defaultValue": 2,
+ "type": "float"
+ },
+ "coreThickness": {
+ "defaultValue": 0.25,
+ "type": "float"
+ },
+ "laserFlareSize": {
+ "defaultValue": 15,
+ "type": "float"
+ },
+ "tileLength": {
+ "defaultValue": 200,
+ "type": "float"
+ },
+ "scrollSpeed": {
+ "defaultValue": 5,
+ "type": "float"
+ },
+ "pulseSpeed": {
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "beamDecay": {
+ "defaultValue": 1,
+ "type": "float"
+ },
+ "falloffRate": {
+ "defaultValue": 0.5,
+ "type": "float"
+ },
+ "hardstop": {
+ "internalName": "laserHardStop",
+ "defaultValue": 0,
+ "type": "bool"
+ },
+ "rgbColor": {
+ "defaultValue": [ 1, 0.5, 0 ],
+ "type": "float3"
+ },
+ "rgbColor2": {
+ "defaultValue": [ 1, 1, 1 ],
+ "type": "float3"
+ },
+ "intensity": {
+ "description": "Alpha transparency for non-model projectiles. Lower values are more opaque, but 0.0 will cause the projectile to disappear entirely.",
+ "defaultValue": 0.9,
+ "type": "float"
+ },
+ "colormap": {
+ "defaultValue": ,
+ "type": "std::__cxx11::basic_string, std::allocator >"
+ },
+ "textures.1": {
+ "internalName": "textures1",
+ "fallbackName": "texture1",
+ "defaultValue": ,
+ "type": "std::__cxx11::basic_string, std::allocator >"
+ },
+ "textures.2": {
+ "internalName": "textures2",
+ "fallbackName": "texture2",
+ "defaultValue": ,
+ "type": "std::__cxx11::basic_string, std::allocator >"
+ },
+ "textures.3": {
+ "internalName": "textures3",
+ "fallbackName": "texture3",
+ "defaultValue": ,
+ "type": "std::__cxx11::basic_string, std::allocator >"
+ },
+ "textures.4": {
+ "internalName": "textures4",
+ "fallbackName": "texture4",
+ "defaultValue": ,
+ "type": "std::__cxx11::basic_string, std::allocator >"
+ },
+ "cegTag": {
+ "description": "The name, without prefixes, of a CEG to be emitted by the projectile each frame.",
+ "defaultValue": ,
+ "type": "std::__cxx11::basic_string, std::allocator >"
+ },
+ "explosionGenerator": {
+ "defaultValue": ,
+ "type": "std::__cxx11::basic_string, std::allocator >"
+ },
+ "bounceExplosionGenerator": {
+ "defaultValue": ,
+ "type": "std::__cxx11::basic_string, std::allocator >"
+ },
+ "soundTrigger": {
+ "type": "bool"
+ },
+ "soundStart": {
+ "defaultValue": ,
+ "type": "std::__cxx11::basic_string, std::allocator >"
+ },
+ "soundHitDry": {
+ "fallbackName": "soundHit",
+ "defaultValue": ,
+ "type": "std::__cxx11::basic_string, std::allocator >"
+ },
+ "soundHitWet": {
+ "fallbackName": "soundHit",
+ "defaultValue": ,
+ "type": "std::__cxx11::basic_string, std::allocator >"
+ },
+ "soundStartVolume": {
+ "defaultValue": -1,
+ "type": "float"
+ },
+ "soundHitDryVolume": {
+ "fallbackName": "soundHitVolume",
+ "defaultValue": -1,
+ "type": "float"
+ },
+ "soundHitWetVolume": {
+ "fallbackName": "soundHitVolume",
+ "defaultValue": -1,
+ "type": "float"
+ }
+ }
+}
diff --git a/_includes/head.html b/_includes/head.html
new file mode 100644
index 0000000000..ca82cb0807
--- /dev/null
+++ b/_includes/head.html
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+ {% if site.ga_tracking != nil %}
+ {% assign ga_tracking_ids = site.ga_tracking | split: "," %}
+
+
+ {% endif %}
+
+ {% if site.search_enabled != false %}
+
+ {% endif %}
+
+ {% if site.mermaid %}
+ {% if site.mermaid.path %}
+
+ {% else %}
+
+ {% endif %}
+ {% endif %}
+
+
+
+
+
+ {% for file in site.static_files %}
+ {% if file.path == site.favicon_ico or file.path == '/favicon.ico' %}
+ {% assign favicon = true %}
+ {% endif %}
+ {% endfor %}
+ {% if favicon %}
+
+ {% endif %}
+
+ {% seo %}
+
+ {% include head_custom.html %}
+
+
diff --git a/_includes/header_custom.html b/_includes/header_custom.html
new file mode 100644
index 0000000000..bf38de64c9
--- /dev/null
+++ b/_includes/header_custom.html
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/_layouts/post.html b/_layouts/post.html
new file mode 100644
index 0000000000..93bd81d917
--- /dev/null
+++ b/_layouts/post.html
@@ -0,0 +1,21 @@
+---
+layout: default
+---
+
+{{ content }}
+
+{% assign author = site.authors | where: 'short_name', page.author | first %}
+
+{% if author != nil %}
+{% assign contributor = site.github.contributors | where: 'login', author.github | first %}
+
+
+Written by: {{author.short_name}}
+
+{% if contributor != nil and contributor != false %}
+
+
+
+{% endif %}
+
+{% endif %}
diff --git a/_sass/content-nocharset.scss b/_sass/content-nocharset.scss
new file mode 100644
index 0000000000..032f8ef159
--- /dev/null
+++ b/_sass/content-nocharset.scss
@@ -0,0 +1,237 @@
+// Styles for rendered markdown in the .main-content container
+// stylelint-disable selector-no-type, max-nesting-depth, selector-max-compound-selectors, selector-max-type, selector-max-specificity, selector-max-id
+
+.main-content {
+ line-height: $content-line-height;
+
+ ol,
+ ul,
+ dl,
+ pre,
+ address,
+ blockquote,
+ .table-wrapper {
+ margin-top: 0.5em;
+ }
+
+ a {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ ul,
+ ol {
+ padding-left: 1.5em;
+ }
+
+ li {
+ .highlight {
+ margin-top: $sp-1;
+ }
+ }
+
+ ol {
+ list-style-type: none;
+ counter-reset: step-counter;
+
+ > li {
+ position: relative;
+
+ &::before {
+ position: absolute;
+ top: 0.2em;
+ left: -1.6em;
+ color: $grey-dk-000;
+ content: counter(step-counter);
+ counter-increment: step-counter;
+ @include fs-3;
+
+ @include mq(sm) {
+ top: 0.11em;
+ }
+ }
+
+ ol {
+ counter-reset: sub-counter;
+
+ > li {
+ &::before {
+ content: counter(sub-counter, lower-alpha);
+ counter-increment: sub-counter;
+ }
+ }
+ }
+ }
+ }
+
+ ul {
+ list-style: none;
+
+ > li {
+ &::before {
+ position: absolute;
+ margin-left: -1.4em;
+ color: $grey-dk-000;
+ content: "•";
+ }
+ }
+ }
+
+ .task-list-item {
+ &::before {
+ content: "";
+ }
+ }
+
+ .task-list-item-checkbox {
+ margin-right: 0.6em;
+ margin-left: -1.4em;
+
+ // The same margin-left is used above for ul > li::before
+ }
+
+ hr + * {
+ margin-top: 0;
+ }
+
+ h1:first-of-type {
+ margin-top: 0.5em;
+ }
+
+ dl {
+ display: grid;
+ grid-template: auto / 10em 1fr;
+ }
+
+ dt,
+ dd {
+ margin: 0.25em 0;
+ }
+
+ dt {
+ grid-column: 1;
+ font-weight: 500;
+ text-align: right;
+
+ &::after {
+ content: ":";
+ }
+ }
+
+ dd {
+ grid-column: 2;
+ margin-bottom: 0;
+ margin-left: 1em;
+
+ blockquote,
+ div,
+ dl,
+ dt,
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6,
+ li,
+ ol,
+ p,
+ pre,
+ table,
+ ul,
+ .table-wrapper {
+ &:first-child {
+ margin-top: 0;
+ }
+ }
+ }
+
+ dd,
+ ol,
+ ul {
+ dl:first-child {
+ dt:first-child,
+ dd:nth-child(2) {
+ margin-top: 0;
+ }
+ }
+ }
+
+ .anchor-heading {
+ position: absolute;
+ right: -$sp-4;
+ width: $sp-5;
+ height: 100%;
+ padding-right: $sp-1;
+ padding-left: $sp-1;
+ overflow: visible;
+
+ @include mq(md) {
+ right: auto;
+ left: -$sp-5;
+ }
+
+ svg {
+ display: inline-block;
+ width: 100%;
+ height: 100%;
+ color: $link-color;
+ visibility: hidden;
+ }
+ }
+
+ .anchor-heading:hover,
+ .anchor-heading:focus,
+ h1:hover > .anchor-heading,
+ h2:hover > .anchor-heading,
+ h3:hover > .anchor-heading,
+ h4:hover > .anchor-heading,
+ h5:hover > .anchor-heading,
+ h6:hover > .anchor-heading {
+ svg {
+ visibility: visible;
+ }
+ }
+
+ summary {
+ cursor: pointer;
+ }
+
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6,
+ #toctitle {
+ position: relative;
+ margin-top: 1.5em;
+ margin-bottom: 0.25em;
+
+ + table,
+ + .table-wrapper,
+ + .code-example,
+ + .highlighter-rouge,
+ + .sectionbody .listingblock {
+ margin-top: 1em;
+ }
+
+ + p:not(.label) {
+ margin-top: 0;
+ }
+ }
+
+ > h1:first-child,
+ > h2:first-child,
+ > h3:first-child,
+ > h4:first-child,
+ > h5:first-child,
+ > h6:first-child,
+ > .sect1:first-child > h2,
+ > .sect2:first-child > h3,
+ > .sect3:first-child > h4,
+ > .sect4:first-child > h5,
+ > .sect5:first-child > h6 {
+ margin-top: $sp-2;
+ }
+}
diff --git a/_sass/custom/custom.scss b/_sass/custom/custom.scss
new file mode 100644
index 0000000000..51766ac182
--- /dev/null
+++ b/_sass/custom/custom.scss
@@ -0,0 +1,226 @@
+/****************************/
+/***** Jekyll Glossary ******/
+/****************************/
+
+/* vendored from https://raw.githubusercontent.com/erikw/jekyll-glossary_tooltip/main/lib/jekyll-glossary_tooltip/jekyll-glossary_tooltip.css */
+
+.jekyll-glossary {
+ position: relative;
+ display: inline-block;
+ border-bottom: 2px dotted #0074bd;
+ cursor: help;
+}
+
+.jekyll-glossary .jekyll-glossary-tooltip {
+ visibility: hidden;
+ width: 120px;
+ background-color: black;
+ color: #fff;
+ text-align: center;
+ font-size: 0.5em;
+ padding: 5px;
+ border-radius: 6px;
+
+ /* Position the tooltip text - see examples below! */
+ position: absolute;
+ z-index: 1;
+
+ width: 160px;
+ bottom: 100%;
+ left: 50%;
+ margin-left: -80px; /* Use half of the width to center the tooltip */
+
+}
+
+/* Show the tooltip text when you mouse over the tooltip container */
+.jekyll-glossary:hover .jekyll-glossary-tooltip {
+ visibility: visible;
+}
+
+/* Style the source link (if there is one provided in the glossary entry). */
+.jekyll-glossary-source-link:before {
+ content: "[source]"; // "(reference)", " " or whatever you want.
+}
+
+/* Arrow created with borders. */
+.jekyll-glossary .jekyll-glossary-tooltip::after {
+ content: " ";
+ position: absolute;
+ top: 100%;
+ left: 50%;
+ margin-left: -5px;
+ border-width: 5px;
+ border-style: solid;
+ border-color: black transparent transparent transparent;
+}
+
+/* Animation from invisible to visible on hover. */
+.jekyll-glossary .jekyll-glossary-tooltip {
+ opacity: 0;
+ transition: opacity 1s;
+}
+.jekyll-glossary:hover .jekyll-glossary-tooltip {
+ opacity: 1;
+}
+
+/***************************/
+/***** Theme switcher ******/
+/***************************/
+
+// vendored from https://github.com/argyleink/gui-challenges/blob/main/theme-switch
+
+@import"https://unpkg.com/open-props/easings.min.css";
+
+.sun-and-moon>:is(.moon,.sun,.sun-beams) {
+ transform-origin:center center
+}
+.sun-and-moon>:is(.moon,
+.sun) {
+ fill:var(--icon-fill)
+}
+.theme-toggle:is(:hover,
+:focus-visible)>.sun-and-moon>:is(.moon,
+.sun) {
+ fill:var(--icon-fill-hover)
+}
+.sun-and-moon>.sun-beams {
+ stroke:var(--icon-fill);
+ stroke-width:2px
+}
+.theme-toggle:is(:hover,
+:focus-visible) .sun-and-moon>.sun-beams {
+ stroke:var(--icon-fill-hover)
+}
+[data-theme=dark] .sun-and-moon>.sun {
+ transform:scale(1.75)
+}
+[data-theme=dark] .sun-and-moon>.sun-beams {
+ opacity:0
+}
+[data-theme=dark] .sun-and-moon>.moon>circle {
+ transform:translate(-7px)
+}
+@supports (cx: 1) {
+ [data-theme=dark] .sun-and-moon>.moon>circle {
+ transform:translate(0);
+ cx:17
+ }
+}
+@media (prefers-reduced-motion: no-preference) {
+ .sun-and-moon>.sun {
+ transition:transform .5s var(--ease-elastic-3)
+ }
+ .sun-and-moon>.sun-beams {
+ transition:transform .5s var(--ease-elastic-4),opacity .5s var(--ease-3)
+ }
+ .sun-and-moon .moon>circle {
+ transition:transform .25s var(--ease-out-5)
+ }
+ @supports (cx: 1) {
+ .sun-and-moon .moon>circle {
+ transition:cx .25s var(--ease-out-5)
+ }
+ }
+ [data-theme=dark] .sun-and-moon>.sun {
+ transform:scale(1.75);
+ transition-timing-function:var(--ease-3);
+ transition-duration:.25s
+ }
+ [data-theme=dark] .sun-and-moon>.sun-beams {
+ transform:rotate(-25deg);
+ transition-duration:.15s
+ }
+ [data-theme=dark] .sun-and-moon>.moon>circle {
+ transition-delay:.25s;
+ transition-duration:.5s
+ }
+}
+.theme-toggle {
+ --size: 2rem;
+ --icon-fill: hsl(210 10% 30%);
+ --icon-fill-hover: hsl(210 10% 15%);
+ background:none;
+ border:none;
+ padding:0;
+ inline-size:var(--size);
+ block-size:var(--size);
+ aspect-ratio:1;
+ border-radius:50%;
+ cursor:pointer;
+ touch-action:manipulation;
+ -webkit-tap-highlight-color:transparent;
+ outline-offset:5px
+}
+.theme-toggle>svg {
+ inline-size:100%;
+ block-size:100%;
+ stroke-linecap:round
+}
+[data-theme=dark] .theme-toggle {
+ --icon-fill: hsl(210 10% 70%);
+ --icon-fill-hover: hsl(210 15% 90%)
+}
+@media (hover: none) {
+ .theme-toggle {
+ --size: 48px
+ }
+}
+
+/***************************/
+/***** Custom Stuff ********/
+/***************************/
+
+// unvendored do not remove
+html[data-theme="dark"] button.theme-toggle, button.theme-toggle {
+ height: 100%;
+ margin: 0 0 0 1rem;
+}
+
+/* Enlarged dt */
+.main-content dl.big-dt, html[data-theme="dark"] dl.big-dt {
+ grid-template: auto / fit-content(20em) 1fr;
+}
+
+/* dt allowed to expand/contract */
+.main-content dl.dl-auto, html[data-theme="dark"] dl.dl-auto {
+ grid-template: auto / auto 1fr;
+}
+
+.aux-nav, html[data-theme="dark"] .aux-nav {
+ padding-right: 0;
+}
+
+.aux-nav-img img {
+ filter: invert(27%) sepia(14%) saturate(463%) hue-rotate(166deg) brightness(93%) contrast(85%);
+}
+
+.aux-nav-list-item:hover .aux-nav-img img {
+ filter: invert(13%) sepia(6%) saturate(958%) hue-rotate(169deg) brightness(96%) contrast(95%);
+}
+
+html:not(data-theme) .aux-nav-matrix img, html[data-theme="light"] .aux-nav-matrix img {
+ background-image: url("/spring/assets/matrix-logo.svg");
+}
+
+html[data-theme="dark"] .aux-nav-matrix img {
+ background-image: url("/spring/assets/matrix-logo-white.svg");
+}
+
+html:not(data-theme) .aux-nav-github img, html[data-theme="light"] .aux-nav-github img {
+ background-image: url("/spring/assets/github-mark.svg");
+}
+
+html[data-theme="dark"] .aux-nav-github img {
+ background-image: url("/spring/assets/github-mark-white.svg");
+}
+
+html .aux-nav-img img {
+ display: block;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+
+ background-repeat: no-repeat;
+ background-size: cover;
+ height: 32px;
+ padding-left: 100%; /* Equal to width of new image */
+}
diff --git a/_sass/modules-nocharset.scss b/_sass/modules-nocharset.scss
new file mode 100644
index 0000000000..cdf9509b4d
--- /dev/null
+++ b/_sass/modules-nocharset.scss
@@ -0,0 +1,16 @@
+// Import external dependencies
+@import "./vendor/normalize.scss/normalize";
+
+// Modules
+@import "./base";
+@import "./layout";
+@import "./content-nocharset";
+@import "./navigation";
+@import "./typography";
+@import "./labels";
+@import "./buttons";
+@import "./search";
+@import "./tables";
+@import "./code";
+@import "./utilities/utilities";
+@import "./print";
diff --git a/_scripts/get_engine_data.sh b/_scripts/get_engine_data.sh
new file mode 100755
index 0000000000..dc0b16d74f
--- /dev/null
+++ b/_scripts/get_engine_data.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+DATA_DIR="$SCRIPT_DIR/../_data"
+DATA_FILE="$DATA_DIR/latest_release.json"
+WORK_DIR="$SCRIPT_DIR/tmp"
+CONFIG_FILE="$DATA_DIR/configs.json"
+WDEFS_FILE="$DATA_DIR/weapondefs.json"
+COMMANDS_FILE="$DATA_DIR/unsynced_commands.json"
+SYNCED_COMMANDS_FILE="$DATA_DIR/synced_commands.json"
+
+DOWNLOAD_URL=$(jq -r '.assets[] | select(.name | contains("_linux-64-minimal-portable")).browser_download_url' $DATA_FILE)
+
+echo "> downloading latest engine release from $DOWNLOAD_URL"
+
+mkdir $WORK_DIR
+cd $WORK_DIR
+
+curl -L $DOWNLOAD_URL -o engine.7z
+7z -y e engine.7z spring
+
+echo "> writing $CONFIG_FILE"
+rm -f $CONFIG_FILE
+./spring --list-config-vars | grep -v "^\[t=" > $CONFIG_FILE
+
+echo "> writing $WDEFS_FILE"
+rm -f $WDEFS_FILE
+./spring --list-def-tags | grep -v "^\[t=" > $WDEFS_FILE
+
+echo "> writing $COMMANDS_FILE"
+rm -f $COMMANDS_FILE
+./spring --list-unsynced-commands | grep -v "^\[t=" > $COMMANDS_FILE
+
+echo "> writing $SYNCED_COMMANDS_FILE"
+rm -f $SYNCED_COMMANDS_FILE
+./spring --list-synced-commands | grep -v "^\[t=" > $SYNCED_COMMANDS_FILE
diff --git a/_scripts/get_release_data.sh b/_scripts/get_release_data.sh
new file mode 100755
index 0000000000..6199cd88c2
--- /dev/null
+++ b/_scripts/get_release_data.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+DATA_FILE="$SCRIPT_DIR/../_data/latest_release.json"
+
+echo "> writing $DATA_FILE"
+
+rm $DATA_FILE
+curl -s https://api.github.com/repos/beyond-all-reason/spring/releases/latest \
+ > $DATA_FILE
diff --git a/about.markdown b/about.markdown
new file mode 100644
index 0000000000..b6ac31f041
--- /dev/null
+++ b/about.markdown
@@ -0,0 +1,10 @@
+---
+layout: default
+title: About
+permalink: /about/
+---
+
+Recoil is an RTS engine.
+
+You can find the source code for Recoil at GitHub:
+[spring](https://github.com/beyond-all-reason/spring)
diff --git a/articles.markdown b/articles.markdown
new file mode 100644
index 0000000000..972cf8783e
--- /dev/null
+++ b/articles.markdown
@@ -0,0 +1,10 @@
+---
+layout: default
+title: Articles
+nav_order: 2
+has_children: true
+permalink: articles
+---
+
+# Articles
+{: .no_toc }
diff --git a/articles/ceg-operators.markdown b/articles/ceg-operators.markdown
new file mode 100644
index 0000000000..59284d39ef
--- /dev/null
+++ b/articles/ceg-operators.markdown
@@ -0,0 +1,190 @@
+---
+layout: post
+title: CEG operators
+parent: Articles
+permalink: articles/ceg-operators
+author: sprunk
+---
+
+## Basics
+
+You can customize some CEG entries by specifying a series of operators instead of just a number.
+This lets you apply limited logic to customize explosions.
+Each operation is specified by a single string.
+
+### Raw numbers
+
+A single number means just that number. So for example:
+```lua
+sizeGrowth = "3",
+```
+This sets `sizeGrowth` to 3. So far so simple.
+
+Some parameters, especially 3D vectors, accept multiple values. In that case, we separate then with the `,` (comma) operator.
+For example:
+```lua
+pos = "1, 2, 3",
+```
+This sets the position to x=1, y=2, and z=3.
+
+### Running value
+
+There is an implicit running value, which starts at 0 and on which all the operators work.
+A raw number is actually an "operatorless" operator that performs simple addition to that running value.
+So, one could think of the examples above as really being `0 +3` for `sizeGrowth` and `0 +1`, `0 +2`, and `0 +3` as the components of the `pos` vector respectively.
+
+
+To illustrate how this matters, consider this example. Note that there is no `,` between these!
+```lua
+sizeGrowth = "1 2 3",
+```
+The result of this is 6. This is because each of these is addition: `0 +1 +2 +3`, which nets 6.
+
+Similarly:
+```lua
+pos = "1 2, 3 4, 5 6",
+```
+This sets the components to 3 (0 +1 +2), 7 (0 +3 +4) and 11 (0 +5 +6) respectively.
+
+
+Putting a bunch of raw numbers next to each other doesn't make much sense, since we could have just written the sum directly, but the principle starts to matter when you mix operators.
+
+### Random (`r`)
+
+The `r` operator also works on the running value, but adds a random value between 0 and the operand.
+So, for example, `r4` gives a random value between 0 and 4. Practical hints:
+ * very useful to make explosions look less artificial.
+ * if you don't want to roll from 0, then just add the offset (remember a raw operatorless number performs addition).
+So, `3 r4` gives a value between 3 and 7.
+ * a common desire is to roll negative values, for example so that a directional particle can go either way.
+In that case, also use the offset. A common idiom is to use, for example, `-15 r30` to roll ±15.
+ * the value is distributed uniformly, but with some knowledge of statistics you could tweak it by stacking rolls.
+For example `r6` produces a flat uniform distribution, `r3 r3` a sort of triangle, and `r2 r2 r2` something smoother still.
+In practice this seems very underused though, and you can't make the distribution asymmetrical via this basic method,
+though you can via the more advanced ones below.
+
+### Index (`i`)
+
+The `i` operator multiplies its operand by the index of the particle, and adds this to the running value.
+When a generator spawns multiple particles of the same kind, each one is assigned an increasing index: 0, 1, 2, etc.
+
+For example, if an explosion spawns 4 particles and `size = "3 i2"`, then they will have sizes of 3, 5, 7 and 9 respectively.
+
+ * useful for spawning stuff in something resembling a line or cone.
+ * useful for scaling explosions via particle count, since the low-index particles will behave the same as before.
+ * remember this doesn't multiply the running value, or anything other than the operand.
+
+### Damage (`d`)
+
+The `d` operator multiplies its operand by the "damage" of an explosion.
+For example `d0.1` will net 10 for a 100-damage explosion, and 50 for a 500-damage explosion.
+
+Some practical remarks:
+ * for regular weapons, this is the "default" damage. Beware if you treat it as the "features" armor class (since they can't have a real armor class)!
+ * for CEG trails, damage is the TTL of the projectile. So you can for example make missile trails burn out.
+ * for explosions spawned by unit scripts, this defaults to 0 but you can set it to an arbitrary value.
+ * existing games prefer to have a separate effect for each similar weapon, so this is quite an uncommon operator, but if made to work could work wonders for consistency.
+
+## Advanced
+
+In addition to the running value, you have an access to a buffer with 16 "slots" whither you can save values for later use.
+Other than allowing complex math, these let you reuse a value for multiple components of a vector (across the `,` boundary which normally resets the running value).
+There are also some operators that involve more complex values than just addition.
+
+### Yank (`y`), add (`a`), and multiply (`x`)
+
+The `y` operator saves ("yanks") the current running value to the buffer under given index, and resets the running value to 0.
+The `a` operator adds to the current running value from given buffer.
+The `x` operator multiplies the running value by the value of given buffer.
+
+Examples:
+ * `10 r20 y7 5 r10 x7`. Rolls a random value 10-30 (see earlier lesson), saves it to buffer #7 (which resets running value to 0), rolls a different one 5-15, then multiplies it by the value of the contents of buffer #7 (i.e. the previous roll). The `foo yN bar xN` pattern is how you multiply things in general.
+ * `r10 y0 a0, 0, a0`. Rolls a value, saves it, loads it right back because of the reset. Reuses the value for the third component of the vector. This is how you can get diagonal values.
+
+### Sinus (`s`)
+
+The `s` operator treats its operand as an amplitude and the current running value as the phase, and _replaces_ the current running value with the result.
+For example `3 s2` is about 0.28, because that's `2 * sin(3 radians)`.
+
+ * only really makes sense with sources of unpredictability such as `r`, `i`, or `d`.
+ * there is no separate cosinus operator, but you can make a ghetto cosinus via `cos(x) = sin(π/2 + x)`, i.e. just do `1.57 sX` instead of just `sX`.
+ * good for making circular or spherical volumetric effects (for non-volumetric there's basic spread parameters like `emitRot`).
+
+### Sawtooth/modulo (`m`) and discretize (`k`)
+
+The `m` operator applies the modulo operator to the running value. The `k` operator truncates the running value to a multiple of the operand. So:
+ * `1 k7` is 0, `1 m7` is 1
+ * `6 k7` is 0, `6 m7` is 6
+ * `7 k7` is 7, `7 m7` is 0
+ * `8 k7` is 7, `8 m7` is 1
+ * `13 k7` is 7, `13 m7` is 6
+ * `14 k7` is 14, `14 m7` is 0
+
+### Power (`p`) and power buffer (`q`)
+
+The `p` operator raises the running value to the operandth power. The `q` operator is similar but takes the power from given buffer. The main use case is probably for getting x² or √x. Examples:
+ * `3p4` is 81, since that's 3⁴.
+ * `4y7 3q7` is also 81 (and leaves the 7th buffer slot with the value of 4).
+
+## Table
+
+Notation: V is the running value, X is the operand, and B denotes the buffer.
+
+
+
+ operator
+ effect
+
+
+ (none)
+ V += X
+
+
+ r
+ V += random(0; X)
+
+
+ i
+ V += X * index
+
+
+ d
+ V += X * damage
+
+
+ y
+ B[X] = V V = 0
+
+
+ a
+ V += B[X]
+
+
+ x
+ V *= B[X]
+
+
+ s
+ V = X * sin(V)
+
+
+ m
+ V = V % X
+
+
+ k
+ V = floor(V / X) * X
+
+
+ p
+ V = VX
+
+
+ q
+ V = VB[X]
+
+
+ ,
+ result = V V = 0
+
+
diff --git a/articles/modrules-and-others.markdown b/articles/modrules-and-others.markdown
new file mode 100644
index 0000000000..44334f25a8
--- /dev/null
+++ b/articles/modrules-and-others.markdown
@@ -0,0 +1,39 @@
+---
+layout: post
+title: Modrules and (un)related concepts
+parent: Articles
+permalink: articles/modrules-and-others
+author: sprunk
+---
+
+### Mod options, mod info, mod rules, rules params
+These concepts have similar names (which stems from how Recoil games used to be called "mods", even original/standalone ones)
+and all deal with customizability in some way, so often get confused with each other. But they are not directly related.
+This article will briefly describe all of them in a way that hopefully prevents any ambiguity.
+
+### Mod info
+* metadata about the game's archive. Things like name and version.
+* lives in `./modinfo.lua`, hence the name.
+* many mature games put `"$VERSION"` as the version. This is a magic value replaced by the Rapid distribution system with the actual version string. Check out Rapid's documentation for specifics.
+* this file is both necessary and sufficient for a Recoil game, and its contents can consist of just the `name` entry as well.
+* for engine devs: note that in engine internals, modinfo is **not** represented by the `CModInfo` class, that one is actually _mod rules_! Modinfo is a "class 1 meta file" only really referred to in the archive scanner.
+
+### Mod rules
+* a hardcoded set of knobs for tweaking engine behaviour.
+* some technical (like the choice of pathfinding system or allocation limits) and some gameplay related (like the resource cost scaling for repairing).
+* everything is a single constant global value. No per-unit rules, no changing at runtime, no rules outside the limited set exposed by the engine.
+* read from `./gamedata/modrules.lua`, hence the name. Internal engine C++ code stores them in the `CModInfo` class.
+* can depend on modoptions.
+
+### Mod options
+* per-match game setup.
+* a set of arbitrary key-value pairs supplied by the host; interpretation is solely up to the game.
+* usually live in `./modoptions.lua`, but this is just a convention for lobbies (this is where `unitsync` looks). The engine doesn't read this, nor enforce defaults etc.
+* usually used for things like enabling custom modes and game setups (add lava, disable units etc.), but also is the technical means for supplying singleplayer mission data.
+* maps can suggest and interpret modoptions too, these are often called mapoptions.
+
+### Rules params
+* dynamic per-unit/team or gamewide values.
+* arbitrary key-value pairs set and interpreted by the game.
+* usually used for storing attributes like "is burning" or "slowdown %" or such.
+* can depend on both modoptions and modrules.
diff --git a/articles/pathfinding.markdown b/articles/pathfinding.markdown
new file mode 100644
index 0000000000..4ee2abc927
--- /dev/null
+++ b/articles/pathfinding.markdown
@@ -0,0 +1,7 @@
+---
+layout: default
+title: Pathfinding
+parent: Articles
+permalink: articles/pathfinding
+published: false
+---
diff --git a/articles/select-command.markdown b/articles/select-command.markdown
new file mode 100644
index 0000000000..3dc366ca59
--- /dev/null
+++ b/articles/select-command.markdown
@@ -0,0 +1,210 @@
+---
+layout: default
+title: The select command
+parent: Articles
+permalink: /articles/select-command/
+---
+
+# The `select` command
+
+You can bind the command `select` to a key, in order to define custom selection commands. After select, you can specify a **selector**, that defines *which* units will be selected.
+
+This selector consists of three parts: `SOURCE+FILTER+CONCLUSION+`
+
+- *SOURCE*: Which units to choose from.
+- *FILTER*: Narrow down the list of units.
+- *CONCLUSION*: What to do exactly with the units that were chosen and filtered.
+
+These three parts are all succeeded by a literal plus sign (`+`), so there is one `+` between *SOURCE* and *FILTER*, one between *FILTER* and *CONCLUSION*, and one after *CONCLUSION*. Do **not** use a space (` `) anywhere in the entire expression.
+
+For example, `AllMap+_Builder+_SelectAll+` is a valid selector, where:
+
+- `AllMap` is the *SOURCE*
+- `_Builder` is the *FILTER* and
+- `_SelectAll` is the *CONCLUSION*.
+
+Note that there is an **underscore** (`_`) between each element, even if there is already a plus sign (`+`), for hysterical raisins...
+
+## Source
+
+The *SOURCE* describes the set of units that you want to filter and pick a selection from. For players, these are restricted your team. It can be one of
+
+- `AllMap`: All active units on the entire map.
+- `Visible`: All active units that are currently visible.
+- `PrevSelection`: All units present in previous selection; that is, the one active before you hit the selection key.
+- `FromMouse_`: All units that are at most a distance of `` away from the mouse cursor.
+- `FromMouseC_`: Same as above, but using a vertical cylinder instead of a sphere. This is good for selecting airplanes or ships on deep water.
+
+## Filter
+
+The *FILTER* is an arbitrarily long list of filters.
+
+Here are the filters. Note that "units" generally means both buildings and mobile units. Typing both got old real quick.
+
+### `Not`
+
+ Every filter can be preceded by `Not` to negate it. You have to use a `_` to separate the `Not` from the filter, as in `Not_Builder`.
+
+### `AbsoluteHealth_`
+
+ Keep only units that have an absolute health greater than `` points.
+
+ - `AbsoluteHealth_100`: Keep only units that have **more** than 100 health points left.
+ - `Not_AbsoluteHealth_100`: Keep only units that have **less** than 101 health points left.
+
+### `Aircraft`
+
+ Keep only units that can fly.
+
+### `Builder`
+
+ Keep only units and buildings that can construct. This means Factories, Construction Turrets, Constructors, but not Rezzers.
+
+### `Buildoptions`
+
+ Keep only units that can build other units or buildings.
+
+### `Building`
+
+ Keep only buildings, not mobile units.
+
+### `Category_`
+
+ Keep only units of category ``
+
+### `Cloak`
+
+ Keep only units that can cloak.
+
+### `Cloaked`
+
+ Keep only units that are currently cloaked.
+
+### `Guarding`
+
+ Keep only units that currently have a **Guard** order.
+
+### `IdMatches_`
+
+ Keep only units whose internal name (unitDef name) matches `` **exactly**.
+
+ - `IdMatches_armcom`: keep only Armada Commanders (internally named `armcom`).
+
+### `Idle`
+
+ Keep only units that are currently idle, i.e. do not have any active order.
+
+### `InGroup_`
+ Keep only units that are in control group ``.
+
+ - `Not_InGroup_`: keep all units that are **not** currently in control group ``.
+
+### `InHotkeyGroup`
+
+ Keep only units that are in any control group.
+
+ - `Not_InHotkeyGroup`: keep all units that are **not** currently in any control group.
+
+### `InPrevSel`
+
+ Keep only units of the same type (unitDefID) as any unit in the selection before this `select` command was run.
+
+### `Jammer`
+
+ Keep only units that have a jammer radius greater than 0.
+
+### `ManualFireUnit`:
+
+ Keep only units that have a weapon that requires manual firing (currently only the commanders and Armada Thor).
+
+### `NameContain_`
+
+ Keep only units whose name contains the ``.
+
+### `Radar`
+
+ Keep only units that have a radar or sonar radius greater than 0.
+
+### `Resurrect`
+
+ Keep only units that can resurrect other units.
+
+### `RelativeHealth_`
+
+ Keep only units that have health greater than `` percent.
+
+ Example:
+ - `Not_RelativeHealth_10`: Keep only units that have less than 10% health.
+
+### `RulesParamEquals__`
+
+ Keep only units where the `` rules parameter has the exact value ``.
+
+### `Stealth`
+
+ Keep only units that are stealthy.
+
+### `Transport`
+
+ Keep only units that can transport other units.
+
+### `Waiting`
+
+ Keep only units that currently have a **Wait** order.
+
+### `WeaponRange_`
+
+ Keep only units that have a maximum weapon range greater than ``.
+
+### `Weapons`
+
+ Keep only units that have any weapons.
+
+
+## Conclusion
+
+The *CONCLUSION* specifies what to do with the units that are left from the source after running through all the filters.
+
+If the *CONCLUSION* starts with `_ClearSelection`, your new selection will replace the old one; otherwise, it will just add to it. It must be followed by exactly one of:
+
+- `SelectAll`: all units
+- `SelectOne`: one unit, will also center the camera on that unit. This command remembers which unit was selected, on repeating the selection command, the **next** unit will be selected, so you can cycle through all matching units.
+- `SelectClosestToCursor`: one unit, the one closest to the mouse cursor.
+- `SelectNum_`: `` units. Repeating this command adds `` more units.
+- `SelectPart_`: `` percent of the units.
+
+
+# Examples
+Recall that between every two tokens, there must be an underscore `_`, even if there is also a `+`. Another way to put it is that before every word in your selector except the *SOURCE*, there must be an underscore.
+
+Some examples. Again, "unit" also includes buildings.
+
+- `AllMap++_ClearSelection_SelectAll+`
+
+ Selects everything on the entire map.
+
+- `AllMap+_Builder_Idle+_ClearSelection_SelectOne+`
+
+ Selects any (one) idle builder (unit or building) on entire map. Repeatedly running this command will cycle through all idle builders.
+
+- `AllMap+_Radar+_ClearSelection_SelectAll+`
+
+ Selects all units with radar/sonar/jammer.
+
+- `AllMap+_Not_Aircraft_Weapons+_ClearSelection_SelectAll+`
+
+ Selects all non-aircraft armed units
+
+- `AllMap+_InPrevSel+_ClearSelection_SelectAll+`
+
+ Selects all units of any type that was in your previous selection.
+
+ Note that up to now, all keys said `ClearSelection`, hence they replaced your old selection.
+
+- `AllMap+_InPrevSel_Not_InHotkeyGroup+_SelectAll+`
+
+ Selects all units of any type that was in your previous selection, unless they are already in a hotkey group.
+
+- `PrevSelection+_Not_Building_Not_RelativeHealth_30+_ClearSelection_SelectAll+`
+
+ From your previous selection, leaves everything that is below 30% health, and not a building. (Use this to quickly retreat damaged units.)
diff --git a/articles/team-terminology.markdown b/articles/team-terminology.markdown
new file mode 100644
index 0000000000..f2225763f6
--- /dev/null
+++ b/articles/team-terminology.markdown
@@ -0,0 +1,89 @@
+---
+layout: post
+title: Team terminology
+parent: Articles
+permalink: articles/team-terminology
+author: sprunk
+---
+
+## Overview
+
+Often players want to play as a team, or conduct diplomacy with each other.
+This article aims to explain Recoil's somewhat confusing terminology behind the various team-related entities and how they relate to each other.
+
+### Allyteam vs team
+
+What most people would naturally call a team is called an *"allyteam"* in Recoil terminology.
+A *"team"* is a single element of an *"allyteam"*. *Teams* are permanently bound to an *allyteam*.
+
+For example, NATO would be an *allyteam* while USA and UK would be *teams*, because they are separate entities but are in the same alliance, sharing goals and intel.
+For modders coming from Supreme Commander, the *team* is what SupCom calls an "army".
+
+*Teams* each have their own:
+ * units
+ * resources
+ * colour
+ * starting point
+ * faction (aka side)
+ * any other custom extra traits you add.
+
+*Teams* in the same *allyteam* always share some traits (meaning that, these operate on the level of *allyteams*):
+ * visibility (this includes sight, other sensors such as radar, but also reading of various unit traits that aren't readable by enemies even in sight, for example mana if a game wants to implement that)
+ * diplomacy towards other *allyteams* (in particular, all *teams* in an *allyteam* are never hostile to each other)
+ * victory goals
+
+### Team vs player
+
+A *team* is generally controlled by a *player* or an AI.
+An AI is not considered a *player* and the interfaces for dealing with AIs are separate to those for dealing with players,
+but generally they fill the same role of controlling a *team*.
+
+Control of a *team* is not exclusive.
+In particular, a *team* can be controlled by two or more *players* (or AIs, or a mix thereof) simultaneously (think SC2 Archon Mode).
+This is sometimes referred to as "comsharing" in the community for historical reasons.
+In that case all of them can exercise control over the team equally.
+
+Control of a *team* is also not permanent.
+*Players* can start controlling a different team (losing control of the previous *team*).
+In particular *players* can also control no team at all, in which case they're just spectators.
+It is up to the game to let *players* change their *team* to a different one (they cannot do so at will), though they can always become a spectator.
+
+To go with the analogy above, if the US Army is a *team* then Patton and Eisenhower are *players*: they both have control over the army (simultaneously with each other), and the army itself is generally unaffected by personal changes in the command staff: it is not bound to its generals, but the generals are bound to the army.
+
+A *team* can also have no controllers.
+This usually happens when somebody disconnects, but you can have teams that are uncontrolled by design (for example to have a perspective change in a singleplayer mission, or to have rescuable units).
+
+### Regular player vs spectator
+
+Spectators are *players* not controlling any *team*.
+They have two modes of spectating, one is a full-view mode where they can see everything, and the other is to spectate as if they were on a particular *team* (meaning their UI will display that team's resources, they will only see what that team sees, etc).
+Spectators can change what team they are spectating, and to and from the full-view mode, at will.
+The engine also has an option to allow new players to join mid-game (as opposed to regular players reconnecting); such added people always end up as spectators (in particular, this means they will have seen the full state of the game while simulating).
+
+### Player vs AI
+
+An AI fulfils a similar role to a *player*, being there to control a *team*.
+One difference is that an AI is permanently bound to a *team* and cannot spectate.
+The API to deal with AIs is also separate to *players* (so, for example, the function to get all *players* will not return them, and a *team* may look uncontrolled if care is not taken to handle both of its *player* and AI controllers).
+There are two main types of AI: Lua AI and Skirmish AI.
+
+### Lua AI vs Skirmish AI
+
+A "skirmish" AI is hosted by one of the players and generally acts very similar to a *player*.
+It can read the game state via AI interface and works by giving units commands.
+Strictly speaking, it is their hosting player relaying commands - this means that this type of AI is subject to lag and will drop if the hosting player quits.
+On the other hand, only the host player is taking on the burden of simulating the AI.
+There are currently Skirmish AI bindings for C and Java (though distributing the Java runtime environment for a Java skirmish AI is up to the game).
+A game does not need explicit support for this kind of AI (meaning for example, somebody can homebrew one), though it will likely want to handle distribution and infrastructure issues (for example to block homebrew AI).
+
+A Lua AI generally has two components: a piece of game mechanics, and the AI instance itself which is just a handle to tell game mechanics which teams are legal to control.
+Since game mechanics have full control over the game state, this type of AI can do things like spawn units on its own (for a sort of PvE experience) .
+It can also control teams that aren't explicitly marked for control by the LuaAI handle (for example a LuaAI can be made to automatically control AFK players' teams, or Gaia units - see below).
+This type of AI is written in Lua (like all game code), has to be included in the game itself, and the code runs for every player in the game.
+
+### Gaia
+
+Gaia is a special *team* that is always present, uncontrolled, and is always in its own *allyteam*.
+It is generally meant for ownership of map features such as trees and rocks, but it also can have resources and own units.
+This can be used for example for PvE enemies - note that game mechanics still have control an uncontrolled *team* so it is not necessary to have an explicit AI for it.
+At the moment there is only one Gaia.
diff --git a/articles/unit-defs.markdown b/articles/unit-defs.markdown
new file mode 100644
index 0000000000..c23d4248cc
--- /dev/null
+++ b/articles/unit-defs.markdown
@@ -0,0 +1,178 @@
+---
+layout: post
+title: Unit defs
+parent: Articles
+permalink: articles/unit-defs
+author: sprunk
+---
+
+# Unit types basics
+
+**Each unit in Spring/Recoil belongs to a single type**.
+By default, all units of a type are the same as far as most traits (for example health) go.
+Units don't necessarily need to fully conform to their type - **most traits can be changed per-unit**.
+
+This is **similar to other RTS engines**.
+For example, a default Starcraft2 marine has 45 health.
+Specific marines can actually have 55 health (after an upgrade), or 22 health (with 50% difficulty handicap), or 200 health (if they're the special campaign marine Jim Raynor).
+But marines, as a generalized type, have 45 health.
+It works **essentially the same way in Recoil**.
+Note that the **type itself cannot be modified at runtime**, though you can still easily apply a modified value to every unit of a type.
+
+The **set of unit types is static**.
+You **cannot dynamically add new types**, though you **can generate them beforehand**, including via code.
+
+The information about a unit type is usually called a **unit def** (from "definition"), and sometimes the type itself is referred to by "unit def" as well.
+This article will talk about and compare the two ways that unit defs are often dealt with that are often confused.
+
+As a general remark, the same notes apply not just to unit types, but also feature types and weapon types and can be applied there directly.
+
+## Unit def files
+
+At their simplest, games can provide **a set of simple Lua files with unit defs in the `./units` subfolder**, which **return a table** like this:
+```lua
+-- ./units/light_tank.lua
+return {
+ light_tank = {
+ health = 100,
+ maxVelocity = 1,
+ requiresSuperSecretResearch = false,
+ customParams = { flammable = 1, },
+ ...
+ },
+}
+```
+The above defines a unit def named "light_tank" with the appropriate stats.
+Note that each def **must have a unique name**.
+
+Note also the keys used inside: `health` and `maxVelocity` are standard and interpreted by the engine, you can find their meanings in the documentation.
+**The `customParams` table is somewhat special as it is itself standard but its contents are not**: anything inside (in this case `customParams.flammable`) needs to be handled by the game.
+Lastly, `requiresSuperSecretResearch` is non-standard.
+We will get back to the non-standard ones later.
+
+In the example above, the filename matches the single def inside and is basically just a static set of values.
+This **is generally the convention** for various reasons (for example it makes it easier for a mod to replace units one by one, and the files can get fairly long), but it **doesn't have to** be the case.
+In particular, you **can put multiple units there and have Lua code inside** to generate values, for example:
+```lua
+-- ./units/various_tanks.lua
+local base_tank_health = Shared.base_tank_health
+return {
+ light_tank = {
+ health = base_tank_health * 1,
+ maxVelocity = 1,
+ requiresSuperSecretResearch = false,
+ customParams = { flammable = 1, },
+ ...
+ },
+ heavy_tank = {
+ health = base_tank_health * 2.5,
+ maxVelocity = 0.3,
+ requiresSuperSecretResearch = true,
+ customParams = { flammable = 0, },
+ ...
+ }
+}
+```
+
+At some point you **might want to post-process** these values.
+For example you'd like to try out a sweeping design change, or maybe the match at hand is a custom scenario with different rules.
+For those cases, **default engine content lets you supply a file, `./gamedata/unitdefs_post.lua`**, which has access to a `UnitDefs` table with all the defs.
+For example, let's say you want to make all units slightly faster, but the healthiest ones more fragile using some arbitrary formula:
+```lua
+-- ./gamedata/unitdefs_post.lua
+for unitDefName, unitDef in pairs(UnitDefs) do
+ UnitDefs[unitDefName] = lowerkeys(unitDef)
+end
+
+for unitDefName, unitDef in pairs(UnitDefs) do
+ if unitDef.maxvelocity then
+ unitDef.maxvelocity = unitDef.maxvelocity * 1.2
+ end
+
+ if unitDef.health and unitDef.health > 300 then
+ unitDef.health = 300 + math.sqrt(unitDef.health - 300)
+ end
+
+ if unitDef.requiressupersecretresearch then
+ unitDef.customparams.tech_level_required = 4
+ end
+end
+```
+
+First, the `lowerkeys` function.
+Maybe some def files defined "maxVelocity" with an uppercase 'V' and some "maxvelocity" with a lowercase 'v', maybe even some used "MAXVELOCITY".
+In Lua, these are all different keys.
+Calling lowerkeys **makes sure that handling those in post-processing does not become a hassle**.
+Some games put the lowerkeys call inside the individual def files as a convention; you also **don't have to do this at all** if you pay attention and don't expect this to be a problem.
+
+Note that **there are checks** so that calculation only happens if the value is defined, **even for the standard ones** (i.e. `if unitDef.health and...`).
+This is because **while the engine does fill in defaults** (so you don't need to define velocity for buildings, for instance) **it does so at a later point**: so far everything is still **just a regular Lua table**.
+In particular, you can make use of the fact that an entry is not defined and/or fill it with some default calculated by you.
+
+Another thing going on here is the handling non-standard entries in the table.
+Anything which is not a standard key **is going to be discarded by the engine after this point unless it's inside the `customparams` table**.
+This can be useful if you just want to define a helper for post-processing - in particular this can even be something like a function.
+`customParams` let you keep non-standard values, but **only allows strings as keys, and strings and numbers as values**.
+
+There is also a **pre-processing file, `./gamedata/unitdefs_pre.lua`**, which can prepare data **before any def files are read**.
+It exposes **a global `Shared` table**, which can be populated there and which can be seen used in one of the examples above.
+Use it to propagate reference values to multiple defs without having to redefine them.
+
+## The `UnitDefs` table inside wupgets
+
+This is where things get somewhat messy. The engine exposes a table also called `UnitDefs` to wupgets.
+However, **this is NOT the same table as the one above**.
+The table above gets parsed into internal engine structures and is gone.
+The engine exposes a new table with those parsed values. This means that, compared to unit def files:
+
+ * the overall table is **indexed by numerical IDs, not the name**.
+So it's (say) `UnitDefs[123]` instead of `UnitDefs["light_tank"]`.
+Default engine content provides **a `UnitDefNames` table indexed by the name** though.
+The internal name is also **provided in the table under the key `"name"`**.
+The majority of **wupget interfaces use the numerical ID**.
+
+ * keys are **not the same**.
+For example, metal cost is read as `buildCostMetal` from unit def files, but exposed as `metalCost` in `UnitDefs`.
+In particular, they often **have "proper" uppercase even if the post-processing file is all lowercase**.
+This may well be **the most common misconception** and mistake when it comes to defs!
+Remember, **don't copy-paste keys between unit def files and wupgets** or vice versa.
+
+ * unused values are discarded.
+In the example above, `UnitDefs[x].requireSuperSecretTech` (and the lowercase spelling) is `nil`.
+
+ * **values are not the same**.
+For example, speed is read as elmos/frame from unit def files, but exposed as elmos/second.
+Some values have caps or offsets applied. See the documentation for specifics.
+
+## Advanced technicalities
+
+Here's some looser remarks around these topics.
+
+### Unit def files
+
+In truth, the engine **only directly reads one file for all def file processing, which is `./gamedata/defs.lua`**.
+This file is **provided in basecontent** and for all the various def types (unit, weapon, etc) it loads a pre-processing file, individual legacy def files (TDF, FBI and other Total Annihilation formats), the individual Lua def files under `./units/`, and then the post-processing file.
+The practical effect is that you can **customize the loading process somewhat** (load things in a different order, or from elsewhere than `./units/`, etc.) if you don't like the default one.
+
+A limited number of **wupget interfaces are available** during def loading.
+This includes **getters involving the match** in general (map, player roster etc), of which most importantly **mod-options**.
+You can use them to customise a match (for example, maybe aircraft fly higher on maps with lava or something like that).
+
+VFS is also available, **as a game dev you can expose interfaces for modders** or mappers by attempting to load specific files.
+
+### UnitDefs
+
+A unitDef is a proxy table with the `__index` meta-method.
+**According to measurements** this makes it somewhat **slower than a plain Lua table**, so it might be worth **caching if a wupget mostly uses a single field** from it.
+
+There is a **defs-editing dev mode where you can edit defs**, toggled via `/editdefs` (requires cheats).
+In this mode, changes are done by just **assigning to a unitDef in Lua code**, which **isn't normally possible**.
+Keep in mind that there is **no standard widget** yet to allow easy editing, and that **editing the def files will do nothing**
+(of course unless you make your editing widget read them, but remember the caveat where the keys and values differ between
+unit defs and `UnitDefs`). This mode is **not usable for game logic** and will desync if used in multiplayer.
+
+There's three **minor differences between `WeaponDefs` and `UnitDefs`/`FeatureDefs`**:
+ * `WeaponDefs` are 0-indexed while the others are 1-indexed. Beware of `for i = 1, #WeaponDefs do`, this is incorrect!
+ * **negative weaponDefIDs are valid and mean things like lava or collisions**. Check the `Game.envDamageTypes` table.
+ * it is possible to iterate over all keys of a unitDef via `for key, value in unitDef:pairs() do`, but this is currently not possible for either weapon or feature defs.
+
diff --git a/articles/units-of-measurement.markdown b/articles/units-of-measurement.markdown
new file mode 100644
index 0000000000..5d8eea376c
--- /dev/null
+++ b/articles/units-of-measurement.markdown
@@ -0,0 +1,55 @@
+---
+layout: post
+title: Units of measurement
+parent: Articles
+permalink: articles/units-of-measurement
+author: sprunk
+---
+
+## Units of measurement
+
+In addition to standard units of measurement such as seconds or radians, Recoil uses some in-house units that warrant a bit of explanation.
+
+### Base
+
+ * **frames**. These represent the discrete, fundamental unit of time for simulation purposes.
+Everything in a simulation happens between two frames.
+Currently, a simulation at x1 speed runs frames at a constant 30 Hz (so a frame is 0.033s).
+On the other hand, it can run slower or faster depending on gamespeed (including at thousands Hz when catching up or skipping over a replay).
+Therefore, do not use frames to measure time for things that should use wall-clock time (for example interface animations), i.e. use `widget:Update(dt)` over `widget:GameFrame(f)`.
+The base frequency value in Hz is available to Lua as `Game.gameSpeed`.
+It is currently hardcoded by the engine and not configurable by games (despite being in the `Game` table and not `Engine`).
+
+* **elmos**. "Elmo" is the name for Recoil's arbitrary unit of distance. It is purposefully underdefined so that each game can have its own sense of scale.
+For example, maybe one game is some sort of galactic war and 1 elmo represents 1 parsec, while another game is about a war between bacteria and viruses and 1 elmo is 1 μm.
+Most existing content seems to assume it's 1 m or 12.5 cm, or within this order of magnitude, but there is nothing to enforce consistency.
+Almost all length/distance values are given in elmos (or derived values such as elmo/s for speed), unless otherwise noted.
+
+* **arbitrary**: many values, such as mass, are also in arbitrary units that a game could define on its own if it wanted to for world-building reasons.
+Unlike the elmo these aren't even named, so they're typically referred to as just, for example, "100 mass", "100 energy", or "100 map hardness".
+
+### Derived
+
+* **game square**. The map is divided into a grid of squares.
+The high-resolution yardmap grid is in squares, as is the heightmap (height is an interpolation between the corners of a square).
+The length of the edge of a game square in elmo is available as `Game.squareSize` to Lua.
+It is not configurable by games and is currently hard-coded to 8 (so a 1x1 square is 8x8 elmos).
+Note that for map creation, the supplied heightmap represents corners of squares (which is why its size has to be N/8 + 1).
+* **footprint square**. Footprints in unit defs are defined in squares of game squares (for historical reasons).
+Regular-resolution yardmap is defined per footprint square.
+The length of the edge of the footprint square in game squares is available to Lua as `Game.footprintScale` and is currently hard-coded to 2 (so a 1x1 footprint is 2x2 game squares).
+* **build square**. The grid to which construction of buildings is aligned.
+Similarly to footprints, it's in multiples of a regular game square.
+The length of the edge of a build square in elmos is available as `Game.buildSquareSize` to Lua and is currently hard-coded to 16 (which is the same as a footprint square, meaning that except for high-resolution yardmaps you can always fit buildings next to each other tightly).
+* **metalmap square**. The metal-map is divided into a grid which covers multiple game squares.
+Interfaces such as `Spring.GetMetalAmount` accept the co-ordinates in this unit.
+It is available to Lua as `Game.metalMapSquareSize` and its value is currently 16.
+Note that for map creation, the supplied metalmap represents the insides of metalmap squares (which is why its size has to be N/16).
+* **lobby map size**. This is the size of maps typically shown in lobbies and other such places.
+A 1x1 map is 512x512 elmos.
+This is merely a convention (though a strong one for historical reasons) and thus is not directly available to Lua (you can derive it via `Game.mapSizeX / Game.mapX` if you have a map loaded, though there isn't much point because `Game.mapX` is already about the only useful value in this unit).
+* **slow update**. Some performance-heavy things only happen to units once per slow-update.
+A slow-update happens once per 15 frames.
+It is a bit of an implementation detail, so it's not directly exposed, though some def entries related to allowing things to run more often are usually capped at the slow-update rate.
+* **TA angular unit**. A full circle is 65536 TA angular units.
+Used in some unit and weapon def entries - consult defs documentation for specifics.
diff --git a/articles/vfs-basics.markdown b/articles/vfs-basics.markdown
new file mode 100644
index 0000000000..d4dfd746ae
--- /dev/null
+++ b/articles/vfs-basics.markdown
@@ -0,0 +1,63 @@
+---
+layout: post
+title: VFS Basics
+parent: Articles
+permalink: articles/vfs-basics
+author: sprunk
+---
+
+## VFS basics
+
+### What is loaded?
+
+Recoil Engine **loads content from three main places** into its Virtual Filesystem (VFS): the game, the map, and the user's local files.
+The game and the map **are specified by the lobby** when launching an instance of Recoil.
+**Game content is primary** and it usually decides whether to even load content from the other two, with some exceptions (for example map layout is always taken from the map archive).
+
+### Archives
+
+Games and maps **typically come as archives** (a single compressed file).
+For development purposes, they can also be **regular folders as long as their name ends with ".SDD"**, though this is **not recommended for production** (for performance reasons).
+Archives **can specify dependency** upon other archives, so **if you want to build upon an existing game you don't need to copy-paste its whole contents** (and probably shouldn't).
+By default, games live in the `./games/` subfolder of your Recoil folder and maps live in `./maps/`, but a **lobby can specify arbitrary archives**.
+
+{: .warning }
+> At the moment, **files in dependencies are completely overridden** in the VFS and are not accessible.
+
+The user can also **specify local content folders** which are then loaded from, **if the game allows** that.
+By default, the Recoil folder is the read directory.
+In this case, there is usually **no archive - loose files are seen by the VFS**.
+Of course **an archive can be such loose file** and there are interfaces to load its contents.
+
+### Sync
+
+The **game and map are synced**, meaning their contents can be used as **authoritative data related to the simulation**.
+Local files are unsynced, so they **cannot even be accessed from synced contexts**.
+For example, the game can define that a tank has 100 health.
+The game **can give the map an opportunity to modify this**, so for example the map can say the tank has 200 health instead.
+But there is no way for local files to modify that further, unit health is part of the game mechanics simulation so the game cannot defer to local files here even if it wants to.
+What this means is that **local files are largely for local content like the UI**, and it is generally **safe to assume the VFS is under a game dev's control even if you don't pay attention**, as far as mechanics are concerned.
+
+### How do I defer to the other content?
+
+VFS interfaces tend to **expect a _mode_ parameter**, which lets you specify **where to look for and in what order**.
+The values are strings so **you can combine them** using the `..` operator.
+For example, if you want to include a file from the map but also have a game-side backup, you'd pass `VFS.MAP .. VFS.GAME` to `VFS.Include`.
+Since `VFS.RAW` was not passed, any existing loose file with the appropriate name among the user's local files is ignored.
+
+By paying attention to the VFS mode, you can **prevent loading unwanted content**.
+As mentioned above, requesting unsynced modes in synced contexts is also ignored.
+
+### Loose remarks
+
+There is a fourth place where content is loaded from, the **basecontent** archive.
+The engine **always loads** it and it contains various **bare necessities** for a functional game, such as default water texture or the basic wupget frameworks.
+Its content is **entirely optional** and can be avoided via the usual VFS mode interface, though even mature games will usually want to make use of its facilities.
+
+The engine **can also write files** in addition to reading them.
+Unlike multiple read-folders, there is **only a single write-folder** (defaults to the Recoil folder).
+Writing is done by general Lua interfaces such as `io` and `os`, not `VFS`.
+
+A somewhat unorthodox way to pass (synced) content is **via modoptions**.
+Modoptions can **contain data** that gameside code can act upon, and if you're brave enough you can even **pass Lua code** as a modoption to be excuted.
+This is one of the ways to let people **run their local files in a synced way**, by just forwarding them as modoptions.
diff --git a/assets/css/just-the-docs-themes.scss b/assets/css/just-the-docs-themes.scss
new file mode 100644
index 0000000000..b6fd209f28
--- /dev/null
+++ b/assets/css/just-the-docs-themes.scss
@@ -0,0 +1,83 @@
+---
+---
+
+{% if site.logo %}
+$logo: "{{ site.logo | relative_url }}";
+{% endif %}
+@import "./support/support";
+@import "./custom/setup";
+
+@import "./color_schemes/light";
+@import "./modules";
+{% include css/callouts.scss.liquid color_scheme = "light" %}
+
+html[data-theme="dark"] {
+@import "./color_schemes/dark";
+@import "./modules-nocharset";
+{% include css/callouts.scss.liquid color_scheme = "dark" %}
+}
+
+// fix for search using class in html tag
+html[data-theme="dark"].search-active {
+ .search {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ padding: 0;
+ }
+
+ .search-input-wrap {
+ height: $sp-10;
+ border-radius: 0;
+
+ @include mq(md) {
+ width: $search-results-width;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 3px 10px rgba(0, 0, 0, 0.08);
+ }
+ }
+
+ .search-input {
+ background-color: $grey-dk-250;
+
+ @include mq(md) {
+ padding-left: 2.3rem;
+ }
+ }
+
+ .search-label {
+ @include mq(md) {
+ padding-left: 0.6rem;
+ }
+ }
+
+ .search-results {
+ display: block;
+ }
+
+ .search-overlay {
+ width: 100%;
+ height: 100%;
+ opacity: 1;
+ transition: opacity ease $transition-duration, width 0s, height 0s;
+ }
+
+ @include mq(md) {
+ .main {
+ position: fixed;
+ right: 0;
+ left: 0;
+ }
+ }
+
+ .main-header {
+ padding-top: $sp-10;
+
+ @include mq(md) {
+ padding-top: 0;
+ }
+ }
+}
+
+{% include css/custom.scss.liquid %}
diff --git a/assets/github-mark-white.svg b/assets/github-mark-white.svg
new file mode 100644
index 0000000000..d5e6491854
--- /dev/null
+++ b/assets/github-mark-white.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/github-mark.svg b/assets/github-mark.svg
new file mode 100644
index 0000000000..37fa923df3
--- /dev/null
+++ b/assets/github-mark.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/guides/lua-vbo-vao-1.png b/assets/guides/lua-vbo-vao-1.png
new file mode 100644
index 0000000000000000000000000000000000000000..981aece9cb3734c8fdf4b5621704a25edaae6df6
GIT binary patch
literal 59905
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