Files
SoaFE/DATA/SCRIPTS/AI/SPACEMODE/SPACEARTILLERY.LUA
2026-02-28 14:00:45 -06:00

234 lines
7.5 KiB
Lua

--/////////////////////////////////////////////////////////////////////////////////////////////////
-- (c) Galyana's Ultimate Empire at War Modifications
--
-- ****** *** *** ************ *** ***
-- * * * * * * * *
-- * * * * * * *
-- * * * * * * *
-- * * * * * **** * * *
-- * * * ****** * * * *
-- * **** * * * * * * * *** *
-- * * * * * * * * * *
-- * * * * * * * * * *
-- * * * * * * * ** * * *
-- ****** ****** ************ **** ** *******
--/////////////////////////////////////////////////////////////////////////////////////////////////
-- C O N F I D E N T I A L S O U R C E C O D E -- D O N O T D I S T R I B U T E
--/////////////////////////////////////////////////////////////////////////////////////////////////
--
-- File: GUEaW/Data/Scripts/AI/SpaceMode/SpaceArtillery.LUA
--
-- Original Editor: Giovanni Galyana
--
-- Final Edit By: Giovanni Galyana
--
-- Date: 7 March, 2019
--
-- Revisions: 0
--
--/////////////////////////////////////////////////////////////////////////////////////////////////
require("pgevents")
function Definitions()
DebugMessage("%s -- In Definitions", tostring(Script))
AllowEngagedUnits = false
IgnoreTarget = true
Category = "Space_Artillery"
TaskForce = {
{
"MainForce"
,"Marauder_Missile_Cruiser | Broadside_Class_Cruiser | Ultor_Beam_Cruiser = 1,2"
},
{
"EscortForce"
,"Fighter = 0,2"
--,"EscortForce" -- Don't require the escort to have good contrast vs our target's neighbors
}
}
artillery_flee_range = 1000 -- This must be less than the artillery_attack_range for the plan to work
slack_range = 500
convenient_space_field_range = 800
path_through = "ASTEROID | NEBULA" -- "ASTEROID | NEBULA | ION_FIELD"
-- for memory pool cleanup
DebugMessage("%s -- Done Definitions", tostring(Script))
end
function MainForce_Thread()
tf = MainForce
-- Collect the task force and bring in any reinforcements to the current location
BlockOnCommand(tf.Produce_Force())
QuickReinforce(PlayerObject, AITarget, tf)
-- Set up proximities on each member of the main task force
for i, unit in (tf.Get_Unit_Table()) do
-- discover the range of the unit if we need to
if not artillery_attack_range then
artillery_attack_range = unit.Get_Type().Get_Max_Range()
DebugMessage("%s-- got artillery range %d", tostring(Script), artillery_attack_range)
enemy_player = unit.Get_Owner().Get_Enemy()
end
--Register_Prox(unit, Prox_Enemy_In_Range, artillery_attack_range - slack_range, enemy_player)
Register_Prox(unit, Prox_Enemy_In_Range, artillery_attack_range, enemy_player)
Register_Prox(unit, Prox_Enemy_Too_Close, artillery_flee_range, enemy_player)
end
-- Move to the plan's original attack location.
tf.Set_As_Goal_System_Removable(false)
good_loc = AITarget
SafeApproach(good_loc)
-- Make sure we're obscured, if a field is within a reasonable range
Obscure(tf, 1500, true, path_through)
-- Repeat as long as a good attack position exists.
while good_loc do
EvadeUntilSafe(tf, true)
-- Attack the nearest good target, but stop advancing if any enemies come in range
best_target = FindTarget(tf, "Unit_Needs_To_Be_Destroyed", "Enemy_Unit | Enemy_Structure", 1.0, artillery_attack_range + slack_range)
if TestValid(best_target) then
enemies_in_range = false
BlockOnCommand(tf.Attack_Target(best_target, 10, path_through), -1, Enemies_In_Range)
tf.Move_To(tf)
else
best_target = FindTarget(tf, "Unit_Needs_To_Be_Destroyed", "Enemy_Unit | Enemy_Structure", 1.0)
if TestValid(best_target) then
--MessageBox("%s--moving to target:%s", tostring(Script), tostring(best_target))
enemies_in_range = false
BlockOnCommand(tf.Attack_Target(best_target, 10, path_through), -1, Enemies_In_Range)
tf.Move_To(tf)
end
end
if EvaluatePerception("Good_Space_Artillery_Area", PlayerObject, good_loc) ~= 0 then
-- We're in a good place. Just continue to attack our last target until threatened.
if TestValid(best_target) then
enemies_near = false
BlockOnCommand(tf.Attack_Target(best_target, 10, path_through), -1, Threatened)
end
else
-- Find a new attack position because the current one has become useless
good_loc = FindTarget(tf, "Good_Space_Artillery_Area", "Tactical_Location", 0.7)
if good_loc then
SafeApproach(good_loc)
else
-- Apparently this plan now sucks. Hide the artillery and abort.
hiding_loc = FindTarget(MainForce, "Space_Area_Is_Hidden", "Tactical_Location", 1.0, 5000.0)
BlockOnCommand(tf.Move_To(hiding_loc, 10, path_through))
break
end
end
-- Yield to other systems, in case nothing else in this loop does.
Sleep(2)
end
-- Ensure that if this fails that the escort thread ends as well
ScriptExit()
end
--Reapproach if enemies are already within range, otherwise edge up to them.
function SafeApproach(loc)
if Enemies_In_Range() then
BlockOnCommand(tf.Move_To(good_loc, 10, path_through))
else
BlockOnCommand(tf.Move_To(good_loc, 10, path_through), -1, Enemies_In_Range)
end
end
--function Artillery_Behavior(tf)
--end
-- Keeps the task force running away from enemies.
-- Should land the task force in a good attack location.
-- Updates good_loc var and resets enemies_near to false.
function EvadeUntilSafe(tf, use_nebulae)
-- Evade as long as we have an enemy whose threat we're tracking and a nearby enemy
deadly_enemy = FindDeadlyEnemy(tf)
while deadly_enemy or enemies_near do
-- Run from any attacker.
if TestValid(deadly_enemy) then
BlockOnCommand(tf.Move_To(Project_By_Unit_Range(deadly_enemy, tf), 10, path_through))
end
-- Further measures if there's still an enemy close
if enemies_near then
--Hide.
good_loc = FindTarget(tf, "Good_Space_Artillery_Area", "Tactical_Location", 0.7)
if good_loc then
BlockOnCommand(tf.Move_To(good_loc, 10, path_through))
end
-- Make sure we're obscured, if convenient.
Obscure(tf, convenient_space_field_range, use_nebulae, path_through)
end
enemies_near = false
deadly_enemy = FindDeadlyEnemy(tf)
end
end
function Prox_Enemy_In_Range(self_obj, enemy_obj)
enemies_in_range = true
end
function Enemies_In_Range()
return enemies_in_range
end
function Prox_Enemy_Too_Close(self_obj, enemy_obj)
enemies_near = true
end
function Enemies_Are_Near()
return enemies_near
end
-- Something has come too close or attacked us
function Threatened()
return enemies_near or TestValid(FindDeadlyEnemy(tf))
end
function EscortForce_Thread()
BlockOnCommand(EscortForce.Produce_Force())
QuickReinforce(PlayerObject, AITarget, EscortForce, MainForce)
-- Give an initial order to put the escorts in a state that the Escort function expects
EscortForce.Guard_Target(MainForce)
-- Continuously follow and guard the main force
EscortAlive = true
while EscortAlive do
Escort(EscortForce, MainForce, true)
end
end