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,519 @@
--/////////////////////////////////////////////////////////////////////////////////////////////////
-- (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/Library/PGEvents.LUA
--
-- Original Editor: Giovanni Galyana
--
-- Final Edit By: Giovanni Galyana
--
-- Date: 7 March, 2015
--
-- Revisions: 0
--
--/////////////////////////////////////////////////////////////////////////////////////////////////
--
-- Default Event Handlers.
--
require("PGTaskForce")
function GoHeal(tf, unit, healer, release)
--If we can lay proximity mines, do so and then rely on a further call to kite the enemy over them
--Add a random factor here since proximity mines currently have no cooldown and so we'll never run
--because we can always use them
if (GameRandom.Get_Float() > 0.5) and Try_Ability(unit, "PROXIMITY_MINES", unit) then
return
end
if Try_Ability(unit, "BUZZ_DROIDS", unit) then
return
end
if release then
Try_Ability(unit,"JET_PACK", healer)
Try_Ability(unit,"SPRINT")
Try_Ability(unit, "FORCE_CLOAK")
Try_Ability(unit, "STEALTH")
unit.Move_To(healer, 10)
unit.Lock_Current_Orders()
tf.Release_Unit(unit)
else
Try_Ability(unit,"JET_PACK", healer)
Try_Ability(unit,"SPRINT")
Try_Ability(unit, "FORCE_CLOAK")
Try_Ability(unit, "STEALTH")
unit.Divert(healer)
end
end
function GoKite(tf, unit, kite_pos, release)
--If we can lay proximity mines, do so and then rely on a further call to kite the enemy over them
--Add a random factor here since proximity mines currently have no cooldown and so we'll never run
--because we can always use them
if (GameRandom.Get_Float() > 0.5) and Try_Ability(unit, "PROXIMITY_MINES", unit) then
return
end
if Try_Ability(unit, "BUZZ_DROIDS", unit) then
return
end
if release then
Try_Ability(unit,"Turbo") -- Enable Turbo mode, if we have it.
Try_Ability(unit,"JET_PACK", kite_pos)
Try_Ability(unit,"EJECT_VEHICLE_THIEF")
Try_Ability(unit,"SPRINT")
Try_Ability(unit, "SPOILER_LOCK")
Try_Ability(unit, "REPLENISH_WINGMEN")
Try_Ability(unit, "FORCE_CLOAK")
Try_Ability(unit, "STEALTH")
if unit.Get_Hull() > 0.5 then
Try_Ability(unit, "STIM_PACK")
end
unit.Move_To(kite_pos)
unit.Lock_Current_Orders()
tf.Release_Unit(unit)
else
if not unit.Is_On_Diversion() then
--MessageBox("%s -- Diverting: %s", tostring(Script), tostring(unit))
Try_Ability(unit,"Turbo") -- Enable Turbo mode, if we have it.
Try_Ability(unit,"JET_PACK", kite_pos)
Try_Ability(unit,"EJECT_VEHICLE_THIEF")
Try_Ability(unit,"SPRINT")
Try_Ability(unit, "SPOILER_LOCK")
Try_Ability(unit, "REPLENISH_WINGMEN")
Try_Ability(unit, "FORCE_CLOAK")
Try_Ability(unit, "STEALTH")
if unit.Get_Hull() > 0.5 then
Try_Ability(unit, "STIM_PACK")
end
unit.Divert(kite_pos)
end
end
end
function Try_Good_Ground(tf, unit)
nearest_good_ground_indicator = Find_Nearest(unit, "Prop_Good_Ground_Area")
if nearest_good_ground_indicator then
dist_to_good_ground = unit.Get_Distance(nearest_good_ground_indicator)
if (dist_to_good_ground < 300) and (dist_to_good_ground > 20) then
unit.Activate_Ability("SPREAD_OUT", false)
unit.Move_To(nearest_good_ground_indicator)
unit.Lock_Current_Orders()
tf.Release_Unit(unit)
return true
end
end
return false
end
-- This should be useful for getting units within the minimum attack range
-- or outside the maximum attack range on opponents who behave like artillery
function Respond_To_MinRange_Attacks(tf, unit)
DebugMessage("%s-- looking at attacker for minrange response", tostring(Script))
min_range_attackers = {
"R_Ground_Turbolaser_Tower"
,"E_Ground_Turbolaser_Tower"
,"U_Ground_Turbolaser_Tower"
,"H_Ground_Turbolaser_Tower"
,"H_Ground_Heavy_Beam_Tower"
,"FCU_E_Ground_Turbolaser_Tower"
,"FCU_R_Ground_Turbolaser_Tower"
,"FCU_U_Ground_Turbolaser_Tower"
,"FCU_H_Ground_Heavy_Beam_Tower"
,"MPTL"
,"SPMAT_Walker"
,"AALL6"
,"Hutt_SailBarge"
,"Marauder_Missile_Cruiser"
,"Broadside_Class_Cruiser"
}
deadly_enemy = FindDeadlyEnemy(unit)
if TestValid(deadly_enemy) then
deadly_enemy_type = deadly_enemy.Get_Type()
if Is_Type_In_List(deadly_enemy_type, min_range_attackers) then
DebugMessage("%s -- attacked by min range attacker", tostring(Script))
-- Move any units in the task force which are in range of the attacker
-- to a position over the max range or under the min range
approach_or_flee_range = ((deadly_enemy_type.Get_Max_Range() - deadly_enemy_type.Get_Min_Range()) * 2 / 3) + deadly_enemy_type.Get_Min_Range()
for i, tf_unit in pairs(tf.Get_Unit_Table()) do
DebugMessage("%s -- considering run or approach for %s", tostring(Script), tostring(tf_unit))
distance = tf_unit.Get_Distance(deadly_enemy)
if distance < deadly_enemy_type.Get_Max_Range() then
if distance < approach_or_flee_range then
DebugMessage("%s -- trying to run inside min attack range", tostring(Script))
tf_unit.Move_To(deadly_enemy)
tf_unit.Lock_Current_Orders()
tf.Release_Unit(unit)
else
DebugMessage("%s -- trying to run outside max attack range", tostring(Script))
GoKite(tf, tf_unit, Project_By_Unit_Range(deadly_enemy, tf_unit))
end
end
end
return true
end
end
return false
end
function Is_Type_In_List(unit_type, type_name_list)
for i, type_name in pairs(type_name_list) do
DebugMessage("%s -- type:%s checking match to:%s", tostring(Script), unit_type.Get_Name(), type_name)
if unit_type == Find_Object_Type(type_name) then
return true
end
end
return false
end
-- Check if the passed ability is one of the type that the AI wants to turn back on when cancelled
function IsAbilityAllowedToRecover(ability)
allowed_abilities = {
"SPOILER_LOCK"
,"Turbo"
}
for i, allowed_ability in pairs(allowed_abilities) do
if ability == allowed_ability then
return true
end
end
return false
end
function Default_Space_Conflict_Begin()
DebugMessage("%s -- In Default_Space_Conflict_Begin.", tostring(Script))
InSpaceConflict = true
GlobalValue.Set(PlayerSpecificName(PlayerObject, "CONTACT_OCCURED"), 0.0)
end
function Default_Space_Conflict_End()
DebugMessage("%s -- In Default_Space_Conflict_End.", tostring(Script))
InSpaceConflict = false
GlobalValue.Set(PlayerSpecificName(PlayerObject, "CONTACT_OCCURED"), 0.0)
end
function Default_Unit_Destroyed()
DebugMessage("%s -- In Default_Unit_Destroyed.", tostring(Script))
end
function Default_Unit_Damaged(tf, unit, attacker, deliberate)
DebugMessage("%s -- In Default_Unit_Damaged.", tostring(Script))
if not TestValid(unit) or not TestValid(attacker) or attacker.Is_Category("Structure") then
return
end
lib_issued_movement_response = false
-- all units but Interdictors try to maneuver against artillery and turbolasers
-- Interdictors should use missile shield instead
if unit.Get_Type() ~= Find_Object_Type("Interdictor_Cruiser") then
lib_issued_movement_response = Respond_To_MinRange_Attacks(tf, unit)
end
if Should_Crush(unit, attacker) then
unit.Divert(Project_By_Unit_Range(unit, attacker))
lib_issued_movement_response = true
end
-- If the unit is infantry, try to use any nearby garrisons or "good ground"
if unit.Is_Category("Infantry") then
if not lib_issued_movement_response then
lib_issued_movement_response = Try_Garrison(tf, unit, unit.Get_Hull() > 0.4, 300.0)
end
if not lib_issued_movement_response then
lib_issued_movement_response = Try_Good_Ground(tf, unit)
end
end
if attacker.Is_Category("Infantry") then
Try_Deploy_Garrison(unit, attacker, 0.5)
end
-- Use "Power to Shields" if this unit has it and it's ready
lib_ability_activated = false
lib_shield_level = unit.Get_Shield()
if lib_shield_level < 0.2 then
lib_ability_activated = Try_Ability(unit, "INVULNERABILITY")
end
if (not lib_ability_activated) and (lib_shield_level < 0.8) then
lib_ability_activated = Try_Ability(unit, "Defend")
end
projectile_type = attacker.Get_Current_Projectile_Type()
if TestValid(projectile_type) then
if (not lib_ability_activated) and projectile_type.Is_Affected_By_Missile_Shield() then
lib_ability_activated = Try_Ability(unit, "SENSOR_JAMMING") or Try_Ability(unit, "MISSILE_SHIELD")
end
if (not lib_ability_activated) and projectile_type.Is_Affected_By_Laser_Defense() then
lib_ability_activated = Try_Ability(unit, "LASER_DEFENSE")
end
end
--Everything below deals with movement orders
if lib_issued_movement_response then
return
end
-- non-hero fighters will always willingly dogfight other fighters
if deliberate and attacker.Is_Category("Fighter") and unit.Is_Category("Fighter") then
DebugMessage("%s -- Fighter shot by fighter, releasing unit from tf and attacking.", tostring(Script))
tf.Release_Unit(unit)
unit.Activate_Ability("SPOILER_LOCK", false)
if not unit.Activate_Ability("BUZZ_DROIDS", attacker) then
unit.Attack_Target(attacker)
end
-- Default handling for a dying unit in both space and land modes.
-- Is this unit not fodder AND do we have low health AND (we have a bad face off OR we're rapidly being killed for any reason)
else
lib_time_till_dead = unit.Get_Time_Till_Dead()
lib_attacker_is_good_vs_me = attacker.Is_Good_Against(unit)
lib_i_am_good_vs_attacker = unit.Is_Good_Against(attacker)
lib_current_health = unit.Get_Hull()
lib_is_hero = unit.Get_Type().Is_Hero()
lib_is_fodder = unit.Has_Property("Fodder")
if not lib_i_am_good_vs_attacker then
Try_Ability(unit, "DEPLOY_TROOPERS")
end
if ((not lib_is_fodder) and lib_time_till_dead < 20) or
((not lib_is_fodder) and lib_current_health < 0.2) or
(lib_is_hero and lib_current_health < 0.6) or
(lib_current_health < 0.7 and lib_attacker_is_good_vs_me) or
(lib_current_health < 0.4 and not lib_i_am_good_vs_attacker) then
--Certain factions have no self-preservation
lib_faction_name = unit.Get_Owner().Get_Faction_Name()
if lib_faction_name == "PIRATES" or lib_faction_name == "HUTTS" then
return
end
-- Turn off any abilities that would hinder self-preservation
unit.Activate_Ability("Power_To_Weapons", false)
-- Try to find the nearest healing structure appropriate for this unit
lib_healer_property_flag = Get_Special_Healer_Property_Flag(unit)
if not lib_healer_property_flag then
if unit.Is_Category("Infantry") then
lib_healer_property_flag = "HealsInfantry"
elseif unit.Is_Category("Vehicle") then
lib_healer_property_flag = "HealsVehicles"
end
end
if lib_healer_property_flag then
healer = Find_Nearest(unit, lib_healer_property_flag, PlayerObject, true)
end
lib_should_release = lib_attacker_is_good_vs_me or lib_is_hero or (lib_current_health < 0.33)
-- Try to heal if we have a healer
if healer then
GoHeal(tf, unit, healer, lib_should_release)
end
if not lib_is_fodder then
-- Try to find a protected kiting location
friendly = Find_Nearest(unit, PlayerObject, true)
xfire_pos = Get_Most_Defended_Position(unit, PlayerObject)
if xfire_pos then
kite_pos = Project_By_Unit_Range(attacker, xfire_pos)
elseif TestValid(friendly) then
DebugMessage("Failed to find a Most Defended Position, using position of nearby friendly.")
kite_pos = Project_By_Unit_Range(attacker, friendly)
else
kite_pos = Project_By_Unit_Range(attacker, unit)
end
GoKite(tf, unit, kite_pos, lib_should_release)
end
end
end
end
function Default_Original_Target_Destroyed()
--DebugMessage("%s -- Original target destroyed. Aborting.", tostring(Script))
Attacking = false
--ScriptExit() Some plans now have behaviors to occur after this event.
end
function Default_Current_Target_Destroyed(tf)
--MessageBox("%s -- Current target destroyed. Aborting.", tostring(Script))
Attacking = false
-- Turn off some unending abilities that might no longer be appropriate
tf.Activate_Ability("SPREAD_OUT", false)
--ScriptExit() Some plans now have behaviors to occur after this event.
end
function Default_Original_Target_Owner_Changed(tf, old_player, new_player)
if InvasionActive == true then
return
end
DebugMessage("%s -- Original target ownership changed. Aborting.", tostring(Script))
ScriptExit()
end
function Default_Unit_Move_Finished(tf, unit)
Try_Deploy_Garrison(unit, nil, 0.5)
end
function Should_Crush(unit, target)
-- don't crush in easy mode
if (PlayerObject.Get_Difficulty() == "Easy") then
return false
end
-- don't try to crush again if already on a diversion
if unit.Is_On_Diversion() then
return false
end
-- if the vehicle is good at it, the victim is infantry, and vulnerable to crushing
if unit.Has_Property("GoodInfantryCrusher") and target.Is_Category("Infantry") then
if target.Is_Ability_Active("SPREAD_OUT") then
return true
elseif GameRandom.Get_Float() > 0.8 then
return true
end
end
-- if the vehicle can crush anything and is close enough
if unit.Has_Property("IsSupercrusher") and (unit.Get_Distance(target) < 75) then
return true
end
return false
end
function Default_Target_In_Range(tf, unit, target)
--MessageBox("%s -- unit: Default_Target_In_Range for: %s.", tostring(Script), tostring(unit), tostring(target))
-- We'll assume that once the first unit within a task force is in range, the attack has begun.
Attacking = true
-- Certain units like to try to crush other units, but we can't crush Rebel units that are spread out
if Should_Crush(unit, target) then
DebugMessage("%s -- Attempting to crush %s with %s", tostring(Script), tostring(target), tostring(unit))
unit.Divert(Project_By_Unit_Range(unit, target))
end
Try_Deploy_Garrison(unit, target, 0.5)
-- Turn various abilities that would be useful.
-- The ability time-out or the plan ending will turn off the ability.
Try_Ability(unit, "Power_To_Weapons")
Try_Ability(unit, "SPREAD_OUT")
Try_Ability(unit, "BARRAGE", target)
Try_Ability(unit, "BUZZ_DROIDS", target)
Try_Ability(unit, "FULL_SALVO")
Try_Ability(unit, "BLAST")
if unit.Get_Hull() > 0.5 then
Try_Ability(unit, "STIM_PACK")
end
Try_Weapon_Switch(unit, target)
GlobalValue.Set(PlayerSpecificName(PlayerObject, "CONTACT_OCCURED"), 1.0)
end
function Default_Hardpoint_Target_In_Range(tf, unit, target)
DebugMessage("%s -- A hardpoint of %s can now fire on target %s.", tostring(Script), tostring(unit), tostring(attacker))
end
function Default_No_Units_Remaining()
DebugMessage("%s -- All units dead or non-buildable. Abandonning plan.", tostring(Script))
ScriptExit()
end
function Default_Unit_Diversion_Finished(tf, unit)
if TestValid(unit) then
-- Turn off turbo, if we happened to be using it to assist in a divert (evasive maneuver).
unit.Activate_Ability("Turbo", false)
unit.Activate_Ability("SPOILER_LOCK", false)
end
end
-- This fires if the countdown was going and it is now refreshed or if you come out of a nebula
function Default_Unit_Ability_Ready(tf, unit, ability)
--MessageBox("%s ready for %s", ability, tostring(unit))
-- Try to recover use of interrupted abilities.
if lib_cancelled_abilities[unit] and lib_cancelled_abilities[unit][ability] then
--MessageBox("%s-- attempting to recover use of %s", tostring(Script), ability)
unit.Activate_Ability(ability, true)
lib_cancelled_abilities[unit][ability] = false
end
end
-- An ability was interrupted before naturally finishing.
function Default_Unit_Ability_Cancelled(tf, unit, ability)
DebugMessage("%s -- Ability %s of %s has been cancelled!", tostring(Script), ability, tostring(unit))
-- Track certain abilities that get cancelled, so we can recover them later
if IsAbilityAllowedToRecover(ability) then
-- make a new ability table for this unit, if one doesn't yet exist
if not lib_cancelled_abilities[unit] then
lib_cancelled_abilities[unit] = {}
end
lib_cancelled_abilities[unit][ability] = true
end
end
-- An ability finished naturally by its duration running out or by being turned off.
function Default_Unit_Ability_Finished(tf, unit)
--DebugMessage("%s -- An ability for %s has finished!", tostring(Script), ability, tostring(unit))
end