<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.fightorder.net/wiki/index.php?action=history&amp;feed=atom&amp;title=Recoil%3AMigrating_From_Spring</id>
	<title>Recoil:Migrating From Spring - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://www.fightorder.net/wiki/index.php?action=history&amp;feed=atom&amp;title=Recoil%3AMigrating_From_Spring"/>
	<link rel="alternate" type="text/html" href="https://www.fightorder.net/wiki/index.php?title=Recoil:Migrating_From_Spring&amp;action=history"/>
	<updated>2026-04-21T05:32:42Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://www.fightorder.net/wiki/index.php?title=Recoil:Migrating_From_Spring&amp;diff=2712&amp;oldid=prev</id>
		<title>Qrow at 06:28, 6 March 2026</title>
		<link rel="alternate" type="text/html" href="https://www.fightorder.net/wiki/index.php?title=Recoil:Migrating_From_Spring&amp;diff=2712&amp;oldid=prev"/>
		<updated>2026-03-06T06:28:02Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 23:28, 5 March 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l19&quot;&gt;Line 19:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 19:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Rendering fonts now obeys the GL color state. Text may appear in a different color than expected. To restore previous behavior, add a &amp;lt;code&amp;gt;gl.Color&amp;lt;/code&amp;gt; call before &amp;lt;code&amp;gt;gl.Text&amp;lt;/code&amp;gt;:&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Rendering fonts now obeys the GL color state. Text may appear in a different color than expected. To restore previous behavior, add a &amp;lt;code&amp;gt;gl.Color&amp;lt;/code&amp;gt; call before &amp;lt;code&amp;gt;gl.Text&amp;lt;/code&amp;gt;:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;syntaxhighlight lang=&quot;lua&quot;&lt;/del&gt;&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;code&lt;/ins&gt;&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;gl.Color(1, 1, 1, 1)  -- set white before drawing text&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;gl.Color(1, 1, 1, 1)  -- set white before drawing text&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;gl.Text(&amp;quot;Hello world&amp;quot;, x, y, size, options)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;gl.Text(&amp;quot;Hello world&amp;quot;, x, y, size, options)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;syntaxhighlight&lt;/del&gt;&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;code&lt;/ins&gt;&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Alternatively, use inline colour codes: &amp;lt;code&amp;gt;\255\rrr\ggg\bbb&amp;lt;/code&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Alternatively, use inline colour codes: &amp;lt;code&amp;gt;\255\rrr\ggg\bbb&amp;lt;/code&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Qrow</name></author>
	</entry>
	<entry>
		<id>https://www.fightorder.net/wiki/index.php?title=Recoil:Migrating_From_Spring&amp;diff=2711&amp;oldid=prev</id>
		<title>Qrow at 06:26, 6 March 2026</title>
		<link rel="alternate" type="text/html" href="https://www.fightorder.net/wiki/index.php?title=Recoil:Migrating_From_Spring&amp;diff=2711&amp;oldid=prev"/>
		<updated>2026-03-06T06:26:10Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 23:26, 5 March 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l3&quot;&gt;Line 3:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 3:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Recoil is a fork and continuation of the Spring RTS engine (version 105.0), maintained by the [https://github.com/beyond-all-reason Beyond All Reason] team. While Recoil is mostly compatible with Spring 105, divergences have naturally developed over time. This page lists the most relevant breaking changes and how to fix them when migrating a game or widget from Spring to Recoil.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Recoil is a fork and continuation of the Spring RTS engine (version 105.0), maintained by the [https://github.com/beyond-all-reason Beyond All Reason] team. While Recoil is mostly compatible with Spring 105, divergences have naturally developed over time. This page lists the most relevant breaking changes and how to fix them when migrating a game or widget from Spring to Recoil.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;For a quick overview of why you might choose Recoil over the original Spring, see [[Recoil:&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Choose &lt;/del&gt;Recoil]].&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;For a quick overview of why you might choose Recoil over the original Spring, see [[Recoil:&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Why &lt;/ins&gt;Recoil]].&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;__TOC__&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;__TOC__&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Qrow</name></author>
	</entry>
	<entry>
		<id>https://www.fightorder.net/wiki/index.php?title=Recoil:Migrating_From_Spring&amp;diff=2710&amp;oldid=prev</id>
		<title>Qrow: Created page with &quot;= Recoil: Migrating From Spring =  Recoil is a fork and continuation of the Spring RTS engine (version 105.0), maintained by the [https://github.com/beyond-all-reason Beyond All Reason] team. While Recoil is mostly compatible with Spring 105, divergences have naturally developed over time. This page lists the most relevant breaking changes and how to fix them when migrating a game or widget from Spring to Recoil.  For a quick overview of why you might choose Recoil over...&quot;</title>
		<link rel="alternate" type="text/html" href="https://www.fightorder.net/wiki/index.php?title=Recoil:Migrating_From_Spring&amp;diff=2710&amp;oldid=prev"/>
		<updated>2026-03-06T06:23:44Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;= Recoil: Migrating From Spring =  Recoil is a fork and continuation of the Spring RTS engine (version 105.0), maintained by the [https://github.com/beyond-all-reason Beyond All Reason] team. While Recoil is mostly compatible with Spring 105, divergences have naturally developed over time. This page lists the most relevant breaking changes and how to fix them when migrating a game or widget from Spring to Recoil.  For a quick overview of why you might choose Recoil over...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;= Recoil: Migrating From Spring =&lt;br /&gt;
&lt;br /&gt;
Recoil is a fork and continuation of the Spring RTS engine (version 105.0), maintained by the [https://github.com/beyond-all-reason Beyond All Reason] team. While Recoil is mostly compatible with Spring 105, divergences have naturally developed over time. This page lists the most relevant breaking changes and how to fix them when migrating a game or widget from Spring to Recoil.&lt;br /&gt;
&lt;br /&gt;
For a quick overview of why you might choose Recoil over the original Spring, see [[Recoil:Choose Recoil]].&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Versioning ==&lt;br /&gt;
&lt;br /&gt;
Recoil switched to a date-based versioning scheme beginning with version 2025.01. Version numbers jump from 105-xxxx to 2025.xx. Use &amp;lt;code&amp;gt;Engine.versionMajor&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Engine.versionMinor&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Engine.commitsNumber&amp;lt;/code&amp;gt; instead of the old commit-count scheme where possible.&lt;br /&gt;
&lt;br /&gt;
For feature detection without version comparisons, use the &amp;lt;code&amp;gt;Engine.FeatureSupport&amp;lt;/code&amp;gt; table (see [[#Feature Support Table|Feature Support Table]] below).&lt;br /&gt;
&lt;br /&gt;
== Lua API Changes ==&lt;br /&gt;
&lt;br /&gt;
=== Font Rendering ===&lt;br /&gt;
&lt;br /&gt;
Rendering fonts now obeys the GL color state. Text may appear in a different color than expected. To restore previous behavior, add a &amp;lt;code&amp;gt;gl.Color&amp;lt;/code&amp;gt; call before &amp;lt;code&amp;gt;gl.Text&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
gl.Color(1, 1, 1, 1)  -- set white before drawing text&lt;br /&gt;
gl.Text(&amp;quot;Hello world&amp;quot;, x, y, size, options)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, use inline colour codes: &amp;lt;code&amp;gt;\255\rrr\ggg\bbb&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Spring.Marker Functions ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Spring.MarkerAddPoint&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Spring.MarkerAddLine&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Spring.MarkerErasePosition&amp;lt;/code&amp;gt; no longer accept numerical &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; for the &amp;lt;code&amp;gt;onlyLocal&amp;lt;/code&amp;gt; parameter. Lua semantics now apply (0 is truthy). Change &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Before&lt;br /&gt;
Spring.MarkerAddPoint(x, y, z, text, 0)&lt;br /&gt;
Spring.MarkerAddLine(x1, y1, z1, x2, y2, z2, 0, playerId)&lt;br /&gt;
Spring.MarkerErasePosition(x, y, z, noop, 0, playerId)&lt;br /&gt;
&lt;br /&gt;
-- After&lt;br /&gt;
Spring.MarkerAddPoint(x, y, z, text, false)&lt;br /&gt;
Spring.MarkerAddLine(x1, y1, z1, x2, y2, z2, false, playerId)&lt;br /&gt;
Spring.MarkerErasePosition(x, y, z, noop, false, playerId)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Spring.GetConfig Functions ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Spring.GetConfigInt&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Spring.GetConfigFloat&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Spring.GetConfigString&amp;lt;/code&amp;gt; now accept &amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt; as the second argument (the default value to return if the key is not set). Previously, &amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt; was treated as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; (Int/Float) or &amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt; (String).&lt;br /&gt;
&lt;br /&gt;
To restore previous behavior:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local originalGetConfigInt = Spring.GetConfigInt&lt;br /&gt;
Spring.GetConfigInt = function(key, def)&lt;br /&gt;
    return originalGetConfigInt(key, def) or 0&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Spring.GetSelectedUnitsSorted and Spring.GetSelectedUnitsCounts ===&lt;br /&gt;
&lt;br /&gt;
The tables returned by &amp;lt;code&amp;gt;Spring.GetSelectedUnitsSorted&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Spring.GetSelectedUnitsCounts&amp;lt;/code&amp;gt; no longer contain an &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; key with the number of unitDefs. Use the second return value instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Before&lt;br /&gt;
local counts = Spring.GetSelectedUnitsCounts()&lt;br /&gt;
local unitDefsCount = counts.n&lt;br /&gt;
counts.n = nil&lt;br /&gt;
&lt;br /&gt;
-- After&lt;br /&gt;
local counts, unitDefsCount = Spring.GetSelectedUnitsCounts()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Spring.UnitIconSetDraw Renamed ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Spring.UnitIconSetDraw&amp;lt;/code&amp;gt; has been renamed to &amp;lt;code&amp;gt;Spring.SetUnitIconDraw&amp;lt;/code&amp;gt;. The old spelling still works but is deprecated and will be removed in a future version.&lt;br /&gt;
&lt;br /&gt;
=== Spring.GetUnitCommands / Spring.GetCommandQueue ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Spring.GetUnitCommands(unitID, 0)&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Spring.GetCommandQueue&amp;lt;/code&amp;gt; are deprecated for counting queue size. Use the new dedicated function instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Before&lt;br /&gt;
local count = Spring.GetUnitCommands(unitID, 0)&lt;br /&gt;
&lt;br /&gt;
-- After&lt;br /&gt;
local count = Spring.GetUnitCommandCount(unitID)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, &amp;lt;code&amp;gt;Spring.GetFactoryCommands(unitID, 0)&amp;lt;/code&amp;gt; is deprecated in favor of &amp;lt;code&amp;gt;Spring.GetFactoryCommandCount(unitID)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Iterating Synced Proxy Tables ===&lt;br /&gt;
&lt;br /&gt;
The functions &amp;lt;code&amp;gt;snext&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;spairs&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;sipairs&amp;lt;/code&amp;gt; for iterating synced proxy tables have been &amp;#039;&amp;#039;&amp;#039;removed&amp;#039;&amp;#039;&amp;#039;. They have been equivalent to the standard Lua &amp;lt;code&amp;gt;next&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;pairs&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;ipairs&amp;lt;/code&amp;gt; for years. Replace them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Before&lt;br /&gt;
for key, value in spairs(SYNCED.foo) do ... end&lt;br /&gt;
&lt;br /&gt;
-- After&lt;br /&gt;
for key, value in  pairs(SYNCED.foo) do ... end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== VFS Mapping API ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Spring.MapArchive&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Spring.UnmapArchive&amp;lt;/code&amp;gt; (and equivalently &amp;lt;code&amp;gt;VFS.MapArchive&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;VFS.UnmapArchive&amp;lt;/code&amp;gt;) have been temporarily removed due to sync-unsafety. Use &amp;lt;code&amp;gt;Spring.UseArchive&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;VFS.UseArchive&amp;lt;/code&amp;gt; in the meantime. The original functions may return at a future date.&lt;br /&gt;
&lt;br /&gt;
=== UnitUnitCollision Return Value ===&lt;br /&gt;
&lt;br /&gt;
The return value from the &amp;lt;code&amp;gt;UnitUnitCollision&amp;lt;/code&amp;gt; callin is now ignored, and only one event fires per collision pair (instead of two). There is currently no replacement for the old two-event behavior.&lt;br /&gt;
&lt;br /&gt;
=== gl.GetMatrix Removed ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gl.GetMatrix&amp;lt;/code&amp;gt; and the interface accessible from its returned matrix object have been removed. These were unused; no direct replacement is available.&lt;br /&gt;
&lt;br /&gt;
=== Removed Platform Constants ===&lt;br /&gt;
&lt;br /&gt;
The following depth buffer support constants have been removed:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Platform.glSupport16bitDepthBuffer&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;Platform.glSupport24bitDepthBuffer&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;Platform.glSupport32bitDepthBuffer&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Replace with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
Platform.glSupportDepthBufferBitDepth &amp;gt;= 16  -- or 24, or 32&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Game.allowTeamColors Removed ===&lt;br /&gt;
&lt;br /&gt;
The deprecated &amp;lt;code&amp;gt;Game.allowTeamColors&amp;lt;/code&amp;gt; entry (which was always &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;) has been removed. If you used it as a boolean condition, note that its removal inverts its effect — previously &amp;lt;code&amp;gt;if Game.allowTeamColors then&amp;lt;/code&amp;gt; was always true; now the variable is &amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt; (falsy).&lt;br /&gt;
&lt;br /&gt;
=== Removed UnitDefs Keys ===&lt;br /&gt;
&lt;br /&gt;
The following deprecated &amp;lt;code&amp;gt;UnitDefs&amp;lt;/code&amp;gt; keys have been removed (they previously returned zero with a warning):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Removed Key&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;techLevel&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;harvestStorage&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;extractSquare&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;canHover&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;drag&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;isAirBase&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cloakTimeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;minx&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;miny&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;minz&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;maxx&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;maxy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;maxz&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;midx&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;midy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;midz&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== tdfID Removed from WeaponDefs ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;tdfID&amp;lt;/code&amp;gt; field has been removed from weapon defs and the &amp;lt;code&amp;gt;WeaponDefs&amp;lt;/code&amp;gt; table. Any remaining interfaces receive &amp;lt;code&amp;gt;weaponDefID&amp;lt;/code&amp;gt; instead.&lt;br /&gt;
&lt;br /&gt;
=== loadstring Bytecode ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;loadstring&amp;lt;/code&amp;gt; in Lua no longer accepts bytecode by default, for safety and maintainability reasons. It still works in devmode.&lt;br /&gt;
&lt;br /&gt;
== Unit Defs ==&lt;br /&gt;
&lt;br /&gt;
=== Hovercraft and Ships Upright Behavior ===&lt;br /&gt;
&lt;br /&gt;
Hovercraft and ships brought out of water are no longer forced to be upright. To restore previous behavior, add &amp;lt;code&amp;gt;upright = true&amp;lt;/code&amp;gt; to all unit defs whose movedef is of the hovercraft or ship type.&lt;br /&gt;
&lt;br /&gt;
=== useFootPrintCollisionVolume ===&lt;br /&gt;
&lt;br /&gt;
Units with &amp;lt;code&amp;gt;useFootPrintCollisionVolume = true&amp;lt;/code&amp;gt; but no &amp;lt;code&amp;gt;collisionVolumeScales&amp;lt;/code&amp;gt; set will now actually use the footprint volume (previously they mistakenly used the model&amp;#039;s bounding sphere).&lt;br /&gt;
&lt;br /&gt;
To keep the old hitvolume behavior, set &amp;lt;code&amp;gt;useFootPrintCollisionVolume = false&amp;lt;/code&amp;gt; for units with no &amp;lt;code&amp;gt;collisionVolumeScales&amp;lt;/code&amp;gt;. This can be done in unit def post-processing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
for unitDefID, unitDef in pairs(UnitDefs) do&lt;br /&gt;
    if not unitDef.collisionvolumescales then&lt;br /&gt;
        unitDef.usefootprintcollisionvolume = nil&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tree Feature Defs ===&lt;br /&gt;
&lt;br /&gt;
The feature defs &amp;lt;code&amp;gt;treetype0&amp;lt;/code&amp;gt; through &amp;lt;code&amp;gt;treetype16&amp;lt;/code&amp;gt; are now provided by the basecontent archive instead of the engine itself. Games that shipped their own basecontent will know what to do; most games are unaffected.&lt;br /&gt;
&lt;br /&gt;
=== Firestarter Weapon Tag ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;firestarter&amp;lt;/code&amp;gt; weapon tag is no longer capped at 10000 in defs (which was 100 in Lua &amp;lt;code&amp;gt;WeaponDefs&amp;lt;/code&amp;gt; after rescaling). It is now uncapped.&lt;br /&gt;
&lt;br /&gt;
To restore the previous cap:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
for weaponDefID, weaponDef in pairs(WeaponDefs) do&lt;br /&gt;
    if weaponDef.firestarter then&lt;br /&gt;
        weaponDef.firestarter = math.min(weaponDef.firestarter, 10000)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== acceleration and brakeRate (Deprecation Warning) ===&lt;br /&gt;
&lt;br /&gt;
The unit def tags &amp;lt;code&amp;gt;acceleration&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;brakeRate&amp;lt;/code&amp;gt; are &amp;#039;&amp;#039;&amp;#039;scheduled&amp;#039;&amp;#039;&amp;#039; for a unit change from elmo/frame to elmo/second. They currently still work as before, but it is strongly recommended to migrate to &amp;lt;code&amp;gt;maxAcc&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;maxDec&amp;lt;/code&amp;gt; respectively, which will remain in elmo/frame:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- In unit def files or post-processing:&lt;br /&gt;
-- acceleration  →  maxAcc   (elmo/frame, unchanged)&lt;br /&gt;
-- brakeRate     →  maxDec   (elmo/frame, unchanged)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Def Validity Checks ===&lt;br /&gt;
&lt;br /&gt;
Some invalid or missing def values are now handled more strictly:&lt;br /&gt;
&lt;br /&gt;
* Negative values for health, speed, reverse speed, metal/energy/buildtime cause the unit def to be &amp;#039;&amp;#039;&amp;#039;rejected&amp;#039;&amp;#039;&amp;#039; (previously clamped to 0.1).&lt;br /&gt;
* Negative values for acceleration and brake rate cause rejection (previously, absolute value was used).&lt;br /&gt;
* Metal cost can now be 0 (undefined metal cost defaults to 0 instead of 1).&lt;br /&gt;
* Weapon &amp;lt;code&amp;gt;edgeEffectiveness&amp;lt;/code&amp;gt; can now be exactly 1 (previously capped at 0.999).&lt;br /&gt;
* Weapon damage and unit armor multiplier can now be 0.&lt;br /&gt;
&lt;br /&gt;
=== trackStretch Reciprocal Change ===&lt;br /&gt;
&lt;br /&gt;
The unit def &amp;lt;code&amp;gt;trackStretch&amp;lt;/code&amp;gt; values are now treated reciprocally. A stretch factor of 2 now means the track is stretched 2× longer (previously it was squeezed 0.5× shorter). Adjust your values accordingly.&lt;br /&gt;
&lt;br /&gt;
=== GroundDecals Springsetting ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;GroundDecals&amp;lt;/code&amp;gt; springsetting is now a boolean. The previous behavior of using it as a decal duration multiplier is gone. Use the new &amp;lt;code&amp;gt;scarTTL&amp;lt;/code&amp;gt; weapon def tag to set scar durations instead. Note: if you had explicitly set &amp;lt;code&amp;gt;scarTTL&amp;lt;/code&amp;gt; values, those are now used directly as the TTL (previously they were multiplied by the ground decal level, which defaulted to 3).&lt;br /&gt;
&lt;br /&gt;
=== Live Unit Footprint Size ===&lt;br /&gt;
&lt;br /&gt;
Live mobile units&amp;#039; footprint is now the size of their movedef (previously the unit def footprint). This affects bugger-off behavior, construction blocking, and the size of the built-in selection square. Unit defs are unaffected; individual units adjust if their movedef changes at runtime.&lt;br /&gt;
&lt;br /&gt;
== Gameplay Behavior ==&lt;br /&gt;
&lt;br /&gt;
=== Stop Command on Manual Share ===&lt;br /&gt;
&lt;br /&gt;
Manually shared units no longer receive the Stop command automatically. To replicate the old behavior, use the &amp;lt;code&amp;gt;UnitGiven&amp;lt;/code&amp;gt; callin in a gadget or widget:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
function wupget:UnitGiven(unitID, unitDefID, newTeam)&lt;br /&gt;
    if newTeam == Spring.GetMyTeamID() then  -- if in unsynced context&lt;br /&gt;
        Spring.GiveOrderToUnit(unitID, CMD.STOP, 0, 0)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Resurrecting Units ===&lt;br /&gt;
&lt;br /&gt;
Resurrecting units no longer overrides their health to 5%. To restore the old behavior, add a gadget with the following callin:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
function gadget:UnitCreated(unitID, unitDefID, teamID, builderID)&lt;br /&gt;
    if builderID and Spring.GetUnitWorkerTask(builderID) == CMD.RESURRECT then&lt;br /&gt;
        Spring.SetUnitHealth(unitID, Spring.GetUnitHealth(unitID) * 0.05)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== weapons groundBounce ===&lt;br /&gt;
&lt;br /&gt;
Weapons with &amp;lt;code&amp;gt;groundBounce = true&amp;lt;/code&amp;gt; will now bounce even if &amp;lt;code&amp;gt;numBounces&amp;lt;/code&amp;gt; is undefined. The default value of &amp;lt;code&amp;gt;numBounces = -1&amp;lt;/code&amp;gt; now correctly results in infinite bounces instead of 0. Set an explicit positive value of &amp;lt;code&amp;gt;numBounces&amp;lt;/code&amp;gt; if you want a finite number of bounces.&lt;br /&gt;
&lt;br /&gt;
=== Default Targeting Priority Random Component Removed ===&lt;br /&gt;
&lt;br /&gt;
The default targeting priority for typed units no longer includes a ±30% random component. Use &amp;lt;code&amp;gt;gadget:AllowWeaponTarget&amp;lt;/code&amp;gt; to restore the previous randomized behavior.&lt;br /&gt;
&lt;br /&gt;
=== Handicap No Longer Applies to Reclaim ===&lt;br /&gt;
&lt;br /&gt;
Handicap (resource income multiplier) no longer applies to reclaim operations.&lt;br /&gt;
&lt;br /&gt;
== Camera ==&lt;br /&gt;
&lt;br /&gt;
=== Camera Modifiers ===&lt;br /&gt;
&lt;br /&gt;
The following keyboard modifiers were unhardcoded from the engine:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Spring Camera:&amp;#039;&amp;#039;&amp;#039; rotating on the x (pitch) or y (yaw) axis with ALT + middle mouse button while moving the cursor.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Resetting camera:&amp;#039;&amp;#039;&amp;#039; ALT + mousewheel scroll down.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Pitch rotation:&amp;#039;&amp;#039;&amp;#039; CTRL + mousewheel.&lt;br /&gt;
&lt;br /&gt;
If games and players do not change engine defaults, no action is needed. To explicitly enable these modifiers as before, add the following keybindings:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bind Any+ctrl movetilt    -- rotates camera over x axis on mousewheel&lt;br /&gt;
bind Any+alt  movereset   -- resets camera state on mousewheel move&lt;br /&gt;
bind Any+alt  moverotate  -- rotates camera in x/y on MMB move (Spring cam)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Rendering ==&lt;br /&gt;
&lt;br /&gt;
=== LOD Rendering Removed ===&lt;br /&gt;
&lt;br /&gt;
LOD rendering (2D unit billboards when zoomed far out) has been removed, along with the &amp;lt;code&amp;gt;/distdraw&amp;lt;/code&amp;gt; command and the &amp;lt;code&amp;gt;UnitLodDist&amp;lt;/code&amp;gt; springsetting entry.&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Sky Removed ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AdvSky&amp;lt;/code&amp;gt; springsetting and the &amp;lt;code&amp;gt;/dynamicsky&amp;lt;/code&amp;gt; command (which made clouds move across the sky) have been removed. There is no direct replacement, though similar behavior can be achieved via custom Lua rendering.&lt;br /&gt;
&lt;br /&gt;
=== Screenshot Format Changed ===&lt;br /&gt;
&lt;br /&gt;
The default &amp;lt;code&amp;gt;/screenshot&amp;lt;/code&amp;gt; format is now PNG (was previously BMP/other). Review any automated processing pipelines that parse screenshot files. Screenshot and replay demo file names also now use a UTC timestamp format instead of a sequential number.&lt;br /&gt;
&lt;br /&gt;
=== Paletted Image Files ===&lt;br /&gt;
&lt;br /&gt;
Paletted image files are no longer accepted. Convert any paletted images to non-paletted format (e.g. standard RGBA PNG).&lt;br /&gt;
&lt;br /&gt;
=== Shader Changes for Unit Rendering ===&lt;br /&gt;
&lt;br /&gt;
Unit vertex shaders now receive TRS (Translation/Rotation/Scale) transforms instead of matrices. Code that calls &amp;lt;code&amp;gt;vbo:ModelsVBO()&amp;lt;/code&amp;gt; must update shader code. The skinning/bones interface at uniform location 5 was extended in version 2025.04 from &amp;lt;code&amp;gt;uvec2&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;uvec3&amp;lt;/code&amp;gt;. Update shaders from:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
// Old (pre-1775)&lt;br /&gt;
layout (location = 5) in uint pieceIndex;&lt;br /&gt;
&lt;br /&gt;
// After 1775 (bones/skinning era)&lt;br /&gt;
layout (location = 5) in uvec2 bonesInfo; // boneIDs, boneWeights&lt;br /&gt;
#define pieceIndex (bonesInfo.x &amp;amp; 0x000000FFu)&lt;br /&gt;
&lt;br /&gt;
// After 2025.04 (extended bone info)&lt;br /&gt;
layout (location = 5) in uvec3 bonesInfo; // boneID low byte, boneWeight, boneID high byte&lt;br /&gt;
#define pieceIndex (bonesInfo.x &amp;amp; 0x000000FFu)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Feature Support Table ==&lt;br /&gt;
&lt;br /&gt;
Recoil provides &amp;lt;code&amp;gt;Engine.FeatureSupport&amp;lt;/code&amp;gt;, a table of feature availability flags for forward/backward compatibility. Use it instead of &amp;lt;code&amp;gt;Script.IsEngineMinVersion&amp;lt;/code&amp;gt; where applicable, as it is self-documenting and does not assume linear commit numbering.&lt;br /&gt;
&lt;br /&gt;
Example usage:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
if Engine.FeatureSupport.rmlUiApiVersion then&lt;br /&gt;
    -- use rmlUI&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Key entries include:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;rmlUiApiVersion&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; || RmlUI GUI framework available&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hasExitOnlyYardmaps&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; || &amp;#039;e&amp;#039; yardmap tile available&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;NegativeGetUnitCurrentCommand&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; || Negative indices work in GetUnitCurrentCommand&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;noAutoShowMetal&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; → future &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; || Automatic metal map toggle deprecation tracking&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;maxPiecesPerModel&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;65534&amp;lt;/code&amp;gt; || Maximum pieces per model (was 254)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Death Event Changes ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;wupget:UnitDestroyed&amp;lt;/code&amp;gt; callin received several changes:&lt;br /&gt;
&lt;br /&gt;
* Now receives a 7th argument: &amp;lt;code&amp;gt;weaponDefID&amp;lt;/code&amp;gt;, the cause of death. This is never &amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt; — all causes of death are attributable.&lt;br /&gt;
* The builder is passed as the killer if a unit is reclaimed.&lt;br /&gt;
&lt;br /&gt;
New &amp;lt;code&amp;gt;Game.envDamageTypes&amp;lt;/code&amp;gt; constants identify the cause of death:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Constant !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AircraftCrashed&amp;lt;/code&amp;gt; || Aircraft hitting the ground&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Kamikaze&amp;lt;/code&amp;gt; || Unit exploding via kamikaze ability&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SelfD&amp;lt;/code&amp;gt; || Self-destruct command and countdown&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ConstructionDecay&amp;lt;/code&amp;gt; || Abandoned nanoframe disappearing&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Reclaimed&amp;lt;/code&amp;gt; || Killed via reclaim&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TurnedIntoFeature&amp;lt;/code&amp;gt; || Died due to &amp;lt;code&amp;gt;isFeature&amp;lt;/code&amp;gt; tag on completion&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TransportKilled&amp;lt;/code&amp;gt; || Was in a transport with no &amp;lt;code&amp;gt;releaseHeld&amp;lt;/code&amp;gt; when transport died&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FactoryKilled&amp;lt;/code&amp;gt; || Was being built in a factory that died&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FactoryCancel&amp;lt;/code&amp;gt; || Build order was cancelled in factory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnitScript&amp;lt;/code&amp;gt; || COB script ordered the unit&amp;#039;s death&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SetNegativeHealth&amp;lt;/code&amp;gt; || Unit had negative health for non-damage reasons (e.g. set via Lua)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;OutOfBounds&amp;lt;/code&amp;gt; || Unit was thrown far out of map bounds&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;KilledByCheat&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;/remove&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;/destroy&amp;lt;/code&amp;gt; command used&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;KilledByLua&amp;lt;/code&amp;gt; || Default cause when using &amp;lt;code&amp;gt;Spring.DestroyUnit&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;KilledByLua&amp;lt;/code&amp;gt; is guaranteed to be the last value. You can define custom damage type constants above it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
Game.envDamageTypes.MyCustomDeath = Game.envDamageTypes.KilledByLua - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other Notable Changes ==&lt;br /&gt;
&lt;br /&gt;
=== Python AI Bindings Removed ===&lt;br /&gt;
&lt;br /&gt;
Python bindings for AI have been removed. Only native C++ AIs are built by default via CMake.&lt;br /&gt;
&lt;br /&gt;
=== 32-bit Builds ===&lt;br /&gt;
&lt;br /&gt;
32-bit builds are no longer supported.&lt;br /&gt;
&lt;br /&gt;
=== Mandatory OpenGL Feature Support ===&lt;br /&gt;
&lt;br /&gt;
Support for non-power-of-2 textures, float textures, and framebuffer objects (FBO) is now mandatory. Systems that do not support these (all of which were common 15+ years ago) are no longer supported.&lt;br /&gt;
&lt;br /&gt;
=== /ally Command ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;/ally&amp;lt;/code&amp;gt; command no longer announces the alliance to unrelated players via a console message. The affected players still see the message. Use the &amp;lt;code&amp;gt;TeamChanged&amp;lt;/code&amp;gt; callin if you want to make alliance announcements public.&lt;br /&gt;
&lt;br /&gt;
=== Group Command Change ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/group add N&amp;lt;/code&amp;gt; no longer selects the entire group after adding units to it.&lt;br /&gt;
&lt;br /&gt;
=== Automatic Metal View Toggle (Deprecated) ===&lt;br /&gt;
&lt;br /&gt;
The metal view automatically toggling when a player begins building a metal extractor is deprecated. Disable it via &amp;lt;code&amp;gt;Spring.SetAutoShowMetal(false)&amp;lt;/code&amp;gt; and re-implement manually. An example widget is available at &amp;lt;code&amp;gt;(basecontent)/examples/Widgets/gui_autoshowmetal.lua&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== DrawUnit and DrawFeature Widget Callins (Deprecated) ===&lt;br /&gt;
&lt;br /&gt;
Widget drawcalls such as &amp;lt;code&amp;gt;wupget:DrawUnit&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;wupget:DrawFeature&amp;lt;/code&amp;gt;, etc. are deprecated. Migrate to alternative rendering approaches.&lt;br /&gt;
&lt;br /&gt;
=== Removed Springsettings ===&lt;br /&gt;
&lt;br /&gt;
The following springsettings have been removed:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Springsetting !! Replacement / Notes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AdvSky&amp;lt;/code&amp;gt; || No direct replacement; use custom Lua rendering&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnitLodDist&amp;lt;/code&amp;gt; || LOD rendering removed entirely&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UpdateWeaponVectorsMT&amp;lt;/code&amp;gt; || Removed (MT is now always on)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UpdateBoundingVolumeMT&amp;lt;/code&amp;gt; || Removed (MT is now always on)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AnimationMT&amp;lt;/code&amp;gt; || Removed after proving stable; animations always MT&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UsePBO&amp;lt;/code&amp;gt; || Already did nothing; removed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Removed Commands ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/distdraw&amp;lt;/code&amp;gt; || LOD rendering removed&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/dynamicsky&amp;lt;/code&amp;gt; || Dynamic sky removed&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/AdvModelShading&amp;lt;/code&amp;gt; || Removed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[Recoil:Choose Recoil]] — Why switch from Spring to Recoil&lt;br /&gt;
* [https://github.com/beyond-all-reason/RecoilEngine/tree/master/doc/site/content/changelogs Full Recoil Changelog]&lt;br /&gt;
* [https://beyond-all-reason.github.io/spring/ldoc/ Recoil Lua API Reference]&lt;br /&gt;
* [https://discord.gg/GUpRg6Wz3e Recoil Discord] — for help and support&lt;br /&gt;
&lt;br /&gt;
[[Category:Recoil]]&lt;br /&gt;
[[Category:Engine]]&lt;br /&gt;
[[Category:Migration]]&lt;/div&gt;</summary>
		<author><name>Qrow</name></author>
	</entry>
</feed>