Initial commit

This commit is contained in:
2026-02-28 14:00:45 -06:00
commit 16d3170787
1134 changed files with 589134 additions and 0 deletions

View File

@@ -0,0 +1,606 @@
-- $Id: //depot/Projects/StarWars_Expansion/Run/Data/Scripts/Library/PGTaskForce.lua#6 $
--/////////////////////////////////////////////////////////////////////////////////////////////////
--
-- (C) Petroglyph Games, Inc.
--
--
-- ***** ** * *
-- * ** * * *
-- * * * * *
-- * * * * * * * *
-- * * *** ****** * ** **** *** * * * ***** * ***
-- * ** * * * ** * ** ** * * * * ** ** ** *
-- *** ***** * * * * * * * * ** * * * *
-- * * * * * * * * * * * * * * *
-- * * * * * * * * * * ** * * * *
-- * ** * * ** * ** * * ** * * * *
-- ** **** ** * **** ***** * ** *** * *
-- * * *
-- * * *
-- * * *
-- * * * *
-- **** * *
--
--/////////////////////////////////////////////////////////////////////////////////////////////////
-- 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: //depot/Projects/StarWars_Expansion/Run/Data/Scripts/Library/PGTaskForce.lua $
--
-- Original Author: Brian Hayes
--
-- $Author: James_Yarrow $
--
-- $Change: 46700 $
--
-- $DateTime: 2006/06/21 14:40:55 $
--
-- $Revision: #6 $
--
--/////////////////////////////////////////////////////////////////////////////////////////////////
require("PGAICommands")
function FindStageArea(_target, taskforce)
return _FindStageArea(PlayerObject, _target, taskforce);
end
function AssembleForce(taskforce, stage_at_strongest_space)
if stage_at_strongest_space then
stage = FindTarget.Reachable_Target(PlayerObject, "FriendlySpaceForceStrength", "Friendly | Enemy | Neutral", "Enemy_undefended", 1.0, AITarget)
DebugMessage("%s -- Using the enemy_undefended reachable system %s with the strongest space force for staging.", tostring(Script), tostring(stage))
else
stage = taskforce.Get_Stage()
DebugMessage("%s -- Using default system %s (nearest faction system) for staging.", tostring(Script), tostring(stage))
end
if not stage then
DebugMessage("%s -- Unable to find a staging area. Abandonning plan.", tostring(Script))
ScriptExit()
end
DebugMessage("%s -- Selected Stage: %s\n", tostring(Script), tostring(stage))
BlockOnCommand(taskforce.Produce_Force(stage));
end
function SynchronizedAssemble(taskforce, stage_at_strongest_space)
if stage_at_strongest_space then
stage = FindTarget(taskforce, "FriendlySpaceForceStrength", "Friendly | Enemy | Neutral", 1.0)
DebugMessage("%s -- Using the system %s with the strongest space force for staging.", tostring(Script), tostring(stage))
else
stage = taskforce.Get_Stage()
DebugMessage("%s -- Using default system %s (nearest faction system) for staging.", tostring(Script), tostring(stage))
end
if not stage then
DebugMessage("%s -- Unable to find a staging area. Abandonning plan.", tostring(Script))
ScriptExit()
end
DebugMessage("%s -- Selected Stage: %s\n", tostring(Script), tostring(stage))
BlockOnCommand(taskforce.Produce_Force(stage, true));
end
function WaitMoveForce(taskforce, planet)
DebugMessage("Moving Taskforce %s to object %s.", tostring(taskforce), tostring(planet))
BlockOnCommand(taskforce.Move_To(FindPlanet(planet)))
DebugMessage("Moving Command finished")
end
function LandUnits(taskforce)
DebugMessage("Landing on %s with taskforce %s.", tostring(Target), tostring(taskforce))
BlockOnCommand(taskforce.Land_Units())
DebugMessage("Land Units Command finished")
end
function LaunchUnits(taskforce)
DebugMessage("Launching units into orbit with taskforce %s.", tostring(taskforce))
block = taskforce.Launch_Units()
if not block then
return false
end
BlockOnCommand(block)
BlockOnCommand(taskforce.Form_Units())
DebugMessage("Launch Units Command finished")
return true
end
function Invade(taskforce)
DebugMessage("Invading %s with taskforce %s.", tostring(Target), tostring(taskforce))
InvasionActive = true
invade_status = taskforce.Invade()
if invade_status and BlockOnCommand(invade_status) then
DebugMessage("Invasion successful. Waiting for planet conversion.");
taskforce.Set_As_Goal_System_Removable(false)
LandUnits(taskforce)
InvasionActive = false
return true
else
DebugMessage("Invasion failed!")
InvasionActive = false
return false
end
end
function FundBases(player, target)
--Prefer starbases since they block enemy movement
DebugMessage("%s -- giving desire bonus to build starbase", tostring(Script))
BlockOnCommand(GiveDesireBonus(player, "Build_Initial_Starbase_Only", target, 15, 5))
DebugMessage("%s -- waiting for starbase", tostring(Script))
BlockOnCommand(WaitForStarbase(Target, 1))
DebugMessage("%s -- giving desire bonus to build groundbase", tostring(Script))
BlockOnCommand(GiveDesireBonus(player, "Build_Initial_Groundbase_Only", target, 15, 5))
end
-- Generally follow the task force we're escorting and attack it's attackers.
-- Conservative style will avoid confrontation with non fighters/bombers
function Escort(taskforce, target, conservative_style)
if not TestValid(target) then
Sleep(1)
return
end
lib_enemy = FindDeadlyEnemy(target)
if lib_enemy then
if Get_Game_Mode() == "Space" then
if not conservative_style or (lib_enemy.Is_Category("Fighter") or lib_enemy.Is_Category("Bomber")) then
-- Lure them away from our escorted target if we can.
Try_Ability(taskforce,"LURE")
-- Weave a bit.
Weave(taskforce, lib_enemy)
-- engage the attackers for a duration
if not TestValid(lib_enemy) then return end
DebugMessage("%s -- In Escort: Attacking lib_enemy: %s for Target: %s", tostring(Script), tostring(lib_enemy), tostring(target))
BlockOnCommand(taskforce.Attack_Target(lib_enemy), 15)
else
-- run away a bit, then hold ground before resuming escort
DebugMessage("%s -- In Escort: attempting to divert lib_enemy: %s for Target: %s", tostring(Script), tostring(lib_enemy), tostring(target))
BlockOnCommand(taskforce.Move_To(Project_By_Unit_Range(lib_enemy, taskforce)), 15)
if not TestValid(target) then return end
BlockOnCommand(taskforce.Guard_Target(target, 5))
end
else
BlockOnCommand(taskforce.Attack_Target(lib_enemy), 20)
end
return
end
if not TestValid(target) then
Sleep(1)
return
end
-- Make sure we're assisting the target provided we're not already assisting
-- because reissuing a guard will cause the assisting escort to break off attack.
-- Note: may receive a non tf "target" param, for example EscortPlan passes a unit
if not Tf_Has_Attack_Target(taskforce) then
-- Escort forces should have attack priorities that allow them to attack structures by this point
DebugMessage("%s on %s -- In Escort: Resuming escort of %s", tostring(Script), tostring(AITarget), tostring(target))
taskforce.Guard_Target(target)
end
Sleep(1)
end
-- Does any member of the given task force have an attack target?
function Tf_Has_Attack_Target(tf)
if TestValid(tf) then
for i, unit in tf.Get_Unit_Table() do
if unit.Has_Attack_Target() == true then
return true
end
end
else
DebugMessage("%s -- task force %s isn't valid", tostring(Script), tostring(tf))
end
return false
end
function Weave(tf, enemy)
if not TestValid(enemy) then return end
BlockOnCommand(tf.Attack_Target(enemy), 10)
if not TestValid(enemy) then return end
BlockOnCommand(tf.Move_To(Project_By_Unit_Range(enemy, tf)), 5)
if not TestValid(enemy) then return end
BlockOnCommand(tf.Attack_Target(enemy), 2)
if not TestValid(enemy) then return end
BlockOnCommand(tf.Move_To(Project_By_Unit_Range(enemy, tf)), 4)
end
function WaitForAllReinforcements(taskforce, target)
block = taskforce.Reinforce(target)
if block then
while block and not BlockOnCommand(block) do
block = taskforce.Reinforce(target)
end
end
end
-- Keep a task force from being idle
-- expects lib_tf_to_anti_idle and lib_enemy_to_avoid to be defined before use
function Anti_Idle_Taskforce()
DebugMessage("%s-- AntiIdle attempt", tostring(Script))
if lib_tf_to_anti_idle and TestValid(lib_enemy_to_avoid) then
DebugMessage("%s-- AntiIdle lib vars are defined", tostring(Script))
if lib_new_anti_idle == true then
DebugMessage("%s-- AntiIdling %s", tostring(Script), tostring(lib_tf_to_anti_idle))
lib_anti_idle_start_time = GetCurrentTime()
lib_anti_idle_block = lib_tf_to_anti_idle.Move_To(Project_By_Unit_Range(lib_enemy_to_avoid, lib_tf_to_anti_idle))
lib_new_anti_idle = false
elseif lib_anti_idle_block then
PumpEvents()
-- Reissue a new command if the old one has expired or some time has passed
-- This ensures that newly landed reinforcements on the task force will also anti-idle
if lib_anti_idle_block.IsFinished() == true
or 2 + lib_anti_idle_start_time < GetCurrentTime() then
lib_new_anti_idle = true
end
end
else
DebugMessage("%s-- needed global vars aren't defined for anti idle", tostring(Script))
end
end
-- Try to get units on the map in the most reasonable manner.
-- Passing an escort_force is optional
function QuickReinforce(player, target, tf_to_reinforce, second_try_tf)
if not player then
DebugMessage("%s-- received nil player", tostring(Script))
return
end
-- Global plans can pass a nil target and rely on failsafes below to find a target
-- if not target then
-- DebugMessage("%s-- received nil target", tostring(Script))
-- return
-- end
if not tf_to_reinforce then
DebugMessage("%s-- received nil tf_to_reinforce", tostring(Script))
return
end
-- Space mode will attempt various reinforce attempts with timeouts,
-- then simply fail after the last option is exhausted.
if Get_Game_Mode() == "Space" then
lib_reinforce_timeout = 3
-- If some units have landed, try land the remainder near the rest of the main tf
if tf_to_reinforce.Get_Force_Count() ~= 0 then
-- Define some global vars for the anti idle
lib_tf_to_anti_idle = tf_to_reinforce
lib_enemy_to_avoid = Find_Nearest(tf_to_reinforce, PlayerObject, false)
lib_new_anti_idle = true
-- Reinforce new units and anti-idle existing units waiting for the reinforce
if BlockOnCommand(tf_to_reinforce.Reinforce(tf_to_reinforce), lib_reinforce_timeout, Anti_Idle_Taskforce) then
DebugMessage("%s-- reinforced by task force", tostring(Script))
lib_tf_to_anti_idle = nil
lib_enemy_to_avoid = nil
return
end
end
-- If some of the escort force exists, try to land there
if second_try_tf and second_try_tf.Get_Force_Count() ~= 0 then
-- Define some global vars for the anti idle
lib_tf_to_anti_idle = second_try_tf
lib_enemy_to_avoid = Find_Nearest(second_try_tf, PlayerObject, false)
lib_new_anti_idle = true
-- Reinforce new units and anti-idle existing units waiting for the reinforce
if BlockOnCommand(tf_to_reinforce.Reinforce(second_try_tf), lib_reinforce_timeout, Anti_Idle_Taskforce) then
DebugMessage("%s-- reinforced by secondary task force", tostring(Script))
lib_tf_to_anti_idle = nil
lib_enemy_to_avoid = nil
return
end
end
-- Try to land near the default starting point, or some base building, or finally the target itself.
lib_start_loc = FindTarget(tf_to_reinforce, "Is_Friendly_Start", "Tactical_Location", 1.0)
if lib_start_loc then
DebugMessage("%s-- Trying to reinforce by start point", tostring(Script))
BlockOnCommand(tf_to_reinforce.Reinforce(lib_start_loc), lib_reinforce_timeout)
else
lib_base_list = Find_All_Objects_Of_Type(player, "Structure")
if lib_base_list[1] then
DebugMessage("%s-- Trying to reinforce by friendly structure", tostring(Script))
BlockOnCommand(tf_to_reinforce.Reinforce(lib_base_list[1]), lib_reinforce_timeout)
else
lib_base_list = Find_All_Objects_Of_Type(player, "Capital")
if lib_base_list[1] then
DebugMessage("%s-- Trying to reinforce by friendly capital", tostring(Script))
BlockOnCommand(tf_to_reinforce.Reinforce(lib_base_list[1]), lib_reinforce_timeout)
else
DebugMessage("%s-- Trying to reinforce by plan target", tostring(Script))
BlockOnCommand(tf_to_reinforce.Reinforce(target), lib_reinforce_timeout)
end
end
end
-- If we were unable to bring in any reinforcements within a reasonable amount of time
-- then just abandon the plan; it's not worth holding up other units for too long
if tf_to_reinforce.Get_Force_Count() == 0 then
ScriptExit()
end
-- Land mode: this will just return if the units are all available;
-- otherwise we'll reinforce for a long time and then the plan will fail because it may no longer be relevant.
else
if tf_to_reinforce.Are_All_Units_On_Free_Store() then
DebugMessage("%s-- All units available, proceeding with plan", tostring(Script))
-- form up any spread out infantry
tf_to_reinforce.Activate_Ability("SPREAD_OUT", false)
else
DebugMessage("%s-- Reinforcements required--waiting for them.", tostring(Script))
-- Generally, we want things reinforced near the target, if possible
-- But this will try all of the reinforcement points, if needed.
-- This typically takes a long time.
if AITarget then
WaitForAllReinforcements(tf_to_reinforce, target)
else
-- find something to reinforce near, for global plans with a nil target
friendly_loc = FindTarget(tf_to_reinforce, "Space_Area_Is_Hidden", "Tactical_Location", 1.0)
WaitForAllReinforcements(tf_to_reinforce, friendly_loc)
end
--WaitForAllReinforcements(tf_to_reinforce, tf_to_reinforce)
DebugMessage("%s-- Reinforcements arrived. Abandonning plan for reproposal if still relevant", tostring(Script))
-- If the plan is still relevant, it will be proposed again.
ScriptExit()
end
end
end
function SetClassPriorities(tf, priority_set_type)
priority_set_name = "Fighter" .. "_" .. priority_set_type
tf.Set_Targeting_Priorities(priority_set_name, "Fighter")
priority_set_name = "Bomber" .. "_" .. priority_set_type
tf.Set_Targeting_Priorities(priority_set_name, "Bomber")
priority_set_name = "Corvette" .. "_" .. priority_set_type
tf.Set_Targeting_Priorities(priority_set_name, "Corvette")
priority_set_name = "Frigate" .. "_" .. priority_set_type
tf.Set_Targeting_Priorities(priority_set_name, "Frigate")
priority_set_name = "Capital" .. "_" .. priority_set_type
tf.Set_Targeting_Priorities(priority_set_name, "Capital")
end
-- Move task force to asteroids or nebulae if within range and the asteroids aren't near an enemy
-- Returns true if the task force is already obscured or this function obscured it
function Obscure(tf, range, use_nebulae, path_through_fields)
tf_unit_list = tf.Get_Unit_Table()
if not UnitListIsObscured(tf_unit_list) then
asteroids = Find_Nearest_Space_Field(tf, "Asteroid")
if asteroids and tf.Get_Distance(asteroids) < range then
enemy_nearest_loc = Find_Nearest(asteroids, PlayerObject, false)
if not TestValid(enemy_nearest_loc) or enemy_nearest_loc.Get_Distance(asteroids) < 750 then
--MessageBox("%s -- moving to asteroids:%s", tostring (Script), path_through_fields)
BlockOnCommand(tf.Move_To(asteroids, 10, path_through_fields))
return true
end
elseif use_nebulae then
nebula = Find_Nearest_Space_Field(tf, "Nebula")
if nebula and tf.Get_Distance(nebula) < range then
enemy_nearest_loc = Find_Nearest(nebula, PlayerObject, false)
if not TestValid(enemy_nearest_loc) or enemy_nearest_loc.Get_Distance(nebula) < 750 then
--MessageBox("%s -- moving to nebulae:%s", tostring (Script), path_through_fields)
BlockOnCommand(tf.Move_To(nebula, 10, path_through_fields))
return true
end
end
end
return false -- We're not obscured, and there's nothing in range to obscure us.
end
return true
end
-- Fix the unit or hide if appropriate.
-- Return true if the unit was fixed.
function ConsiderHeal(unit)
unit_hull = unit.Get_Hull()
if (unit_hull < 0.8) then
bacta = Find_Nearest(unit, "HealsInfantry", PlayerObject, true)
if TestValid(bacta) then
if (unit_hull < 0.4) or (unit.Get_Distance(bacta) < 700) then
unit.Activate_Ability("STEALTH", true)
unit.Activate_Ability("FORCE_CLOAK", true)
BlockOnCommand(unit.Move_To(bacta))
while unit.Get_Hull() < 0.9 do
DebugMessage("%s-- Waiting to heal", tostring(Script))
BlockOnCommand(unit.Guard_Target(bacta), 2)
end
return true
end
end
end
return false
end
-- Fix the unit or hide if appropriate.
-- Return true if the unit was fixed.
function ConsiderRepair(unit)
unit_hull = unit.Get_Hull()
if (unit_hull < 0.8) then
repair_station = Find_Nearest(unit, "HealsVehicles", PlayerObject, true)
if TestValid(repair_station) then
if (unit_hull < 0.4) or (unit.Get_Distance(repair_station) < 700) then
BlockOnCommand(unit.Move_To(repair_station))
while unit.Get_Hull() < 0.9 do
BlockOnCommand(unit.Guard_Target(repair_station), 2)
end
return true
end
end
end
return false
end
-- Note, this is safe for event response (because it doesn't block)
function Release_To_Hide(tf, unit)
flee_loc = Find_Nearest(unit, "HealsInfantry", PlayerObject, true)
if not flee_loc then
flee_loc = FindTarget(tf, "Space_Area_Is_Hidden", "Tactical_Location", 1.0, 5000.0)
end
if flee_loc then
unit.Move_To(flee_loc)
unit.Lock_Current_Orders()
tf.Release_Unit(unit)
return true
end
end
-- This is for some give and take pacing. The AI is allowed to attack without difficulty-based pause
-- 1 to N times, then it must wait for the player to win 1 to N times before attacking without pause.
function GalacticAttackAllowed(difficulty, ai_territories_just_gained)
num_ai_attacks_left = GetGlobalValueOrZero(PlayerObject, "num_ai_attacks_left")
if num_ai_attacks_left > 0 then
-- If the AI has allowed attacks left, permit the attack and decrement
GlobalValue.Set(PlayerSpecificName(PlayerObject, "num_ai_attacks_left"), num_ai_attacks_left - 1)
--MessageBox("%s -- ai has %d attacks left; not pausing before next attack", tostring(Script), num_ai_attacks_left)
return true
else
-- AI has to wait for player wins
-- Difficulty will dictate aggressiveness and amount of contrived breathing room the AI gives for free
min_player_wins_unresponded = 4
max_player_wins_unresponded = 8
max_ai_attacks_allowed = 2
if difficulty == "Normal" then
min_player_wins_unresponded = 3
max_player_wins_unresponded = 6
max_ai_attacks_allowed = 2
elseif difficulty == "Hard" then
min_player_wins_unresponded = 1
max_player_wins_unresponded = 2
max_ai_attacks_allowed = 4
end
-- Track the player's progress
num_land_enemy_controlled = EvaluatePerception("Num_Enemy_Land_Territories", PlayerObject)
num_space_enemy_controlled = EvaluatePerception("Num_Enemy_Space_Territories", PlayerObject)
--MessageBox("%s -- num_land_enemy_controlled:%d num_space_enemy_controlled:%d", tostring(Script), num_land_enemy_controlled, num_space_enemy_controlled)
player_gains_before_attacking = GetGlobalValueOrZero(PlayerObject, "player_gains_before_attacking")
if player_gains_before_attacking == 0 then
-- Establish how far the player can go unresponded
player_gains_before_attacking = GameRandom(min_player_wins_unresponded, max_player_wins_unresponded)
GlobalValue.Set(PlayerSpecificName(PlayerObject, "player_gains_before_attacking"), player_gains_before_attacking)
--MessageBox("%s -- Determined %d player gains allowed and recording current player territories.", tostring(Script), player_gains_before_attacking)
-- Record the state of the galaxy
GlobalValue.Set(PlayerSpecificName(PlayerObject, "recent_land_enemy_controlled"), num_land_enemy_controlled)
GlobalValue.Set(PlayerSpecificName(PlayerObject, "recent_space_enemy_controlled"), num_space_enemy_controlled)
end
-- Check the player's progress (before our current attack)
player_territories_gained = num_land_enemy_controlled + num_space_enemy_controlled
- GlobalValue.Get(PlayerSpecificName(PlayerObject, "recent_land_enemy_controlled"))
- GlobalValue.Get(PlayerSpecificName(PlayerObject, "recent_space_enemy_controlled"))
-- + ai_territories_just_gained
if player_territories_gained >= player_gains_before_attacking then
-- Player has won all that he's allowed without AI response, time to start attacking again
num_ai_attacks_left = GameRandom(0, max_player_wins_unresponded - 1)
GlobalValue.Set(PlayerSpecificName(PlayerObject, "num_ai_attacks_left"), num_ai_attacks_left)
-- Also reset the losses allowed, so that it will be randomized next time
GlobalValue.Set(PlayerSpecificName(PlayerObject, "player_gains_before_attacking"), 0)
--MessageBox("%s -- player has enough wins unresponded (%d); not pausing before next attack. \n AI gets %d attacks without pause", tostring(Script), player_territories_gained, num_ai_attacks_left)
return true
else
--MessageBox("%s -- %d player territories gained, %d allowed before responding so pausing before next attack"
-- , tostring(Script), player_territories_gained, player_gains_before_attacking)
if player_territories_gained < 0 then
-- Record the state of the galaxy
--MessageBox("%s -- player lost ground; resetting recent territories records", tostring(Script))
GlobalValue.Set(PlayerSpecificName(PlayerObject, "recent_land_enemy_controlled"), num_land_enemy_controlled)
GlobalValue.Set(PlayerSpecificName(PlayerObject, "recent_space_enemy_controlled"), num_space_enemy_controlled)
end
end
end
return false
end
function DifficultyBasedMinPause(difficulty)
sleep_duration = 300
if difficulty == "Normal" then
sleep_duration = 200
elseif difficulty == "Hard" then
sleep_duration = 45
end
return sleep_duration
end
function GetGlobalValueOrZero(player, value_name)
ret_value = GlobalValue.Get(PlayerSpecificName(player, value_name))
if ret_value == nil then
return 0.0
end
return ret_value
end