<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.hoodedhorse.com/NEBULOUS_Fleet_Command/index.php?action=history&amp;feed=atom&amp;title=Point_Defense_Controller</id>
	<title>Point Defense Controller - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.hoodedhorse.com/NEBULOUS_Fleet_Command/index.php?action=history&amp;feed=atom&amp;title=Point_Defense_Controller"/>
	<link rel="alternate" type="text/html" href="https://wiki.hoodedhorse.com/NEBULOUS_Fleet_Command/index.php?title=Point_Defense_Controller&amp;action=history"/>
	<updated>2026-10-24T00:15:12Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.5</generator>
	<entry>
		<id>https://wiki.hoodedhorse.com/NEBULOUS_Fleet_Command/index.php?title=Point_Defense_Controller&amp;diff=3903&amp;oldid=prev</id>
		<title>76561199078160033: Create new page Point Defense Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.hoodedhorse.com/NEBULOUS_Fleet_Command/index.php?title=Point_Defense_Controller&amp;diff=3903&amp;oldid=prev"/>
		<updated>2026-10-13T22:01:39Z</updated>

		<summary type="html">&lt;p&gt;Create new page Point Defense Controller&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;The game&amp;#039;s &amp;#039;&amp;#039;&amp;#039;point defense controller&amp;#039;&amp;#039;&amp;#039; prioritizes targets based on a variety of factors. Analysis based on &amp;lt;code&amp;gt;Nebulous.Ships.PointDefenseController&amp;lt;/code&amp;gt; from the ilspy decompilation of game version &amp;lt;code&amp;gt;0.6.2.6:260903-1430&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Working loop==&lt;br /&gt;
Every two seconds, or when the PD target list changes, &amp;lt;code&amp;gt;Ships.PointDefenseController.SortPointDefensePriorities&amp;lt;/code&amp;gt; is called.&amp;lt;ref&amp;gt;&amp;lt;code&amp;gt;Nebulous.Ships.PointDefenseController.Update&amp;lt;/code&amp;gt;&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;SortPointDefensePriorities&amp;lt;/code&amp;gt; does a whole lot of things but primarily first sorts the list of all point defense targets then tasks turrets and AMMs down the list of targets, then launches decoys.&amp;lt;ref name=&amp;quot;spdp&amp;quot;&amp;gt;&amp;lt;code&amp;gt;Ships.PointDefenseController.SortPointDefensePriorities&amp;lt;/code&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Sorting the list==&lt;br /&gt;
First, &amp;lt;code&amp;gt;SortPointDefensePriorities&amp;lt;/code&amp;gt; calculates properties of each PD target and assigns them to it.&lt;br /&gt;
&amp;lt;pre lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
foreach (PDTarget target in _allTargets)&lt;br /&gt;
{&lt;br /&gt;
	Vector3 fromTargetToShip = (_ship.Position - target.Track.KnownPosition).normalized;&lt;br /&gt;
	Vector3 targetVelocity = target.Track.AbsoluteVelocity.normalized;&lt;br /&gt;
	target.Angle = Vector3.Angle(targetVelocity, fromTargetToShip);&lt;br /&gt;
	target.Range = Vector3.Distance(target.Track.KnownPosition, _ship.Position);&lt;br /&gt;
	target.TimeToImpact = target.Range.SafeDivideMaxVal(Vector3.Project(target.Track.AbsoluteVelocity, fromTargetToShip).magnitude);&lt;br /&gt;
	target.WeaponsAssigned = 0;&lt;br /&gt;
	target.SensorsAssigned = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt; &amp;lt;ref name=&amp;quot;spdp&amp;quot; /&amp;gt;&lt;br /&gt;
It then sorts the list of &amp;lt;code&amp;gt;_allTargets&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;PDTarget&amp;lt;/code&amp;gt; implements &amp;lt;code&amp;gt;System.IComparable&amp;lt;/code&amp;gt; so it is sorted normally.&lt;br /&gt;
&lt;br /&gt;
==Comparing PDTargets==&lt;br /&gt;
Sorting requires an object have some way of being distinguished as higher or lower than another object; this is the &amp;lt;code&amp;gt;CompareTo&amp;lt;/code&amp;gt; function that is defined by &amp;lt;code&amp;gt;IComparable&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;Ships.PointDefenseController+PDTarget.CompareTo(PDTarget other)&amp;lt;/code&amp;gt; is as follows:&lt;br /&gt;
&amp;lt;pre lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
if (this == other)&lt;br /&gt;
{&lt;br /&gt;
	return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
If both &amp;lt;code&amp;gt;this&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;other&amp;lt;/code&amp;gt; point at the same memory location (i.e. are exactly the same), then both are sorted equally (e.g. sorting two equal numbers).&lt;br /&gt;
&lt;br /&gt;
====Lemma 1: &amp;lt;code&amp;gt;sortAsPriority&amp;lt;/code&amp;gt;====&lt;br /&gt;
The &amp;lt;code&amp;gt;compareTo&amp;lt;/code&amp;gt; function is structured in such a way that priority targets will always take precedence over (be sorted in front of) non-priority targets. What defines a priority target is the boolean &amp;lt;code&amp;gt;SortAsPriority&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public bool SortAsPriority =&amp;gt; PlayerPriority || (IsDecoy &amp;amp;&amp;amp; IsDirectThreat);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
All priority targets are either manually prioritized (i.e. Z-prioed), or are both a decoy and a direct threat.&lt;br /&gt;
&lt;br /&gt;
====Lemma 2: &amp;lt;code&amp;gt;IsDirectThreat&amp;lt;/code&amp;gt;====&lt;br /&gt;
A direct threat is defined by the boolean &amp;lt;code&amp;gt;IsDirectThreat&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;pre lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
public bool IsDirectThreat&lt;br /&gt;
{&lt;br /&gt;
	get&lt;br /&gt;
	{&lt;br /&gt;
		if (IsCraft)&lt;br /&gt;
		{&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
		bool threat = Angle &amp;lt;= 10f;&lt;br /&gt;
		WasEverDirectThreat |= threat;&lt;br /&gt;
		return threat;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If a target is a craft, it cannot ever be a direct threat. Otherwise, if its velocity vector is within ten degrees of its direction towards the ship, it is a direct threat.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (SortAsPriority)&lt;br /&gt;
{&lt;br /&gt;
	if (other.SortAsPriority)&lt;br /&gt;
	{&lt;br /&gt;
		int sizeCompare = -MissileSize.CompareTo(other.MissileSize);&lt;br /&gt;
		if (sizeCompare != 0)&lt;br /&gt;
		{&lt;br /&gt;
			return sizeCompare;&lt;br /&gt;
		}&lt;br /&gt;
		return Range.CompareTo(other.Range);&lt;br /&gt;
	}&lt;br /&gt;
	return -1;&lt;br /&gt;
}&lt;br /&gt;
if (other.SortAsPriority)&lt;br /&gt;
{&lt;br /&gt;
	return 1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If &amp;lt;code&amp;gt;this&amp;lt;/code&amp;gt; is a priority target, and &amp;lt;code&amp;gt;other&amp;lt;/code&amp;gt; is also a priority target, then whichever target has a larger size takes precedence. If both targets have the same size, then whichever is closer takes precendence.&lt;br /&gt;
If &amp;lt;code&amp;gt;other&amp;lt;/code&amp;gt; is not a priority target, then &amp;lt;code&amp;gt;this&amp;lt;/code&amp;gt; takes precedence.&lt;br /&gt;
If &amp;lt;code&amp;gt;this&amp;lt;/code&amp;gt; is not a priority target, and &amp;lt;code&amp;gt;other&amp;lt;/code&amp;gt; is, then &amp;lt;code&amp;gt;other&amp;lt;/code&amp;gt; take precedence.&lt;br /&gt;
&lt;br /&gt;
====Lemma 3: Time to Impact====&lt;br /&gt;
&amp;lt;code&amp;gt;PDTarget.TimeToImpact&amp;lt;/code&amp;gt; is set by &amp;lt;code&amp;gt;SortPointDefensePriorities&amp;lt;/code&amp;gt; as seen above. &lt;br /&gt;
&amp;lt;pre lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
target.TimeToImpact = target.Range.SafeDivideMaxVal(Vector3.Project(target.Track.AbsoluteVelocity, fromTargetToShip).magnitude);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
It is calculated as the range to the target divided by the projected velocity towards the ship, and zero if the velocity is zero.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
if (IsDirectThreat &amp;amp;&amp;amp; other.IsDirectThreat)&lt;br /&gt;
{&lt;br /&gt;
	float ttiDiff = Mathf.Abs(TimeToImpact - other.TimeToImpact);&lt;br /&gt;
	if (ttiDiff &amp;lt;= 5f)&lt;br /&gt;
	{&lt;br /&gt;
		int sizeCompare2 = -MissileSize.CompareTo(other.MissileSize);&lt;br /&gt;
		if (sizeCompare2 != 0)&lt;br /&gt;
		{&lt;br /&gt;
			return sizeCompare2;&lt;br /&gt;
		}&lt;br /&gt;
		return invertRange ? (-TimeToImpact.CompareTo(other.TimeToImpact)) : TimeToImpact.CompareTo(other.TimeToImpact);&lt;br /&gt;
	}&lt;br /&gt;
	return invertRange ? (-TimeToImpact.CompareTo(other.TimeToImpact)) : TimeToImpact.CompareTo(other.TimeToImpact);&lt;br /&gt;
}&lt;br /&gt;
if (IsDirectThreat)&lt;br /&gt;
{&lt;br /&gt;
	return -1;&lt;br /&gt;
}&lt;br /&gt;
if (other.IsDirectThreat)&lt;br /&gt;
{&lt;br /&gt;
	return 1;&lt;br /&gt;
}&lt;br /&gt;
return invertRange ? (-TimeToImpact.CompareTo(other.TimeToImpact)) : TimeToImpact.CompareTo(other.TimeToImpact);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If both &amp;lt;code&amp;gt;this&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;other&amp;lt;/code&amp;gt; are direct threats, the code first calculates the difference between the time to impacts. If this is less than five seconds, the larger target takes precedence. If both targets are the same size, then whichever impacts first takes precedence. However, if &amp;lt;code&amp;gt;invertRange&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; &amp;lt;!--(potentially due to pdmsl settings? unsure of where this applies, needs to be checked)--&amp;gt;, then whichever impacts last takes precedence.&lt;br /&gt;
If the time to impact difference is greater than five seconds, whichever impacts first (or last) takes precedence.&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;this&amp;lt;/code&amp;gt; is a direct threat, and &amp;lt;code&amp;gt;other&amp;lt;/code&amp;gt; is not, then &amp;lt;code&amp;gt;this&amp;lt;/code&amp;gt; takes precedence.&lt;br /&gt;
If &amp;lt;code&amp;gt;other&amp;lt;/code&amp;gt; is a direct threat, and &amp;lt;code&amp;gt;this&amp;lt;/code&amp;gt; is not, then &amp;lt;code&amp;gt;other&amp;lt;/code&amp;gt; takes precedence.&lt;br /&gt;
&lt;br /&gt;
==Queuing point defense fire==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Queuing point defense missile launches==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Launching decoys==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Mechanics]]&lt;/div&gt;</summary>
		<author><name>76561199078160033</name></author>
	</entry>
</feed>