234 lines
7.5 KiB
Lua
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
|
|
|