--///////////////////////////////////////////////////////////////////////////////////////////////// -- (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