Here is the vanilla script I am talking about so if anyone can look through it.
Code: Select all
<?xml version="1.0" encoding="utf-8"?>
<mdscript name="FactionGoal_Hold_Space" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="md.xsd">
<cues>
<!--Add goal to global variable-->
<cue name="RegisterGoal">
<actions>
<do_if value="not global.$FactionGoals?">
<create_list name="global.$FactionGoals"/>
</do_if>
<set_value name="Start.$Name" exact="'Hold Space'"/>
<append_to_list name="global.$FactionGoals" exact="table[$EvaluationCue = Evaluate, $EvaluateEventLib = null, $TriggerCue = Start]"/>
</actions>
</cue>
<library name="Evaluate">
<actions>
<do_all exact="$ClaimedSectors.count" counter="$Eval_Counter1">
<set_value name="$EvaluationTarget" exact="$ClaimedSectors.{$Eval_Counter1}"/>
<debug_text text="'%1 evaluating %2 for hold space.'.[$Faction, $EvaluationTarget.knownname]" chance="0"/>
<set_value name="$Valid" exact="true"/>
<!--Check if we are already holding the sector-->
<do_all exact="$Goals.count" counter="$Eval_Counter2">
<do_if value="$Goals.{$Eval_Counter2}.static == md.FactionGoal_Hold_Space.Start">
<do_if value="$Goals.{$Eval_Counter2}.$Target == $EvaluationTarget">
<debug_text text="'%1 evaluating %2 for hold target. Target already taken care of, discarding.'.[$Faction, $EvaluationTarget.knownname]" chance="0"/>
<set_value name="$Valid" exact="false"/>
<break/>
</do_if>
</do_if>
</do_all>
<do_if value="$Valid">
<set_value name="$MatchingIntel" exact="null"/>
<do_all exact="$Intel.count" counter="$Intel_Counter">
<do_if value="$Intel.{$Intel_Counter}.{1} == $EvaluationTarget">
<set_value name="$MatchingIntel" exact="$Intel.{$Intel_Counter}"/>
<break/>
</do_if>
</do_all>
<do_if value="$MatchingIntel">
<set_value name="$ReconData" exact="[$MatchingIntel.{2}, $MatchingIntel.{3}]"/>
<debug_text text="'Evaluation: %1 has prior intel on %2. Recon_NumObjects: %3 Last updated: %4'.[$Faction, $EvaluationTarget.knownname, $ReconData.{1}, $ReconData.{2}]" chance="$DebugChance2"/>
</do_if>
<do_else>
<set_value name="$ReconData" exact="[10, 0]"/>
<debug_text text="'Evaluation: %1 has no intel on %2. Recon_NumObjects: %3 Last updated: %4'.[$Faction, $EvaluationTarget.knownname, $ReconData.{1}, $ReconData.{2}]" chance="$DebugChance2"/>
</do_else>
<append_to_list name="$PriorityGoals" exact="table[
$FactionCue = namespace,
$Faction = $Faction,
$TriggerCue = global.$FactionGoals.{$i}.$TriggerCue,
$Target = $EvaluationTarget,
$ReconData = $ReconData,
$DebugChance = $DebugChance,
$DebugChance2 = $DebugChance2]"/>
<remove_value name="$MatchingIntel"/>
<remove_value name="$ReconData"/>
<debug_text text="'Set hold target for %1 as a priority target for %2.'.[$EvaluationTarget.knownname, $Faction]" chance="$DebugChance"/>
</do_if>
</do_all>
</actions>
</library>
<!--Instance the goal by passing a list.
This cue may be signalled with other parameters to trigger child cues e.g. event.param.{1} == 'generate_report' - See Process_Signal cue-->
<cue name="Start" instantiate="true" namespace="this" version="2">
<conditions>
<event_cue_signalled/>
<check_value value="this.state == cuestate.waiting and typeof event.param == datatype.table"/>
</conditions>
<actions>
<!--Params-->
<set_value name="$FactionCue" exact="event.param.$FactionCue"/>
<set_value name="$Faction" exact="event.param.$Faction"/>
<set_value name="$Target" exact="event.param.$Target" comment="Target sector"/>
<assert value="$Target.isclass.sector" text="$DebugText + 'Target is not a sector, not currently supported [Owen]'"/>
<!-- Recon_NumObjects is the number of hostile object "points" this faction thinks there are in the target space. If they have no clue, they assume there will be 10.
Recon_LastUpdate is when Recon_NumObjects was last updated. If working on an unverified assumption, this is 0.
IntelCurrent is set if the last time the faction got an update regarding Recon_NumObjects in the target space is less than an hour ago.
IntelUsed is set if Recon_NumObjects was already used to reset WantedShips.
If any new intel comes in via a mission, NewIntel is set in EvaluateEvent. This resets IntelUsed so that Faction will revise WantedShips. -->
<set_value name="$Recon_NumObjects" exact="event.param.$ReconData.{1}" comment="threat-level"/>
<set_value name="$Recon_LastUpdate" exact="event.param.$ReconData.{2}"/>
<!--***Debug***-->
<set_value name="$DebugChance" exact="@event.param.$DebugChance"/>
<set_value name="$DebugChance2" exact="@event.param.$DebugChance2"/>
<set_value name="$DebugText" exact="'(' + $Faction.id + ') ' + static.$Name + ': ' + $Target.knownname + '(' + $Target.owner.id + ') - '"/>
<debug_text text="$DebugText" chance="$DebugChance"/>
<!--***Initialise***-->
<set_value name="$Mood" exact="null"/>
<set_value name="$StateEvaluationDelay" exact="1ms"/>
<set_value name="$CurrentPhaseSubGoals" exact="[]"/>
<!--***Goal States***-->
<set_value name="$UnclaimTime" exact="-1s" comment="Time at which the faction no longer has a claim on the sector"/>
<!--***Invasions***-->
<set_value name="$Invasions" exact="[]"/>
<!--Find existing invasion goals of enemy factions to this sector-->
<set_value name="$FactionManagerKeys" exact="global.$FactionManagers.keys.list"/>
<do_all exact="$FactionManagerKeys.count" counter="$i">
<do_if value="global.$FactionManagers.{$FactionManagerKeys.{$i}}.$Faction.hasrelation.enemy.{$Faction}">
<set_value name="$EnemyGoals" exact="global.$FactionManagers.{$FactionManagerKeys.{$i}}.$Goals"/>
<do_all exact="$EnemyGoals.count" counter="$k">
<do_if value="$EnemyGoals.{$k}.static == md.FactionGoal_Invade_Space.Start">
<do_if value="$EnemyGoals.{$k}.$Target == $Target">
<debug_text text="$DebugText + 'Faction ' + $EnemyGoals.{$k}.$Faction + ' is already invading ' + $Target.knownname" context="false" chance="$DebugChance"/>
<append_to_list name="$Invasions" exact="$EnemyGoals.{$k}"/>
</do_if>
</do_if>
</do_all>
<remove_value name="$EnemyGoals"/>
</do_if>
</do_all>
<remove_value name="$FactionManagerKeys"/>
<!--Standby Ships
Ships already commandeered by the factiongoal but not currently used in a subgoal-->
<create_group groupname="$StandbyShips"/>
<!--Key = Ship, Value = StandbyStartTime-->
<set_value name="$StandbyShipTable" exact="table[]"/>
<set_value name="$ForceStrength" exact="0"/>
<!--TODO @Owen move to library to allow updating after initialisation-->
<!--Find sectors which may be a threat-->
<find_cluster_in_range name="$LocalClusters" object="$Target" maxdistance="2" multiple="true"/>
<set_value name="$LocalSectors" exact="[]"/>
<do_all exact="$LocalClusters.count" counter="$i">
<find_sector name="$LocalSectors" space="$LocalClusters.{$i}" multiple="true" append="true">
<!--<match_relation_of faction="$Faction" relation="neutral" comparison="ge"/>-->
</find_sector>
</do_all>
<remove_value name="$LocalClusters"/>
<!--TODO @Owen better check that entry points are actually in control of this faction before idling there-->
<create_group groupname="$EntryPoints"/>
<create_group groupname="$EnemyEntryPoints"/>
<find_cluster_in_range name="$AdjacentClusters" object="$Target" maxdistance="1" multiple="true"/>
<set_value name="$AdjacentSectors" exact="[]"/>
<do_all exact="$AdjacentClusters.count" counter="$i">
<find_sector name="$AdjacentSectors" space="$AdjacentClusters.{$i}" multiple="true" append="true"/>
</do_all>
<remove_value name="$AdjacentClusters"/>
<set_value name="$LocalEntryPoints" exact="[]"/>
<set_value name="$TargetCluster" exact="$Target.cluster"/>
<do_all exact="$AdjacentSectors.count" counter="$i">
<do_if value="$AdjacentSectors.{$i}.cluster == $TargetCluster">
<find_object name="$LocalEntryPoints" class="class.highwayentrygate" space="$AdjacentSectors.{$i}" destination="$Target" multiple="true"/>
</do_if>
<do_else>
<find_gate name="$LocalEntryPoints" destination="$Target" space="$AdjacentSectors.{$i}" multiple="true"/>
</do_else>
<set_value name="this.$IsEnemy" exact="$AdjacentSectors.{$i}.hasrelation.enemy.{$Faction}"/>
<do_all exact="$LocalEntryPoints.count" counter="$k">
<add_to_group groupname="$EntryPoints" object="$LocalEntryPoints.{$k}.exit"/>
<do_if value="this.$IsEnemy">
<add_to_group groupname="$EnemyEntryPoints" object="$LocalEntryPoints.{$k}.exit"/>
</do_if>
</do_all>
</do_all>
<remove_value name="$TargetCluster"/>
<remove_value name="$LocalEntryPoints"/>
</actions>
<patch sinceversion="2" state="complete">
<remove_value name="$Phase"/>
<remove_value name="$NewPhase"/>
<remove_value name="$PrepareStagingAreaStrength"/>
<set_value name="$UnclaimTime" exact="-1s" comment="Time at which the faction no longer has a claim on the sector"/>
</patch>
<cues>
<cue name="Init">
<actions>
<do_if value="@$FeedbackValue">
<!--Something happened during setup which requires this goal to be aborted-->
<signal_cue_instantly cue="Cleanup"/>
</do_if>
<do_else>
<!--Register this goal with the faction logic-->
<append_to_list name="$FactionCue.$Goals" exact="namespace"/>
</do_else>
</actions>
</cue>
<!--event.param.{1} == Signal ID
Other elements are custom-->
<cue name="Process_Signal" instantiate="true">
<conditions>
<event_cue_signalled cue="Start"/>
</conditions>
<actions>
<do_if value="event.param.{1} == 'evaluate_event'">
<signal_cue_instantly cue="Evaluate_Event" param="event.param.{2}"/>
</do_if>
<do_elseif value="event.param.{1} == 'add_subgoal'">
<signal_cue_instantly cue="Add_Subgoal" param="event.param.{2}"/>
</do_elseif>
<do_elseif value="event.param.{1} == 'remove_subgoal'">
<signal_cue_instantly cue="Remove_Subgoal" param="event.param.{2}"/>
</do_elseif>
<do_elseif value="event.param.{1} == 'reactivate_subgoal'">
<signal_cue_instantly cue="Reactivate_Subgoal" param="event.param.{2}"/>
</do_elseif>
<do_elseif value="event.param.{1} == 'add_standby_ship'">
<!--event.param = ['add_standby_ship', Ship, FeedbackList (Element 1 set to true if ship added as standby ship)-->
<signal_cue_instantly cue="Add_Standby_Ship" param="event.param" comment="Pass all parameters"/>
</do_elseif>
<do_elseif value="event.param.{1} == 'remove_standby_ship'">
<!--event.param = ['remove_standby_ship', Ship, Uncommandeer? (bool)-->
<signal_cue_instantly cue="Remove_Standby_Ship" param="event.param"/>
</do_elseif>
<do_elseif value="event.param.{1} == 'generate_report'">
<signal_cue_instantly cue="Generate_Report"/>
</do_elseif>
<do_else>
<assert value="false" text="'Signal ' + event.param + ' was not recognised [Owen]\n' + $DebugText" break="1"/>
</do_else>
</actions>
</cue>
<!--Signal cues-->
<cue name="Evaluate_Event" instantiate="true">
<conditions>
<event_cue_signalled/>
</conditions>
<actions>
<assert value="typeof event.param == datatype.list and event.param.count ge 2" text="'Invalid event parameters' + event.param + ' [Owen]\n' + $DebugText" break="1"/>
<set_value name="$EventParams" exact="event.param"/>
<do_if value="$EventParams.{2} == 'recon update'">
<!--Faction is holding this area-->
<do_if value="$Target == $EventParams.{4} or $EventParams.{4}.hascontext.{$Target}">
<do_if value="typeof $EventParams.{5} == datatype.list and (typeof $EventParams.{5}.{1}).isnumeric">
<set_value name="$Recon_NumObjects" exact="$EventParams.{5}.{1}" comment="threat-level"/>
<set_value name="$Recon_LastUpdate" exact="$EventParams.{5}.{2}"/>
<set_value name="$NewIntel"/>
<debug_text text="'New Intel received by %1 at %3: \n OpFor numbers updated: %2'.[$Faction, $Recon_NumObjects, $Recon_LastUpdate]" chance="$DebugChance2"/>
<!--TODO @Owen check the recon processing for holding space. Check if the below comment is still relevant-->
<!-- $Intel == [[$TargetSpace, $Recon_NumObjects, $Recon_LastUpdate], etc]
to do: if/when invasions actually take ownership of space:
if invasion is successful, wipe this entry from $Intel,
if invasion is not successful, update with what the invasion actually finds there?
Owen mentioned NPC ships reconnoitering. That could be used to update this as well if/when it gets in. -->
<set_value name="$Intel" exact="$FactionCue.$Intel"/>
<do_all exact="$Intel.count + 1" counter="$Intel_Counter">
<do_if value="$Intel_Counter gt $Intel.count">
<append_to_list name="$Intel" exact="[$Target, $EventParams.{5}.{1}, $EventParams.{5}.{2}]"/>
<debug_text text="'%1 has no prior intel on %2. Updating: OpFor: %3 Last Updated: %4'.[$Faction, $Intel.{$Intel.count}.{1}.knownname, $Intel.{$Intel.count}.{2}, $Intel.{$Intel.count}.{3}]" chance="$DebugChance2"/>
</do_if>
<do_elseif value="$Intel.{$Intel_Counter}.{1}" exact="$Target">
<set_value name="$Intel.{$Intel_Counter}.{2}" exact="$EventParams.{5}.{1}"/>
<set_value name="$Intel.{$Intel_Counter}.{3}" exact="$EventParams.{5}.{2}"/>
<debug_text text="'%1 updating intel on %2. Updating: OpFor: %3 Last Updated: %4'.[$Faction, $Intel.{$Intel_Counter}.{1}.knownname, $Intel.{$Intel_Counter}.{2}, $Intel.{$Intel_Counter}.{3}]" chance="$DebugChance2"/>
<break/>
</do_elseif>
</do_all>
<remove_value name="$Intel"/>
</do_if>
<do_else>
<debug_text text="'Unexpected recon update passed to this goal. ' + $EventParams.{5}" filter="error"/>
</do_else>
<break/>
</do_if>
</do_if>
<remove_value name="$EventParams"/>
</actions>
</cue>
<cue name="Generate_Report" instantiate="true">
<conditions>
<event_cue_signalled/>
</conditions>
<actions>
<debug_text text="'Hold Space - ' + $Faction.knownname + ' is set to hold Space: ' + $Target.knownname + ' (' + $Target.owner + ')'" context="false"/>
<debug_text text="'Has ' + $CurrentPhaseSubGoals.count + ' subgoals'" context="false"/>
<do_all exact="$CurrentPhaseSubGoals.count" counter="$i">
<do_if value="$CurrentPhaseSubGoals.{$i}.$GenerateReportCue?">
<signal_cue_instantly cue="$CurrentPhaseSubGoals.{$i}.$GenerateReportCue"/>
</do_if>
<do_else>
<debug_text text="'SUBGOAL - ' + $CurrentPhaseSubGoals.{$i}.$Cue" context="false"/>
</do_else>
</do_all>
</actions>
</cue>
<!--event.param = Subgoal registry table-->
<cue name="Add_Subgoal" instantiate="true">
<conditions>
<event_cue_signalled/>
</conditions>
<actions>
<!--TODO - flag subgoal as being related to something e.g. an invasion?-->
<assert value="typeof event.param == datatype.table" text="'parameter ' + event.param + ' was not a table [Owen]'" break="1"/>
<set_value name="this.$IDX" exact="$CurrentPhaseSubGoals.indexof.{event.param}"/>
<do_if value="this.$IDX">
<assert value="not $CurrentPhaseSubGoals.indexof.{event.param}" text="'Subgoal ' + event.param + ' was already in $CurrentPhaseSubGoals [Owen]'" break="1"/>
</do_if>
<do_else>
<append_to_list name="$CurrentPhaseSubGoals" exact="event.param"/>
<debug_text text="$DebugText + 'Adding subgoal ' + event.param.$Cue.$DebugText + ' - now has ' + $CurrentPhaseSubGoals.count + ' subgoals'" context="false" chance="$DebugChance"/>
</do_else>
</actions>
</cue>
<!--event.param = Subgoal registry table-->
<cue name="Remove_Subgoal" instantiate="true">
<conditions>
<event_cue_signalled/>
</conditions>
<actions>
<assert value="typeof event.param == datatype.table" text="'parameter ' + event.param + ' was not a table [Owen]'" break="1"/>
<assert value="$CurrentPhaseSubGoals.indexof.{event.param}" text="'Subgoal ' + event.param + ' is not a $CurrentPhaseSubGoals where it is expected to be [Owen]'" break="1"/>
<set_value name="this.$IDX" exact="$CurrentPhaseSubGoals.indexof.{event.param}"/>
<do_if value="this.$IDX">
<debug_text text="$DebugText + ' Removing subgoal: ' + event.param + ' from $CurrentPhaseSubGoals'" chance="$DebugChance"/>
<remove_value name="$CurrentPhaseSubGoals.{this.$IDX}"/>
</do_if>
</actions>
</cue>
<!--event.param = Subgoal registry table-->
<cue name="Reactivate_Subgoal" instantiate="true">
<conditions>
<event_cue_signalled/>
</conditions>
<actions>
</actions>
</cue>
<!--
event.param.{1} = signal ID 'add_standby_ship' (optional)
event.param.{2} = Ship
event.param.{3} = Result feedback list ref. Element 1 set to true if ship added as standby ship-->
<cue name="Add_Standby_Ship" instantiate="true">
<conditions>
<event_cue_signalled/>
</conditions>
<actions>
<set_value name="this.$Ship" exact="event.param.{2}"/>
<do_if value="typeof this.$Ship == datatype.component and this.$Ship.isclass.ship">
<assert value="this.$Ship.iscommandeered" text="'Standby ship ' + this.$Ship + ' ' + this.$Ship.knownname + ' is not commandeered [Owen]'"/>
<debug_text text="$DebugText + 'Adding ship ' + this.$Ship.knownname + ' ' + this.$Ship + ' as a standby ship. $StandbyShips: ' + $StandbyShips.count + ' $StandbyShipTable: ' + $StandbyShipTable.keys.count" context="false" chance="$DebugChance"/>
<assert value="not $StandbyShips.indexof.{this.$Ship}" text="'Object ' + this.$Ship + ' ' + this.$Ship.knownname + ' is already in group $StandbyShips [Owen]\n' + $DebugText" break="1"/>
<add_to_group groupname="$StandbyShips" object="this.$Ship"/>
<assert value="not $StandbyShipTable.{this.$Ship}?" text="'Object ' + this.$Ship + ' ' + this.$Ship.knownname + ' is already in $StandbyShipTable [Owen]\n' + $DebugText" break="1"/>
<set_value name="$StandbyShipTable.{this.$Ship}" exact="player.age"/>
<assert value="$StandbyShips.count == $StandbyShipTable.keys.count" text="'Counts of $StandbyShips and $StandbyShipTable do not match [Owen]\n' + $DebugText" break="1"/>
<set_value name="event.param.{3}.{1}" exact="true"/>
</do_if>
<do_else>
<assert value="typeof this.$Ship == datatype.component" text="'Invalid event parameters' + this.$Ship + ' [Owen]\n' + $DebugText" break="1"/>
</do_else>
</actions>
</cue>
<!--
event.param.{1} = signal ID 'remove_standby_ship' (optional)
event.param.{2} = Ship
event.param.{3} = Uncommandeer?-->
<cue name="Remove_Standby_Ship" instantiate="true">
<conditions>
<event_cue_signalled/>
</conditions>
<actions>
<set_value name="this.$Ship" exact="event.param.{2}"/>
<do_if value="typeof this.$Ship == datatype.component">
<debug_text text="$DebugText + 'Removing ship ' + this.$Ship.knownname + ' ' + this.$Ship + ' as a standby ship. $StandbyShips: ' + $StandbyShips.count + ' $StandbyShipTable: ' + $StandbyShipTable.keys.count" context="false" chance="$DebugChance"/>
<do_if value="$StandbyShips.indexof.{this.$Ship}">
<remove_from_group group="$StandbyShips" object="this.$Ship"/>
</do_if>
<do_else>
<assert value="$StandbyShips.indexof.{this.$Ship}" text="'Object ' + this.$Ship + ' ' + this.$Ship.knownname + ' is not in group $StandbyShips [Owen]\n' + $DebugText" break="1"/>
</do_else>
<do_if value="$StandbyShipTable.{this.$Ship}?">
<remove_value name="$StandbyShipTable.{this.$Ship}"/>
</do_if>
<do_else>
<assert value="$StandbyShipTable.{this.$Ship}?" text="'Object ' + this.$Ship + ' ' + this.$Ship.knownname + ' is not in $StandbyShipTable [Owen]\n' + $DebugText" break="1"/>
</do_else>
<assert value="$StandbyShips.count == $StandbyShipTable.keys.count" text="'Counts of $StandbyShips and $StandbyShipTable do not match [Owen]\n' + $DebugText" break="1"/>
<do_if value="event.param.{3}">
<release_commandeered_object object="this.$Ship"/>
</do_if>
</do_if>
<do_else>
<assert value="typeof this.$Ship == datatype.component" text="'Invalid event parameters' + this.$Ship + ' [Owen]\n' + $DebugText" break="1"/>
</do_else>
</actions>
</cue>
<cue name="Standby_Ship_Lost" instantiate="true">
<conditions>
<check_any>
<event_object_destroyed group="$StandbyShips"/>
<event_object_changed_owner group="$StandbyShips"/>
<event_object_changed_true_owner group="$StandbyShips"/>
</check_any>
</conditions>
<actions>
<debug_text text="$DebugText + 'Standby ship ' + event.param.knownname + ' ' + event.param + ' lost due to ' + event.name + ' $StandbyShips: ' + $StandbyShips.count + ' $StandbyShipTable: ' + $StandbyShipTable.keys.count" context="false" chance="$DebugChance"/>
<!-- TODO @Ownen: please review this // is it correct that the ship is removed from the list upon each triggered owner change event (i.e. even if it "changed" to the faction for which standby ships were added?) -->
<do_if value="event.name == 'event_object_changed_true_owner' or event.name == 'event_object_changed_owner'">
<remove_from_group group="$StandbyShips" object="event.object"/>
</do_if>
<do_if value="$StandbyShipTable.{event.object}?">
<remove_value name="$StandbyShipTable.{event.object}"/>
</do_if>
<do_else>
<assert value="$StandbyShipTable.{event.object}?" text="'Object ' + event.object + ' ' + event.object.knownname + ' is not in $StandbyShipTable [Owen]\n' + $DebugText" break="1"/>
</do_else>
</actions>
</cue>
<!--An invasion has started against this sector. Keep track of the invasion faction goal cue. Invader may be non-enemy.-->
<cue name="Sector_Faction_Logic_Goal_Signal" instantiate="true">
<conditions>
<event_object_signalled object="$Target"/>
<check_value value="event.param == 'faction_logic_goal_event'"/>
</conditions>
<actions>
<do_if value="typeof event.param2 == datatype.cue">
<do_if value="event.param2.static == md.FactionGoal_Invade_Space.Start">
<debug_text text="$DebugText + 'Sector is being invaded by ' + event.param2.$Faction + ' which are in phase ' + event.param2.$Phase" context="false" chance="$DebugChance"/>
<do_if value="not $Invasions.indexof.{event.param2}">
<append_to_list name="$Invasions" exact="event.param2"/>
</do_if>
<do_if value="true" chance="5">
<!--Small chance to react immediatly-->
<!--TODO @Owen base chance on recon of invasion source sector?-->
<set_value name="$StateEvaluationDelay" exact="1s"/>
<reset_cue cue="EvaluateState"/>
</do_if>
</do_if>
</do_if>
</actions>
</cue>
<!-- returns $ForceStrength -->
<library name="EvaluateForceStrength">
<actions>
<!--TODO @Owen base strength on other factors.-->
<set_value name="$ForceStrength" exact="0"/>
<do_all exact="$CurrentPhaseSubGoals.count" counter="$i">
<set_value name="$CurrentSubGoal" exact="$CurrentPhaseSubGoals.{$i}"/>
<!--Current Recon Subgoal-->
<do_if value="$CurrentSubGoal.$Cue.$Descriptor == '$SUBGOAL_Recon'">
<do_if value="$CurrentSubGoal.$EvaluateShipsCue?">
<signal_cue_instantly cue="$CurrentSubGoal.$EvaluateShipStrengthCue"/>
<set_value name="$ForceStrength" operation="add" exact="$CurrentSubGoal.$ShipStrength"/>
</do_if>
</do_if>
<!--Current Defend Area Subgoal-->
<do_elseif value="$CurrentSubGoal.$Cue.$Descriptor == '$SUBGOAL_DefendArea'">
<do_if value="$CurrentSubGoal.$EvaluateShipsCue?">
<signal_cue_instantly cue="$CurrentSubGoal.$EvaluateShipStrengthCue"/>
<set_value name="$ForceStrength" operation="add" exact="$CurrentSubGoal.$ShipStrength"/>
</do_if>
</do_elseif>
<!--Current Build Defence Station Subgoal - Do nothing-->
</do_all>
</actions>
</library>
<cue name="EvaluateState">
<delay exact="$StateEvaluationDelay"/>
<actions>
<set_value name="$StateEvaluationDelay" exact="0s"/>
<set_value name="$ForceStrength" exact="0"/>
<do_if value="@$NewIntel">
<remove_value name="$IntelUsed"/>
<remove_value name="$NewIntel"/>
</do_if>
<!--Release any commandeered standby ships which have not been requested by a subgoal-->
<do_all exact="$StandbyShips.count" counter="$i" reverse="true">
<do_if value="player.age gt $StandbyShipTable.{$StandbyShips.{$i}} + 2min">
<signal_cue_instantly cue="Remove_Standby_Ship" param="[null, $StandbyShips.{$i}, true]"/>
</do_if>
</do_all>
<do_all exact="$Invasions.count" counter="$i" reverse="true">
<do_if value="not $Invasions.{$i}.exists">
<remove_value name="$Invasions.{$i}"/>
</do_if>
</do_all>
<do_if value="$Faction.isactive">
<set_value name="this.$EnemyContestingFactions" exact="[]"/>
<set_value name="this.$ContestingFactions" exact="$Target.contestingfactions"/>
<set_value name="this.$HasClaim" exact="if this.$ContestingFactions.count then this.$ContestingFactions.indexof.{$Faction} else $Target.owner == $Faction"/>
<do_all exact="this.$ContestingFactions.count" counter="$i">
<do_if value="$Faction.hasrelation.enemy.{this.$ContestingFactions.{$i}}">
<append_to_list name="this.$EnemyContestingFactions" exact="this.$ContestingFactions.{$i}"/>
</do_if>
</do_all>
<do_if value="this.$HasClaim">
<set_value name="$UnclaimTime" exact="-1"/>
</do_if>
<do_elseif value="$UnclaimTime lt 0">
<set_value name="$UnclaimTime" exact="player.age"/>
<debug_text text="$DebugText + ' Sector no longer is claimed by the faction. Aborting hold space goal.'" chance="$DebugChance"/>
</do_elseif>
</do_if>
<do_if value="not $Faction.isactive">
<debug_text text="$DebugText + ' Faction is no longer active. Aborting hold space goal.'" chance="$DebugChance"/>
<signal_cue_instantly cue="Cleanup"/>
</do_if>
<do_elseif value="$UnclaimTime gt 0 and player.age gt $UnclaimTime + 10min">
<debug_text text="$DebugText + ' Sector has been unclaimed for too long. Aborting hold space goal.'" chance="$DebugChance"/>
<signal_cue_instantly cue="Cleanup"/>
</do_elseif>
<do_else>
<!--Evaluate all current goals, checking their states and seeing if any should begin handing off and ending.-->
<set_value name="$CurrentGoalStates" exact="table[]"/>
<set_value name="$CurrentSubGoalDescriptor" exact="null"/>
<set_value name="$PrepareStagingAreaStrength" exact="0"/>
<set_value name="$ActiveDefenceStationGoals" exact="0"/>
<do_all exact="$CurrentPhaseSubGoals.count" counter="$i" reverse="true">
<set_value name="$CurrentSubGoal" exact="$CurrentPhaseSubGoals.{$i}"/>
<do_if value="$CurrentSubGoal.$EvaluateCue?">
<signal_cue_instantly cue="$CurrentSubGoal.$EvaluateCue"/>
<do_if value="$CurrentSubGoal.$EvaluationResult?">
<set_value name="$CurrentSubGoalDescriptor" exact="$CurrentSubGoal.$Cue.$Descriptor"/>
<set_value name="$Handoff" exact="false"/>
<do_if value="not $CurrentGoalStates.{$CurrentSubGoalDescriptor}?">
<set_value name="$CurrentGoalStates.{$CurrentSubGoalDescriptor}" exact="table[]"/>
</do_if>
<do_if value="$CurrentSubGoalDescriptor == '$SUBGOAL_Recon'">
<do_if value="$CurrentSubGoal.$EvaluationResult == 'failed'">
<set_value name="$Handoff" exact="true"/>
</do_if>
<do_else>
<set_value name="$CurrentGoalStates.{$CurrentSubGoalDescriptor}.$DesiredShipStrength" operation="add" exact="$CurrentSubGoal.$DesiredShipStrength"/>
<do_if value="$CurrentSubGoal.$EvaluationResult == 'performing'">
<set_value name="$CurrentGoalStates.{$CurrentSubGoalDescriptor}.$ReadyShipStrength" operation="add" exact="$CurrentSubGoal.$ShipStrength"/>
</do_if>
<do_else>
<set_value name="$CurrentGoalStates.{$CurrentSubGoalDescriptor}.$UnreadyShipStrength" operation="add" exact="$CurrentSubGoal.$ShipStrength"/>
</do_else>
</do_else>
</do_if>
<do_elseif value="$CurrentSubGoalDescriptor == '$SUBGOAL_DefendArea'">
<do_if value="$CurrentSubGoal.$EvaluationResult == 'failed' or $CurrentSubGoal.$EvaluationResult == 'ending'">
<set_value name="$Handoff" exact="true"/>
</do_if>
<do_else>
<set_value name="$CurrentGoalStates.{$CurrentSubGoalDescriptor}.$DesiredShipStrength" operation="add" exact="$CurrentSubGoal.$DesiredShipStrength"/>
<do_if value="$CurrentSubGoal.$EvaluationResult == 'performing'">
<set_value name="$CurrentGoalStates.{$CurrentSubGoalDescriptor}.$ReadyShipStrength" operation="add" exact="$CurrentSubGoal.$ShipStrength"/>
</do_if>
<do_else>
<set_value name="$CurrentGoalStates.{$CurrentSubGoalDescriptor}.$UnreadyShipStrength" operation="add" exact="$CurrentSubGoal.$ShipStrength"/>
</do_else>
<!--Count how many subgoals are in reaction to an invasion or a contesting faction-->
<do_if value="$CurrentSubGoal.$DefendArea.$Invasion? and $Invasions.indexof.{$CurrentSubGoal.$DefendArea.$Invasion}">
<do_if value="not $CurrentGoalStates.{$CurrentSubGoalDescriptor}.$Invasions?">
<set_value name="$CurrentGoalStates.{$CurrentSubGoalDescriptor}.$Invasions" exact="table[]"/>
</do_if>
<set_value name="$CurrentGoalStates.{$CurrentSubGoalDescriptor}.$Invasions.{$CurrentSubGoal.$DefendArea.$Invasion}" operation="add"/>
</do_if>
<do_elseif value="$CurrentSubGoal.$DefendArea.$ContestingFaction? and this.$ContestingFactions.indexof.{$CurrentSubGoal.$DefendArea.$ContestingFaction}">
<do_if value="not $CurrentGoalStates.{$CurrentSubGoalDescriptor}.$ContestingFactions?">
<set_value name="$CurrentGoalStates.{$CurrentSubGoalDescriptor}.$ContestingFactions" exact="table[]"/>
</do_if>
<set_value name="$CurrentGoalStates.{$CurrentSubGoalDescriptor}.$ContestingFactions.{$CurrentSubGoal.$DefendArea.$ContestingFaction}" operation="add"/>
</do_elseif>
<do_if value="@$CurrentSubGoal.$DefendArea.$TargetObject.isrealclass.station">
<set_value name="$CurrentGoalStates.{$CurrentSubGoalDescriptor}.$StationTargetCount" operation="add"/>
</do_if>
</do_else>
</do_elseif>
<do_elseif value="$CurrentSubGoalDescriptor == '$SUBGOAL_BuildDefenceStation'">
<!--TODO @Owen-->
<do_if value="$CurrentSubGoal.$EvaluationResult == 'failed'">
<set_value name="$Handoff" exact="true"/>
</do_if>
<do_elseif value="$CurrentSubGoal.$EvaluationResult == 'achieved'">
<set_value name="$Handoff" exact="true"/>
</do_elseif>
<do_else>
<set_value name="$ActiveDefenceStationGoals" operation="add"/>
</do_else>
</do_elseif>
<do_else>
<assert value="false" text="'Faction Subgoal ' + [$CurrentSubGoal.$Cue] +' was not recognised for this Faction Goal [Owen]\n' + $DebugText"/>
</do_else>
<do_if value="$Handoff">
<signal_cue_instantly cue="$CurrentPhaseSubGoals.{$i}.$UpdateSubgoalCue" param="['handoff']"/>
</do_if>
<do_else>
<set_value name="$CurrentGoalStates.{$CurrentSubGoalDescriptor}.$Counter" operation="add"/>
<set_value name="$CurrentGoalStates.{$CurrentSubGoalDescriptor}.{'$' + $CurrentSubGoal.$EvaluationResult}" operation="add"/>
</do_else>
</do_if>
</do_if>
</do_all>
<remove_value name="$CurrentSubGoalDescriptor"/>
<!--Set base wanted strength based on the current aggression-->
<set_value name="this.$MaxDefenceSubGoals" exact="5"/>
<set_value name="this.$MaxAttackEnemyStationSubGoals" exact="1" comment="Also using Defend Area subgoal"/>
<set_value name="$Mood" exact="$Faction.mood.aggression"/>
<do_if value="$Mood == moodlevel.verylow">
<set_value name="$MinimumStrengthFactor" exact="1.2f"/>
<set_value name="$MaximumStrengthFactor" exact="1.3f"/>
</do_if>
<do_elseif value="$Mood == moodlevel.low">
<set_value name="$MinimumStrengthFactor" exact="1.1f"/>
<set_value name="$MaximumStrengthFactor" exact="1.3f"/>
</do_elseif>
<do_elseif value="$Mood == moodlevel.normal">
<set_value name="$MinimumStrengthFactor" exact="1.0f"/>
<set_value name="$MaximumStrengthFactor" exact="1.4f"/>
</do_elseif>
<do_elseif value="$Mood == moodlevel.high">
<set_value name="$MinimumStrengthFactor" exact="0.9f"/>
<set_value name="$MaximumStrengthFactor" exact="1.8f"/>
<set_value name="this.$MaxDefenceSubGoals" exact="7"/>
<set_value name="this.$MaxAttackEnemyStationSubGoals" exact="2" comment="Also using Defend Area subgoal"/>
</do_elseif>
<do_elseif value="$Mood == moodlevel.veryhigh">
<set_value name="$MinimumStrengthFactor" exact="0.8f"/>
<set_value name="$MaximumStrengthFactor" exact="2.0f"/>
<set_value name="this.$MaxDefenceSubGoals" exact="9"/>
<set_value name="this.$MaxAttackEnemyStationSubGoals" exact="2" comment="Also using Defend Area subgoal"/>
</do_elseif>
<remove_value name="$Mood"/>
<!--TODO @Owen check what $Recon_NumObjects actually is (a threat-level) -->
<!--<set_value name="$MinimumStrength" exact="[$MinimumStrength, $MinimumStrengthFactor * $Recon_NumObjects].max"/>
<set_value name="$MaximumStrength" exact="[$MinimumStrength, $MaximumStrengthFactor * $Recon_NumObjects].max"/>-->
<set_value name="$IntelUsed"/>
<!--Check if new subgoals should be requested for the current situation-->
<set_value name="this.$PotentialDefendAreaDefinitions" exact="[]"/>
<!--Invasions
Invasions can trigger the following subgoals:
- DefendArea, around the entry point if possible (if enemy)
- DefendArea, around important stations (if enemy)
- Recon, into enemy space-->
<do_all exact="$Invasions.count" counter="$i">
<!--Defend Area sub goals against invasions. Limit number per invasion.-->
<!--First, check if there are already enough active DefendArea goals for this invasion-->
<set_value name="this.$WantedDefendAreaSubgoals" exact="3 - @$CurrentGoalStates.$SUBGOAL_DefendArea.$Invasions.{$Invasions.{$i}}"/>
<do_if value="this.$WantedDefendAreaSubgoals gt 0">
<debug_text text="$DebugText + ' Wants to react to invasion ' + [$Invasions.{$i}] + ' with ' + this.$WantedDefendAreaSubgoals + ' defend area goals'" context="false" chance="$DebugChance"/>
<set_value name="this.$HasExistingInvasionDefenceSubgoal" exact="@$CurrentGoalStates.$SUBGOAL_DefendArea.$Invasions.{$Invasions.{$i}} != 0"/>
<!--First, check if there are entry points to be guarded. These take priority.-->
<do_all exact="$Invasions.{$i}.$AlliedEntryPoints.count" counter="$k">
<assert value="$Invasions.{$i}.$AlliedEntryPoints.{$k}.exit.sector == $Target" text="'Invasion exit point for enemy faction leads to sector ' + $Invasions.{$i}.$AlliedEntryPoints.{$k}.exit.sector.knownname + ' instead of ' + $Target.knownname + ' [Owen]'"/>
<do_if value="$Invasions.{$i}.$AlliedEntryPoints.{$k}.exit.sector == $Target">
<create_position name="this.$DefendPos" object="$Invasions.{$i}.$AlliedEntryPoints.{$k}.exit" space="$Target"/>
<set_value name="this.$AlreadyDefendingEntryPoint" exact="false"/>
<do_all exact="$CurrentPhaseSubGoals.count" counter="$j">
<set_value name="this.$CurrentSubGoal" exact="$CurrentPhaseSubGoals.{$j}"/>
<do_if value="this.$CurrentSubGoal.$Cue.$Descriptor == '$SUBGOAL_DefendArea'">
<signal_cue_instantly cue="this.$CurrentSubGoal.$IsDefendingPositionCue" param="[this, $Target, this.$DefendPos, false]"/>
<!--Existing defend area subgoal is close to this position. Leave it to do its job.-->
<set_value name="this.$AlreadyDefendingEntryPoint" exact="true"/>
<debug_text text="$DebugText + ' Exiting defendArea subgoal has is already guarding entry point'" context="false" chance="$DebugChance2"/>
</do_if>
</do_all>
<do_if value="not this.$AlreadyDefendingEntryPoint">
<debug_text text="$DebugText + ' Will attempt to defend entrypoint: ' + $Invasions.{$i}.$AlliedEntryPoints.{$k}.exit + ' ' + $Invasions.{$i}.$AlliedEntryPoints.{$k}.exit.knownname" chance="$DebugChance2"/>
<!--<debug_text text="'pos ' + this.$DefendPos"/>
<debug_text text="'$CurrentPhaseSubGoals.count ' + $CurrentPhaseSubGoals.count"/>-->
<!--Check if it's safe to go to the defend area position immediatly, or if the ships should gather at a staging area-->
<find_ship_by_true_owner name="this.$OwnShips" faction="$Faction" space="$Target" multiple="true">
<match_distance object="$Invasions.{$i}.$AlliedEntryPoints.{$k}.exit" max="20km"/>
</find_ship_by_true_owner>
<find_ship_by_true_owner name="this.$EnemyShips" faction="$Invasions.{$i}.$Faction" space="$Target" multiple="true">
<match_distance object="$Invasions.{$i}.$AlliedEntryPoints.{$k}.exit" max="20km"/>
</find_ship_by_true_owner>
<signal_cue_instantly cue="md.FactionLogic.EvaluateForceStrength" param="[this, this.$OwnShips, md.$DefaultShipStrengthTable, md.$DefaultSubordinateStrengthTable]"/>
<set_value name="this.$OwnShipsStrength" exact="this.$EFS_Result"/>
<signal_cue_instantly cue="md.FactionLogic.EvaluateForceStrength" param="[this, this.$EnemyShips, md.$DefaultShipStrengthTable, md.$DefaultSubordinateStrengthTable]"/>
<set_value name="this.$EnemyShipsStrength" exact="this.$EFS_Result"/>
<remove_value name="this.$EFS_Result"/>
<set_value name="this.$StagingAreaDefinition" exact="null"/>
<do_if value="this.$OwnShipsStrength lt this.$EnemyShipsStrength">
<!--More enemies at the entry point than own ships. Gather ships at safe staging area-->
<set_value name="this.$StagingAreaDefinition" exact="table[]"/>
<!--Try to find any allied station within range-->
<find_station name="this.$AlliedStation" space="$Target">
<match_relation_to faction="$Faction" relation="neutral" comparison="ge"/>
<match_distance object="$Invasions.{$i}.$AlliedEntryPoints.{$k}.exit" max="50km"/>
</find_station>
<do_if value="this.$AlliedStation">
<create_position name="this.$StagingAreaPos" object="this.$AlliedStation" space="$Target"/>
<set_value name="this.$StagingAreaDefinition.$Sector" exact="$Target"/>
<set_value name="this.$StagingAreaDefinition.$Position" exact="this.$StagingAreaPos"/>
<set_value name="this.$StagingAreaDefinition.$Range" exact="20km"/>
</do_if>
<do_else>
<!--TODO @Owen - positioning. Currently a position pushed from the entry point-->
<create_position name="this.$StagingAreaPos" object="$Invasions.{$i}.$AlliedEntryPoints.{$k}.exit" z="50km" max="5km" space="$Invasions.{$i}.$AlliedEntryPoints.{$k}.exit.sector"/>
<set_value name="this.$StagingAreaDefinition.$Sector" exact="$Target"/>
<set_value name="this.$StagingAreaDefinition.$Position" exact="this.$StagingAreaPos"/>
<set_value name="this.$StagingAreaDefinition.$Range" exact="25km"/>
</do_else>
</do_if>
<!--Entry point is in need of defence. Add defintion to the list to process after this loop-->
<set_value name="this.$DefenceDefinition" exact="table[]"/>
<!--If this is the first defence subgoal, request a larger force-->
<do_if value="this.$HasExistingInvasionDefenceSubgoal">
<set_value name="this.$WantedDefenceStrength" exact="md.$DefaultShipStrengthTable.{class.ship_m} * 4"/>
<set_value name="this.$DefenceDefinition.$Strength" min="this.$WantedDefenceStrength" max="this.$WantedDefenceStrength + md.$DefaultShipStrengthTable.{class.ship_l}"/>
</do_if>
<do_else>
<set_value name="this.$WantedDefenceStrength" exact="md.$DefaultShipStrengthTable.{class.ship_xl}"/>
<set_value name="this.$DefenceDefinition.$Strength" min="this.$WantedDefenceStrength" max="this.$WantedDefenceStrength + (md.$DefaultShipStrengthTable.{class.ship_m} * 2)"/>
<set_value name="this.$HasExistingInvasionDefenceSubgoal" exact="true"/>
</do_else>
<set_value name="this.$DefenceDefinition.$RequestStrengthAllowance" min="this.$DefenceDefinition.$Strength / 2" max="this.$DefenceDefinition.$Strength" profile="decreasing" comment="Chance of all ships to be requested to be built"/>
<set_value name="this.$DefenceDefinition.$StagingArea" exact="this.$StagingAreaDefinition"/>
<set_value name="this.$AreaDefintion" exact="table[]"/>
<set_value name="this.$AreaDefintion.$Sector" exact="$Target"/>
<set_value name="this.$AreaDefintion.$Position" exact="this.$DefendPos"/>
<set_value name="this.$AreaDefintion.$Range" exact="25km"/>
<set_value name="this.$AreaDefintion.$Invasion" exact="$Invasions.{$i}"/>
<set_value name="this.$DefenceDefinition.$DefendArea" exact="this.$AreaDefintion"/>
<append_to_list name="this.$PotentialDefendAreaDefinitions" exact="this.$DefenceDefinition"/>
<set_value name="this.$WantedDefendAreaSubgoals" operation="subtract"/>
</do_if>
<remove_value name="this.$AlreadyDefendingEntryPoint"/>
</do_if>
<do_if value="this.$WantedDefendAreaSubgoals le 0">
<break/>
</do_if>
</do_all>
<do_all exact="this.$WantedDefendAreaSubgoals">
<!--Find non-entry point places to defend-->
<!--TODO @Owen better selection of areas-->
<find_station name="this.$AlliedStation" space="$Target">
<match_relation_to faction="$Faction" relation="neutral" comparison="ge"/>
</find_station>
<do_if value="this.$AlliedStation">
<set_value name="this.$DefenceDefinition" exact="table[]"/>
<!--If this is the first defence subgoal, request a larger force-->
<do_if value="this.$HasExistingInvasionDefenceSubgoal">
<set_value name="this.$WantedDefenceStrength" exact="md.$DefaultShipStrengthTable.{class.ship_m} * 4"/>
<set_value name="this.$DefenceDefinition.$Strength" min="this.$WantedDefenceStrength" max="this.$WantedDefenceStrength + md.$DefaultShipStrengthTable.{class.ship_l}"/>
</do_if>
<do_else>
<set_value name="this.$WantedDefenceStrength" exact="md.$DefaultShipStrengthTable.{class.ship_xl}"/>
<set_value name="this.$DefenceDefinition.$Strength" min="this.$WantedDefenceStrength" max="this.$WantedDefenceStrength + (md.$DefaultShipStrengthTable.{class.ship_m} * 2)"/>
<set_value name="this.$HasExistingInvasionDefenceSubgoal" exact="true"/>
</do_else>
<set_value name="this.$DefenceDefinition.$RequestStrengthAllowance" min="this.$DefenceDefinition.$Strength / 2" max="this.$DefenceDefinition.$Strength" profile="decreasing" comment="Chance of all ships to be requested to be built"/>
<set_value name="this.$DefenceDefinition.$StagingArea" exact="null"/>
<set_value name="this.$AreaDefintion" exact="table[]"/>
<set_value name="this.$AreaDefintion.$Sector" exact="$Target"/>
<create_position name="this.$AreaDefintion.$Position" object="this.$AlliedStation" max="3km" space="$Target"/>
<set_value name="this.$AreaDefintion.$Range" exact="15km"/>
<set_value name="this.$AreaDefintion.$Invasion" exact="$Invasions.{$i}"/>
<set_value name="this.$DefenceDefinition.$DefendArea" exact="this.$AreaDefintion"/>
<append_to_list name="this.$PotentialDefendAreaDefinitions" exact="this.$DefenceDefinition"/>
<set_value name="this.$WantedDefendAreaSubgoals" operation="subtract"/>
</do_if>
<do_else>
<!--TODO @Owen fallback to a position instead of a station-->
<break/>
</do_else>
</do_all>
</do_if>
</do_all>