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,163 @@
-- $Id: //depot/Projects/StarWars_Expansion/Run/Data/Scripts/Library/PGAICommands.lua#2 $
--/////////////////////////////////////////////////////////////////////////////////////////////////
--
-- (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/PGAICommands.lua $
--
-- Original Author: Brian Hayes
--
-- $Author: James_Yarrow $
--
-- $Change: 57990 $
--
-- $DateTime: 2006/11/13 17:33:10 $
--
-- $Revision: #2 $
--
--/////////////////////////////////////////////////////////////////////////////////////////////////
require("PGCommands")
function Base_Definitions()
-- DebugMessage("%s -- In Base_Definitions", tostring(Script))
InSpaceConflict = false
MagicPlan = false
-- Scale all counter forces by this factor
MinContrastScale = 1.0
MaxContrastScale = 1.5
PerFailureContrastAdjust = 0.1
EnemyContrastTypes = {}
FriendlyContrastTypes = {}
ContrastTypeScale = {}
-- Track abilities that got cancelled (nebula or whatever) so we can turn them on later
lib_cancelled_abilities = {}
Common_Base_Definitions()
-- nil out the global Taskforce variables.
if TaskForce and type(TaskForce) == "table" then
for idx,tfdef in pairs(TaskForce) do
if type(tfdef) == "table" and type(tfdef[1]) == "string" then
_G[tfdef[1]] = nil
end
end
end
if PlanDefinitionLoad then
Set_Contrast_Values()
end
PlanDefinitionLoad = nil
if Definitions then
Definitions()
end
end
function Set_Contrast_Values()
_e_cnt = 1;
EnemyContrastTypes[_e_cnt] = "Fighter"
FriendlyContrastTypeNames = {"AntiFighter", "Bomber", "Fighter", "Corvette", "Frigate", "Capital"}
FriendlyContrastWeights = {4.0, 0.25, 1.0, 1.0, 1.0, 1.0}
FriendlyContrastTypes[_e_cnt] = WeightedTypeList.Create()
FriendlyContrastTypes[_e_cnt].Parse(FriendlyContrastTypeNames, FriendlyContrastWeights)
_e_cnt = _e_cnt+1;
EnemyContrastTypes[_e_cnt] = "Bomber"
FriendlyContrastTypeNames = {"AntiBomber", "Frigate", "Capital", "Fighter", "Bomber", "Corvette"}
FriendlyContrastWeights = {4.0, 0.25, 0.25, 1.0, 1.0, 1.0}
FriendlyContrastTypes[_e_cnt] = WeightedTypeList.Create()
FriendlyContrastTypes[_e_cnt].Parse(FriendlyContrastTypeNames, FriendlyContrastWeights)
_e_cnt = _e_cnt+1;
EnemyContrastTypes[_e_cnt] = "Transport"
FriendlyContrastTypeNames = {"Fighter", "Bomber", "Corvette", "Frigate", "Capital", }
FriendlyContrastWeights = {1.0, 1.0, 1.0, 1.0, 1.0}
FriendlyContrastTypes[_e_cnt] = WeightedTypeList.Create()
FriendlyContrastTypes[_e_cnt].Parse(FriendlyContrastTypeNames, FriendlyContrastWeights)
_e_cnt = _e_cnt+1;
EnemyContrastTypes[_e_cnt] = "Corvette"
FriendlyContrastTypeNames = {"AntiCorvette", "Fighter", "Bomber", "Corvette", "Frigate", "Capital"}
FriendlyContrastWeights = {3.0, 0.25, 0.25, 1.0, 1.0, 1.0}
FriendlyContrastTypes[_e_cnt] = WeightedTypeList.Create()
FriendlyContrastTypes[_e_cnt].Parse(FriendlyContrastTypeNames, FriendlyContrastWeights)
_e_cnt = _e_cnt+1;
EnemyContrastTypes[_e_cnt] = "Frigate"
FriendlyContrastTypeNames = {"AntiFrigate", "Corvette", "Fighter", "Bomber", "Frigate", "Capital"}
FriendlyContrastWeights = {3.0, 0.5, 1.0, 1.0, 1.0, 1.0}
FriendlyContrastTypes[_e_cnt] = WeightedTypeList.Create()
FriendlyContrastTypes[_e_cnt].Parse(FriendlyContrastTypeNames, FriendlyContrastWeights)
_e_cnt = _e_cnt+1;
EnemyContrastTypes[_e_cnt] = "Capital"
FriendlyContrastTypeNames = {"AntiCapital", "Corvette", "Frigate", "Fighter", "Bomber", "Capital"}
FriendlyContrastWeights = {2.0, 0.33, 0.5, 0.75, 1.0, 1.0}
FriendlyContrastTypes[_e_cnt] = WeightedTypeList.Create()
FriendlyContrastTypes[_e_cnt].Parse(FriendlyContrastTypeNames, FriendlyContrastWeights)
_e_cnt = _e_cnt+1;
EnemyContrastTypes[_e_cnt] = "Infantry"
FriendlyContrastTypeNames = {"AntiInfantry", "Vehicle", "Infantry", "Air", "Structure", "LandHero"}
FriendlyContrastWeights = {2.0, 0.5, 1.0, 1.0, 1.0, 2.0}
FriendlyContrastTypes[_e_cnt] = WeightedTypeList.Create()
FriendlyContrastTypes[_e_cnt].Parse(FriendlyContrastTypeNames, FriendlyContrastWeights)
_e_cnt = _e_cnt+1;
EnemyContrastTypes[_e_cnt] = "Vehicle"
FriendlyContrastTypeNames = {"AntiVehicle", "Infantry", "Vehicle", "Air", "Structure", "LandHero"}
FriendlyContrastWeights = {2.0, 0.25, 1.0, 1.0, 1.0, 2.0}
FriendlyContrastTypes[_e_cnt] = WeightedTypeList.Create()
FriendlyContrastTypes[_e_cnt].Parse(FriendlyContrastTypeNames, FriendlyContrastWeights)
_e_cnt = _e_cnt+1;
EnemyContrastTypes[_e_cnt] = "Air"
FriendlyContrastTypeNames = {"AntiAir", "Infantry", "Vehicle", "Air", "Structure", "LandHero"}
FriendlyContrastWeights = {2.0, 1.0, 1.0, 1.0, 1.0, 1.0}
FriendlyContrastTypes[_e_cnt] = WeightedTypeList.Create()
FriendlyContrastTypes[_e_cnt].Parse(FriendlyContrastTypeNames, FriendlyContrastWeights)
_e_cnt = _e_cnt+1;
EnemyContrastTypes[_e_cnt] = "Structure"
FriendlyContrastTypeNames = {"AntiStructure", "Infantry", "Vehicle", "Air", "Structure", "LandHero"}
FriendlyContrastWeights = {2.0, 1.0, 1.0, 1.0, 1.0, 1.0}
FriendlyContrastTypes[_e_cnt] = WeightedTypeList.Create()
FriendlyContrastTypes[_e_cnt].Parse(FriendlyContrastTypeNames, FriendlyContrastWeights)
_e_cnt = _e_cnt+1;
EnemyContrastTypes[_e_cnt] = "LandHero"
FriendlyContrastTypeNames = {"Infantry", "Vehicle", "Air", "Structure", "LandHero"}
FriendlyContrastWeights = {0.5, 0.5, 0.5, 0.25, 1.0}
FriendlyContrastTypes[_e_cnt] = WeightedTypeList.Create()
FriendlyContrastTypes[_e_cnt].Parse(FriendlyContrastTypeNames, FriendlyContrastWeights)
_e_cnt = _e_cnt+1;
end

View File

@@ -0,0 +1,287 @@
-- $Id: //depot/Projects/StarWars_Expansion/Run/Data/Scripts/Library/PGBase.lua#2 $
--/////////////////////////////////////////////////////////////////////////////////////////////////
--
-- (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/PGBase.lua $
--
-- Original Author: Brian Hayes
--
-- $Author: James_Yarrow $
--
-- $Change: 45244 $
--
-- $DateTime: 2006/05/26 10:01:00 $
--
-- $Revision: #2 $
--
--/////////////////////////////////////////////////////////////////////////////////////////////////
require("PGDebug")
YieldCount = 0;
function ScriptExit()
_ScriptExit() -- set a flag in 'C' to terminate the whole script on next yield
if GetThreadID() >= 0 then
coroutine.yield(false) -- return false to exit this thread
end
end
function Sleep(time)
--DebugMessage("Sleeping... SleepTime: %.3f, CurTime: %.3f\n", time, GetCurrentTime())
ThreadValue.Set("StartTime", GetCurrentTime())
while GetCurrentTime() - ThreadValue("StartTime") < time do
PumpEvents()
end
--DebugMessage("Done with Sleep. Continuing, CurTime: %.3f\n", GetCurrentTime())
end
-- Service the block until optional max duration has expired or alternate break function returns true
-- Pass -1 max_duration to use optional alternate break function with no time limit
function BlockOnCommand(block, max_duration, alternate_break_func)
PumpEvents()
if not block then
return nil
end
break_block = false
ThreadValue.Set("BlockStart", GetCurrentTime())
repeat
if break_block == true then
break_block = false
return nil
end
PumpEvents()
if ((max_duration ~= nil) and (max_duration ~= -1)
and (GetCurrentTime() - ThreadValue("BlockStart") > max_duration)) then
--MessageBox("%s -- Had a time limit and it expired", tostring(Script))
return nil
end
if ((alternate_break_func ~= nil) and alternate_break_func()) then
--MessageBox("%s-- had a break func and it returned true", tostring(Script))
return nil
end
until (block.IsFinished() == true)
PumpEvents()
return block.Result()
end
function BreakBlock()
break_block = true
end
function TestCommand(block)
if not block then
return nil
end
PumpEvents()
return block.IsFinished()
end
function PumpEvents()
if Object and type(Object) == "userdata" then
Object.Service_Wrapper()
end
if Pump_Service and type(Pump_Service) == "function" then
Pump_Service()
end
if ThreadValue("InPumpEvents") then
ScriptError("%s -- Already in pump event!!", tostring(Script))
end
ThreadValue.Set("InPumpEvents", true)
--DebugMessage("%s -- Entering yield. Count: %d, Time: %.3f\n", tostring(Script), YieldCount, GetCurrentTime())
YieldCount = YieldCount + 1
coroutine.yield(true) -- yield here and return to 'C'
--DebugMessage("%s -- Return from yield. Count: %d, Time: %.3f\n", tostring(Script), YieldCount, GetCurrentTime())
CurrentEvent = GetEvent()
while CurrentEvent do
ScriptMessage("%s -- Pumping Event: %s.", tostring(Script), tostring(CurrentEvent))
EventParams = GetEvent.Params()
if EventParams then
CurrentEvent(unpack(EventParams))
else
CurrentEvent()
end
if Script.Debug_Should_Issue_Event_Alert() and DebugEventAlert then
DebugEventAlert(CurrentEvent, EventParams)
end
CurrentEvent = GetEvent()
end
ThreadValue.Set("InPumpEvents", false)
end
function TestValid(wrapper)
if wrapper == nil then
return false
end
if wrapper.Is_Valid == nil then
return false
end
return wrapper.Is_Valid()
end
function Clamp(value, min, max)
if value < min then
return min
elseif value > max then
return max
else
return value
end
end
-- Nasty hack of a floor function to be replaced if a math library floor funciton is exposed
function Dirty_Floor(val)
return string.format("%d", val) -- works on implicit string to int conversion
end
-- Machine independent modulus function
function Simple_Mod(a,b)
--return a-b*math.floor(a/b)
return a-b*Dirty_Floor(a/b)
end
-- Returns if something happened, given a % chance
function Chance(seed, percent)
roll = Simple_Mod((seed + 1), 100)
is_allowed = roll < percent
DebugMessage("%s -- seed:%d percent:%d roll:%d is_allowed:%s", tostring(Script), seed, percent, roll, tostring(is_allowed))
return is_allowed
end
function GetCurrentMinute()
--return math.floor(GetCurrentTime()/60)
return Dirty_Floor(GetCurrentTime()/60)
end
-- Every X seconds, the AI will have a new opportunity to see if it's allowed to use an ability
function GetAbilityChanceSeed()
return GetCurrentTime()
end
function GetChanceAllowed(difficulty)
--Possibly change these back, but randomness makes things hard to test
chance = 100
if difficulty == "Easy" then
chance = 100
elseif difficulty == "Hard" then
chance = 100
end
return chance
end
function PlayerSpecificName(player_object, var_name)
-- ret_value = tostring(player_object.Get_ID()) .. "_" .. var_name
-- DebugMessage("%s -- creating player specific string %s.", tostring(Script), ret_value)
-- return ret_value
return (tostring("PLAYER" .. player_object.Get_ID()) .. "_" .. var_name)
end
function Flush_G()
entries_for_deletion = {}
--Define the set of tables that we had better keep around
very_important_tables = {
_LOADED,
coroutine,
string,
LuaWrapperMetaTable,
_G,
security,
table,
entries_for_deletion
}
--Silly thing is nil (we think) if we try to add it earlier
table.insert(very_important_tables, very_important_tables)
--Iterate all globals
for i,g_entry in pairs(_G) do
if type(g_entry) == "table" then
--Tables are inherently unsafe: who knows what might be in there?
--If they're not in the list of things we must keep then they go.
for j,important_entry in pairs(very_important_tables) do
if important_entry == g_entry then
keep_table = true
end
end
if not keep_table then
table.insert(entries_for_deletion, i)
end
keep_table = nil
elseif type(g_entry) == "userdata" then
--Some User Data (e.g. our code functions) should be kept, but some is very, very dangerous.
--Query the object to see whether it's safe to persist.
if not g_entry.Is_Pool_Safe() then
table.insert(entries_for_deletion, i)
end
end
end
for i,bad_entry in pairs(entries_for_deletion) do
_G[bad_entry] = nil
end
entries_for_deletion = nil
very_important_tables = nil
end

View File

@@ -0,0 +1,134 @@
-- $Id: //depot/Projects/StarWars_Expansion/Run/Data/Scripts/Library/PGBaseDefinitions.lua#1 $
--/////////////////////////////////////////////////////////////////////////////////////////////////
--
-- (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/PGBaseDefinitions.lua $
--
-- Original Author: Brian Hayes
--
-- $Author: Andre_Arsenault $
--
-- $Change: 37816 $
--
-- $DateTime: 2006/02/15 15:33:33 $
--
-- $Revision: #1 $
--
--/////////////////////////////////////////////////////////////////////////////////////////////////
require("PGBase")
BAD_WEIGHT = -1000000000000000000.0
BIG_FLOAT = 1000000000000000000.0
-- Set the garbage collection threshold to 256k
collectgarbage(256)
function Common_Base_Definitions()
-- Clear out the thread specific values.
ThreadValue.Reset()
-- Clear out any thread events.
GetEvent.Reset()
TimerTable = {}
DeathTable = {}
ProxTable = {}
AttackedTable = {}
CurrentEvent = nil
EventParams = nil
block = nil
break_block = false
YieldCount = 0
AITarget = nil
Object = nil
Target = nil
FreeStore = nil
PlayerObject = nil
LastService = nil
Budget = nil
enemy = nil
taskforce = nil
tfObj = nil
stage = nil
UnitType = nil
invade_status = nil
path = nil
InvasionActive = false
unit = nil
hide_target = nil
healer = nil
xfire_pos = nil
kite_pos = nil
friendly = nil
block_table = {}
lib_anti_idle_block = nil
end
-- base constructor
function Base_Definitions()
Common_Base_Definitions()
if Definitions then
Definitions()
end
end
function Evaluator_Clean_Up()
Target = nil
PlayerObject = nil
if Clean_Up then
Clean_Up()
end
end
-- Returns true if the entire list is not in some kind of obscuring field
function UnitListIsObscured(unit_list)
for i, unit in pairs(unit_list) do
if not (unit.Is_In_Nebula() or unit.Is_In_Asteroid_Field() or unit.Is_In_Ion_Storm()) then
return false
end
end
return true
end
-- Remove all invalid or dead units from a list and return it.
function Cull_Unit_List(unit_list)
for k, unit in pairs(unit_list) do
if not TestValid(unit) then
unit_list[k] = nil
end
end
return unit_list
end

View File

@@ -0,0 +1,593 @@
-- $Id: //depot/Projects/StarWars_Expansion/Run/Data/Scripts/Library/PGCommands.lua#10 $
--/////////////////////////////////////////////////////////////////////////////////////////////////
--
-- (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/PGCommands.lua $
--
-- Original Author: Brian Hayes
--
-- $Author: James_Yarrow $
--
-- $Change: 53991 $
--
-- $DateTime: 2006/09/08 11:01:51 $
--
-- $Revision: #10 $
--
--/////////////////////////////////////////////////////////////////////////////////////////////////
require("PGBaseDefinitions")
-- Deprecated...
--
-- function ProduceForce(taskforce)
-- tfIndex = 0
--
-- DebugMessage("Beginning production on %s at %s.", tostring(taskforce),
-- tostring(taskforce.Production_Facility()))
--
-- -- loop through all the unit types and produce each one.
-- UnitType = taskforce.Get_Type_Of_Unit(tfIndex)
-- while UnitType do
--
-- -- Build the object at the production facility.
-- tfObj = WaitProduceObject(UnitType, taskforce.Production_Facility())
-- DebugMessage("Object %s produced.", tostring(tfObj))
--
-- -- Add the object to the task force.
-- taskforce.Add_Force(tfObj)
--
-- -- Remove our reference to the object, since a merge will destroy it.
-- tfObj.Release()
--
-- -- Merge the new fleets together.
-- BlockOnCommand(taskforce.Form_Units())
--
-- -- Look for another unit type.
-- tfIndex = tfIndex + 1
-- UnitType = taskforce.Get_Type_Of_Unit(tfIndex)
-- end
-- end
--
-- function ProduceObject(player, objecttype, where)
-- return _ProduceObject(player, objecttype, where)
-- end
--
-- function WaitProduceObject(objecttype, where)
-- return BlockOnCommand(ProduceObject(PlayerObject, objecttype, where))
-- end
function WaitForever()
DebugMessage("%s -- Waiting forever...", tostring(Script))
while true do
PumpEvents()
end
-- BlockOnCommand(BlockForever())
DebugMessage("%s -- Something interrupted the wait!.", tostring(Script))
end
-- TimerTable[func] = {timeout = timeout, start_time = GetCurrentTime(), param = param }
--function Debug_Timer_Table()
-- OutputDebug("%s -- TimerTable Dump.\n", tostring(Script))
-- for func,tabtab in pairs(TimerTable) do
-- for idx,tab in pairs(tabtab) do
-- OutputDebug("%s, %f, %f, %s\n", tostring(func), tab.timeout, tab.start_time, tostring(tab.param))
-- end
-- end
--end
function Register_Timer(func, timeout, param)
if TimerTable[func] == nil then
TimerTable[func] = {}
end
table.insert(TimerTable[func], {timeout = timeout, start_time = GetCurrentTime(), param = param})
end
function Process_Timers()
for func,tabtab in pairs(TimerTable) do
found_entry = false
for idx,tab in pairs(tabtab) do
found_entry = true
if tab.timeout + tab.start_time < GetCurrentTime() then
tabtab[idx] = nil
func(tab.param)
Process_Timers()
return
end
end
if found_entry == false then
TimerTable[func] = nil
Process_Timers()
return
end
end
end
-- Cancels all occurences of this timer function
function Cancel_Timer(func)
if func ~= nil then
TimerTable[func] = nil
else
MessageBox("%s -- cancelling nonexistant function, got:%s; aborting.", tostring(Script), type(func))
end
end
-- Setup a callback for the death or deletion of a given object.
function Register_Death_Event(obj, func)
if not TestValid(obj) then
MessageBox("%s -- Error, object doesn't exist or has already died.", tostring(Script))
return
end
if DeathTable[obj] ~= nil then
MessageBox("%s -- Error, object already registered for death event", tostring(Script))
return
end
DeathTable[obj] = func
end
function Process_Death_Events()
for obj, func in pairs(DeathTable) do
if not TestValid(obj) then
DeathTable[obj] = nil
func()
Process_Death_Events()
return
end
end
end
-- Setup a callback for a given object falling under attack.
function Register_Attacked_Event(obj, func)
if not TestValid(obj) then
MessageBox("%s -- Error, object doesn't exist or has died.", tostring(Script))
return
end
if AttackedTable[obj] ~= nil then
MessageBox("%s -- Error, object already registered for attacked event", tostring(Script))
return
end
-- Storing the callback and if the object currently has a "deadly enemy"
AttackedTable[obj] = {func, false}
end
-- Executes the callback with (true, object) if first going under attack.
-- Executes the callback with (false) if no longer under attack.
function Process_Attacked_Events()
for obj, table in pairs(AttackedTable) do
if not TestValid(obj) then
AttackedTable[obj] = nil
else
most_deadly_enemy = FindDeadlyEnemy(obj)
if most_deadly_enemy then
-- If we have a deadly enemy and this just became true, run the callback.
if not table[2] then
table[2] = true
table[1](true, most_deadly_enemy, obj)
Process_Attacked_Events()
return
end
-- Update that we don't have a deadly enemy any longer.
--else
elseif table[2] then
--MessageBox("obj:%s now has no deadly enemy", tostring(obj))
table[2] = false
table[1](false, nil, obj)
end
end
end
end
function Cancel_Attacked_Event(obj)
if obj ~= nil then
AttackedTable[obj] = nil
else
MessageBox("received nil object")
end
end
-- Set up proximity triggers on arbitrary objects and have them serviced.
function Register_Prox(obj, func, range, player_filter)
-- prevent this from doing anything in galactic mode
if Get_Game_Mode() == "Galactic" then
DebugMessage("%s -- Warning, proximity register disallowed in galactic mode; aborting.", tostring(Script))
return
end
if not TestValid(obj) then
MessageBox("%s -- Error, prox object doesn't exist; aborting", tostring(Script))
ScriptError("%s -- Error, prox object doesn't exist; aborting", tostring(Script))
return
end
-- Note the player_filter is optional. The user of this function must check
-- for player validity at the source.
if player_filter == nil then
DebugMessage("%s -- Warning, passed a nil player, not filtering prox by player", tostring(Script))
end
obj.Event_Object_In_Range(func, range, player_filter)
ProxTable[obj] = 1
end
function Process_Proximities()
for obj, count in pairs(ProxTable) do
if TestValid(obj) then
obj.Service_Wrapper()
else
ProxTable[obj] = nil
end
end
end
function Pump_Service()
Process_Timers()
Process_Death_Events()
Process_Proximities()
Process_Attacked_Events()
-- Don't test if this is a function, so that we can catch accidental redefinitions when it's used as a function.
if Process_Reinforcements then
Process_Reinforcements()
end
-- This is for behavior that we need evaluated every service without regard to story event state.
if Story_Mode_Service then
Story_Mode_Service()
end
end
-- Try an ability if the AI difficulty will allow a chance
function Try_Ability(thing, ability_name, target)
owner = PlayerObject
if not Is_A_Taskforce(thing) then
owner = thing.Get_Owner()
end
if owner == nil then
MessageBox("%s -- no owner for thing:%s", tostring(Script), tostring(thing))
end
-- At a given difficulty, there is a chance that the ability use will be allowed.
if not Chance(GetAbilityChanceSeed(), GetChanceAllowed(owner.Get_Difficulty())) then
return false
end
return Use_Ability_If_Able(thing, ability_name, target)
end
-- Activates the ability for a unit or a taskforce's units if able.
-- Optionally uses ability on a target.
-- Returns true if the ability was attempted
function Use_Ability_If_Able(thing, ability_name, target)
-- Taskforces aren't able to check for the ability availablity or readiness, but check this for units
if Is_A_Taskforce(thing) or (thing.Has_Ability(ability_name) and thing.Is_Ability_Ready(ability_name) and (not thing.Is_Ability_Active(ability_name))) then
if target == nil then
thing.Activate_Ability(ability_name, true)
elseif TestValid(target) then
thing.Activate_Ability(ability_name, target)
end
return true
end
return false
end
function Is_A_Taskforce(thing)
return thing and thing.Get_Unit_Table
end
-- This will consider diverting the passed object in order to use an area of effect ability centered on the unit.
function ConsiderDivertAndAOE(object, ability_name, area_of_effect, recent_enemy_units, min_threat_to_use_ability)
-- At a given difficulty, there is a chance that the divert for ability use will be allowed.
if (not aoe_pos) and (not Chance(GetCurrentMinute(), GetChanceAllowed(object.Get_Owner().Get_Difficulty()))) then
return
end
-- See if the ability is ready and there are enough enemies around to consider using it.
if object.Is_Ability_Ready(ability_name) then
DebugMessage("%s -- %s is ready and trigger number met", tostring(Script), ability_name)
-- If we haven't found a good use for the ability
if aoe_pos == nil then
-- Find a good place to use the ability and divert or throw the result away.
aoe_pos, aoe_victim_threat = Find_Best_Local_Threat_Center(recent_enemy_units, area_of_effect)
if aoe_pos == nil then
DebugMessage("%s -- couldn't get a valid threat center", tostring(Script))
DebugPrintTable(recent_enemy_units)
return
end
DebugMessage("%s -- Found ability pos with threat %d", tostring(Script), aoe_victim_threat)
if (aoe_victim_threat > min_threat_to_use_ability) then
-- Check distance to prevent the unit from spinning in circles on repeated diversions
if object.Get_Distance(aoe_pos) > 15 then
DebugMessage("%s -- Met minimum threat; diverting.", tostring(Script))
Use_Ability_If_Able(object, "SPRINT")
object.Divert(aoe_pos)
else
DebugMessage("%s -- Met minimum threat; Already very close to ideal target so no divert necessary.", tostring(Script))
end
else
DebugMessage("%s -- Resetting pos and threat.", tostring(Script))
aoe_pos = nil
aoe_victim_threat = nil
end
-- We have found a good use for the ability
else
-- Are we done chasing down the position to use the ability?
if object.Is_On_Diversion() then
DebugMessage("%s -- In process of diverting to chase threat %d (no new orders issued)", tostring(Script), aoe_victim_threat)
else
-- We're done diverting. Perform a sanity check to make sure at least one enemy is now in range.
--if OneOrMoreInRange(object, recent_enemy_units, area_of_effect) then
-- We're done diverting so check to see if we're at least in range of the best location (even if not centered on it)
aoe_pos, aoe_victim_threat = Find_Best_Local_Threat_Center(recent_enemy_units, area_of_effect)
if aoe_pos and (object.Get_Distance(aoe_pos) < area_of_effect) then
-- Use the ability
DebugMessage("%s -- Attempting %s.", tostring(Script), ability_name)
Use_Ability_If_Able(object, ability_name)
else
DebugMessage("%s -- Nothing at diversion locaion; aborting.", tostring(Script))
end
-- Reset everything; this try is done. If the victims moved too much, we'll need to start over.
recent_enemy_units = {}
aoe_pos = nil
aoe_victim_threat = nil
end
end
end
end
function OneOrMoreInRange(origin_unit, target_unit_list, range)
for key, unit in pairs(target_unit_list) do
if origin_unit.Get_Distance(unit) < range then
return true
end
end
return false
end
function PruneFriendlyObjects(obj_table)
non_friendly_obj_table = {}
for i, obj in pairs(obj_table) do
if not (obj.Get_Owner() == PlayerObject) then
table.insert(non_friendly_obj_table, obj)
end
end
return non_friendly_obj_table
end
function Try_Garrison(tf, unit, offensive_only, range)
lib_nearest_garrison = Find_Nearest(unit, "GarrisonCanFire", unit.Get_Owner(), true)
if TestValid(lib_nearest_garrison) and unit.Can_Garrison(lib_nearest_garrison) then
lib_dist_to_garrison = unit.Get_Distance(lib_nearest_garrison)
if lib_dist_to_garrison < range then
unit.Activate_Ability("SPREAD_OUT", false)
unit.Garrison(lib_nearest_garrison)
if TestValid(tf) then
tf.Release_Unit(unit)
unit.Lock_Current_Orders()
end
return true
end
end
if not offensive_only then
lib_nearest_garrison = Find_Nearest(unit, "CanContainGarrison", unit.Get_Owner(), true)
if TestValid(lib_nearest_garrison) and unit.Can_Garrison(lib_nearest_garrison) then
lib_dist_to_garrison = unit.Get_Distance(lib_nearest_garrison)
if lib_dist_to_garrison < range then
unit.Activate_Ability("SPREAD_OUT", false)
unit.Garrison(lib_nearest_garrison)
if TestValid(tf) then
unit.Lock_Current_Orders()
tf.Release_Unit(unit)
end
return true
end
end
end
return false
end
function Try_Deploy_Garrison(object, target, health_threshold)
lib_any_deployed = false
lib_garrison_table = object.Get_Garrisoned_Units()
if table.getn(lib_garrison_table) > 0 then
for i,garrison in pairs(lib_garrison_table) do
if garrison.Get_Hull() > health_threshold then
if (not TestValid(target)) or garrison.Is_Good_Against(target) then
garrison.Leave_Garrison()
lib_any_deployed = true
end
end
end
end
return lib_any_deployed
end
function Get_Special_Healer_Property_Flag(unit)
if not TestValid(unit) then
return nil
end
if not special_healer_table then
special_healer_table = {}
special_healer_table["BOBA_FETT"] = "HealsInfantry"
special_healer_table["EMPEROR_PALPATINE"] = "HealsInfantry"
special_healer_table["HAN_SOLO"] = "HealsInfantry"
special_healer_table["CHEWBACCA"] = "HealsInfantry"
special_healer_table["MARA_JADE"] = "HealsInfantry"
special_healer_table["OBI_WAN_KENOBI"] = "HealsInfantry"
special_healer_table["DARTH_VADER"] = "HealsInfantry"
special_healer_table["KYLE_KATARN"] = "HealsInfantry"
special_healer_table["TACTICAL_R2_3PO_TEAM"] = "HealsVehicles"
special_healer_table["GARGANTUAN_BATTLE_PLATFORM"] = "HealsVehicles"
special_healer_table["LUKE_SKYWALKER_JEDI"] = "HealsInfantry"
special_healer_table["YODA"] = "HealsInfantry"
special_healer_table["BOSSK"] = "HealsInfantry"
special_healer_table["IG-88"] = "HealsVehicles"
special_healer_table["SILRI"] = "HealsInfantry"
special_healer_table["TYBER_ZANN"] = "HealsInfantry"
special_healer_table["URAI_FEN"] = "HealsInfantry"
special_healer_table["PESTELOUS_THE_HUTT"] = "HealsVehicles"
special_healer_table["CUARSON"] = "HealsInfantry"
special_healer_table["XIZOR"] = "HealsInfantry"
special_healer_table["SYKARIIUS"] = "HealsInfantry"
special_healer_table["MPTL_SPOTTER"] = "HealsVehicles"
special_healer_table["SCOUT_TROOPER"] = "HealsVehicles"
special_healer_table["B1_BATTLEDROID"] = "HealsVehicles"
special_healer_table["B2_BATTLEDROID"] = "HealsVehicles"
special_healer_table["B1_REPAIRDROID"] = "HealsVehicles"
special_healer_table["MAGNAGUARD"] = "HealsVehicles"
end
return special_healer_table[unit.Get_Type().Get_Name()]
end
function Set_Land_AI_Targeting_Priorities(tf)
--First set up generic priorities
tf.Set_Targeting_Priorities("Infantry_Attack_Move", "Infantry")
tf.Set_Targeting_Priorities("Infantry_Attack_Move", "LandHero")
tf.Set_Targeting_Priorities("Air_Attack_Move", "Air")
tf.Set_Targeting_Priorities("Heavy_Vehicle_Attack_Move", "Vehicle")
--Now for some more specific stuff
tf.Set_Targeting_Priorities("Rocket_Infantry_Attack_Move", "Plex_Soldier_Team")
tf.Set_Targeting_Priorities("Rocket_Infantry_Attack_Move", "Pirate_Plex_Soldier_Team")
tf.Set_Targeting_Priorities("Light_Vehicle_Attack_Move", "TIE_Crawler")
tf.Set_Targeting_Priorities("Light_Vehicle_Attack_Move", "AT_RT_Walker")
tf.Set_Targeting_Priorities("Light_Vehicle_Attack_Move", "AT_PT_Walker")
tf.Set_Targeting_Priorities("Light_Vehicle_Attack_Move", "AT_ST_Walker")
tf.Set_Targeting_Priorities("Light_Vehicle_Attack_Move", "T1C_Tank")
tf.Set_Targeting_Priorities("Light_Vehicle_Attack_Move", "T2B_Tank")
tf.Set_Targeting_Priorities("Light_Vehicle_Attack_Move", "Dark_Trooper_PhaseI")
tf.Set_Targeting_Priorities("Light_Vehicle_Attack_Move", "Hutt_Modified_Skiff")
tf.Set_Targeting_Priorities("Light_Vehicle_Attack_Move", "Hutt_Modified_Swamp_Speeder")
tf.Set_Targeting_Priorities("Artillery_Attack_Move", "MPTL")
tf.Set_Targeting_Priorities("Artillery_Attack_Move", "SPMAT_Walker")
tf.Set_Targeting_Priorities("Artillery_Attack_Move", "MAL_Rocket_Vehicle")
tf.Set_Targeting_Priorities("Artillery_Attack_Move", "HAG")
end
function Try_Weapon_Switch(object, target)
lib_switcher_type = object.Get_Type()
if not lib_t4b_type then
lib_t4b_type = Find_Object_Type("T4B_TANK")
lib_t3b_type = Find_Object_Type("T3B_TANK")
-- lib_marauder_type = Find_Object_Type("Marauder_Missile_Cruiser")
-- lib_broadside_type = Find_Object_Type("Broadside_Class_Cruiser")
-- lib_atst_type = Find_Object_Type("AT_ST_Walker")
lib_bossk_type = Find_Object_Type("BOSSK")
lib_b2battledroid_type = Find_Object_Type("B2_Battledroid")
lib_destroyer_droid_type = Find_Object_Type("DESTROYER_DROID")
lib_mal_type = Find_Object_Type("MAL_ROCKET_VEHICLE")
-- lib_subjugator_type = Find_Object_Type("Malevolence")
lib_vader_type = Find_Object_Type("TIE_Prototype")
lib_vader_team_type = Find_Object_Type("Darth_Vader_TIE_Fighter_Container")
end
if lib_switcher_type == lib_t4b_type then
object.Activate_Ability("ROCKET_ATTACK", target.Is_Category("Structure") or target.Is_Category("Infantry"))
elseif lib_switcher_type == lib_t3b_type then
object.Activate_Ability("ROCKET_ATTACK", target.Is_Category("Structure") or target.Is_Category("Infantry"))
-- elseif lib_switcher_type == lib_marauder_type then
-- object.Activate_Ability("ROCKET_ATTACK", target.Is_Category("Structure") or target.Is_Category("Capital"))
-- elseif lib_switcher_type == lib_broadside_type then
-- object.Activate_Ability("ROCKET_ATTACK", target.Is_Category("Structure") or target.Is_Category("Capital"))
-- elseif lib_switcher_type == lib_atst_type then
-- object.Activate_Ability("ROCKET_ATTACK", target.Is_Category("Infantry") or target.Is_Category("Vehicle"))
elseif lib_switcher_type == lib_bossk_type then
object.Activate_Ability("SWAP_WEAPONS", target.Is_Category("Infantry") or target.Is_Category("Vehicle"))
elseif lib_switcher_type == lib_b2battledroid_type then
object.Activate_Ability("SWAP_WEAPONS", target.Is_Category("Infantry") or target.Is_Category("Vehicle"))
elseif lib_switcher_type == lib_destroyer_droid_type then
object.Activate_Ability("ROCKET_ATTACK", target.Get_Shield() > 0.0)
elseif lib_switcher_type == lib_mal_type then
object.Activate_Ability("SWAP_WEAPONS", (target.Is_Category("Infantry") or target.Is_Category("Vehicle")) and GameRandom.Get_Float() > 0.8)
-- elseif lib_switcher_type == lib_subjugator_type then
-- object.Activate_Ability("ROCKET_ATTACK", target.Is_Category("Structure") or target.Is_Category("Super") or target.Is_Category("Capital") and target.Get_Shield() > 0.0)
elseif lib_switcher_type == lib_vader_type then
object.Activate_Ability("SWAP_WEAPONS", target.Get_Shield() > 0.0)
elseif lib_switcher_type == lib_vader_team_type then
object.Activate_Ability("SWAP_WEAPONS", target.Get_Shield() > 0.0)
elseif object.Should_Switch_Weapons(target) then
object.Activate_Ability("SWAP_WEAPONS", not object.Is_Ability_Active("SWAP_WEAPONS"))
end
end
function Determine_Magic_Wait_Duration()
lib_magic_wait_time = 2400 - GetCurrentTime()
if lib_magic_wait_time < 60 then
lib_magic_wait_time = 60
end
return lib_magic_wait_time
end

View File

@@ -0,0 +1,86 @@
-- $Id: //depot/Projects/StarWars_Expansion/Run/Data/Scripts/Library/PGDebug.lua#1 $
--/////////////////////////////////////////////////////////////////////////////////////////////////
--
-- (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/PGDebug.lua $
--
-- Original Author: Brian Hayes
--
-- $Author: Andre_Arsenault $
--
-- $Change: 37816 $
--
-- $DateTime: 2006/02/15 15:33:33 $
--
-- $Revision: #1 $
--
--/////////////////////////////////////////////////////////////////////////////////////////////////
function DebugEventAlert(event, params)
message = tostring(Script) .. ": handled event " .. tostring(event)
function AppendParameter(ival, parameter)
message = message .. "\nParameter " .. tostring(ival) .. ": " .. tostring(parameter)
end
table.foreachi(params, AppendParameter)
MessageBox(message)
end
function MessageBox(...)
_MessagePopup(string.format(unpack(arg)))
end
function ScriptMessage(...)
_ScriptMessage(string.format(unpack(arg)))
end
function DebugMessage(...)
_ScriptMessage(string.format(unpack(arg)))
end
function OutputDebug(...)
_OuputDebug(string.format(unpack(arg)))
end
function ScriptError(...)
outstr = string.format(unpack(arg))
_OuputDebug(outstr .. "\n")
_ScriptMessage(outstr)
outstr = DumpCallStack()
_OuputDebug(outstr .. "\n")
_ScriptMessage(outstr)
ScriptExit()
end
function DebugPrintTable(unit_table)
DebugMessage("%s -- unit table contents:", tostring(Script))
for key, obj in pairs(unit_table) do
DebugMessage("%s -- \t\t** unit:%s", tostring(Script), tostring(obj))
end
end

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

View File

@@ -0,0 +1,133 @@
-- $Id: //depot/Projects/StarWars_Expansion/Run/Data/Scripts/Library/PGInterventions.lua#1 $
--/////////////////////////////////////////////////////////////////////////////////////////////////
--
-- (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/PGInterventions.lua $
--
-- Original Author: Brian Hayes
--
-- $Author: Andre_Arsenault $
--
-- $Change: 37816 $
--
-- $DateTime: 2006/02/15 15:33:33 $
--
-- $Revision: #1 $
--
--/////////////////////////////////////////////////////////////////////////////////////////////////
require("PGBaseDefinitions")
function Definitions()
TaskForce = {
{
"Intervention",
"TaskForceRequired",
"DenyHeroAttach",
},
}
StartTime = GetCurrentTime()
InterventionExclusionPeriod = 120.0
MinContrastScale = 1.1
MaxContrastScale = 1.5
PerFailureContrastAdjust = 0.1
EnemyContrastTypes = {}
FriendlyContrastTypes = {}
ContrastTypeScale = {}
if Declare_Goal_Type then
Declare_Goal_Type()
end
end
function Wait_On_Flag(flag_name, location)
while not Check_Story_Flag(PlayerObject, flag_name, location, true) do
Sleep(1)
if GetCurrentTime() - StartTime > InterventionExclusionPeriod then
Intervention.Unblock_Goal_Proposal()
end
end
end
function Begin_Intervention()
if EvaluatePerception("Are_Interventions_Allowed", PlayerObject) == 0 then
ScriptExit()
end
Intervention.Block_Goal_Proposal()
Intervention.Set_As_Goal_System_Removable(false)
end
function End_Intervention()
Intervention.Unblock_Goal_Proposal()
Sleep(GameRandom(60, 300))
ScriptExit()
end
function Select_Reward_Unit(reward_table, player, min_value)
distribution = DiscreteDistribution.Create()
for i,possible_reward in pairs(reward_table) do
if not possible_reward.Is_Obsolete(player) and possible_reward.Is_Affiliated_With(player) then
tech_difference = possible_reward.Get_Tech_Level() - player.Get_Tech_Level()
if possible_reward.Is_Build_Locked(player) then
if tech_difference == 0 then
distribution.Insert(possible_reward, 7.0)
end
else
if tech_difference <= 1 then
distribution.Insert(possible_reward, 6.0 + tech_difference)
end
end
end
end
reward = distribution.Sample()
if not reward then
return nil
end
reward_count = (min_value - 1) / reward.Get_Build_Cost() + 0.5
if reward_count < 1 then
reward_count = 1
elseif reward_count > 5 then
reward_count = 5
end
return reward, reward_count
end

View File

@@ -0,0 +1,109 @@
-- $Id: //depot/Projects/StarWars_Expansion/Run/Data/Scripts/Library/PGMoveUnits.lua#1 $
--/////////////////////////////////////////////////////////////////////////////////////////////////
--
-- (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/PGMoveUnits.lua $
--
-- Original Author: Brian Hayes
--
-- $Author: Andre_Arsenault $
--
-- $Change: 37816 $
--
-- $DateTime: 2006/02/15 15:33:33 $
--
-- $Revision: #1 $
--
--/////////////////////////////////////////////////////////////////////////////////////////////////
require("PGBaseDefinitions")
-- This will move an entire unit list with simultaneous orders.
-- They will block as a whole and pass when the last unit's move is complete.
function Formation_Move(unit_list, target)
if type(unit_list) == "table" then
Cull_Unit_List(unit_list)
for k, unit in pairs(unit_list) do -- An individual unit is needed to reach the Move_To function.
BlockOnCommand(unit.Move_To(unit_list, target)) -- Note that the unit list is passed.
return
end
DebugMessage("%s -- Formation_Move, unit_list is empty", tostring(Script))
elseif type(unit_list) == "userdata" then
BlockOnCommand(unit_list.Move_To(target))
else
DebugMessage("%s -- Formation_Move, expected table or userdata got %s", tostring(Script), tostring(unit_list))
end
end
function Formation_Attack(unit_list, target)
if type(unit_list) == "table" then
Cull_Unit_List(unit_list)
for k, unit in pairs(unit_list) do
BlockOnCommand(unit.Attack_Target(unit_list, target))
return
end
DebugMessage("%s -- Formation_Attack, unit_list is empty", tostring(Script))
elseif type(unit_list) == "userdata" then
BlockOnCommand(unit_list.Attack_Move(target))
else
DebugMessage("%s -- Formation_Attack, expected table or userdata got %s", tostring(Script), tostring(unit_list))
end
end
function Formation_Attack_Move(unit_list, target)
if type(unit_list) == "table" then
Cull_Unit_List(unit_list)
for k, unit in pairs(unit_list) do
BlockOnCommand(unit.Attack_Move(unit_list, target))
return
end
DebugMessage("%s -- Formation_Attack, unit_list is empty", tostring(Script))
elseif type(unit_list) == "userdata" then
BlockOnCommand(unit_list.Attack_Move(target))
else
DebugMessage("%s -- Formation_Attack, expected table or userdata got %s", tostring(Script), tostring(unit_list))
end
end
function Formation_Guard(unit_list, target)
if type(unit_list) == "table" then
Cull_Unit_List(unit_list)
for k, unit in pairs(unit_list) do
BlockOnCommand(unit.Guard_Target(unit_list, target))
return
end
DebugMessage("%s -- Formation_Guard, unit_list is empty", tostring(Script))
elseif type(unit_list) == "userdata" then
BlockOnCommand(unit_list.Guard_Target(target))
else
DebugMessage("%s -- Formation_Guard, expected table or userdata got %s", tostring(Script), tostring(unit_list))
end
end

View File

@@ -0,0 +1,162 @@
-- $Id: //depot/Projects/StarWars_Expansion/Run/Data/Scripts/Library/PGSpawnUnits.lua#1 $
--/////////////////////////////////////////////////////////////////////////////////////////////////
--
-- (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/PGSpawnUnits.lua $
--
-- Original Author: Brian Hayes
--
-- $Author: Andre_Arsenault $
--
-- $Change: 37816 $
--
-- $DateTime: 2006/02/15 15:33:33 $
--
-- $Revision: #1 $
--
--/////////////////////////////////////////////////////////////////////////////////////////////////
require("PGBaseDefinitions")
function Process_Reinforcements()
for index, btable in ipairs(block_table) do
for k, block in pairs(btable) do
if not block.block then
--Haven't yet issued the reinforcement command, or else a previous attempt failed
block.block = Reinforce_Unit(block.ref_type, block.entry_marker, block.player, true, block.obey_zones)
elseif block.block.IsFinished() then
new_units = block.block.Result()
if type(new_units) == "table" then
for j, unit in pairs(new_units) do
DebugMessage("%s -- Process_Reinforcements Block: %s, unit: %s, allow:%s, delete:%s", tostring(Script), tostring(block.block), tostring(unit), tostring(block.allow_ai_usage), tostring(block.delete_after_scenario))
if block.allow_ai_usage then
--MessageBox("allow_ai_usage: %s", tostring(unit))
unit.Prevent_AI_Usage(false)
end
if block.delete_after_scenario then
--MessageBox("deleting after scenario: %s", tostring(unit))
unit.Mark_Parent_Mode_Object_For_Death()
end
table.insert(block.block_track.unit_list, unit)
end
block.block_track.type_count = block.block_track.type_count - 1
if block.block_track.type_count <= 0 then
if type(block.callback) == "function" then
block.callback(block.block_track.unit_list)
end
table.remove(block_table, index)
Process_Reinforcements()
return
end
end
block_table[index][k] = nil
Process_Reinforcements()
return
end
end
end
new_units = nil
end
function Add_Reinforcement(object_type, player)
if type(object_type) == "string" then
object_type = Find_Object_Type(object_type)
end
Reinforce_Unit(object_type, false, player, true, false)
end
-- Reinforce units via transport, simultaneously.
function ReinforceList(type_list, entry_marker, player, allow_ai_usage, delete_after_scenario, ignore_reinforcement_rules, callback)
if type(ignore_reinforcement_rules) == "function" then
MessageBox("Received a function for 6th parameter; expected bool. Note the signature change, sorry.")
return
end
if player == nil then
MessageBox("expected a player for 3rd parameter; aborting")
return
end
table.insert(block_table, {})
index = table.getn(block_table)
block_track = {
type_count = table.getn(type_list),
unit_list = {}
}
for k, unit_type in pairs(type_list) do
ref_type = Find_Object_Type(unit_type)
btab = {
block = nil,
block_track = block_track,
ref_type = ref_type,
entry_marker = entry_marker,
player = player,
obey_zones = not ignore_reinforcement_rules,
allow_ai_usage = allow_ai_usage,
callback = callback,
delete_after_scenario = delete_after_scenario
}
table.insert(block_table[index], btab)
btab = nil
ref_type = nil
end
end
-- Spawn units simultaneously.
function SpawnList(type_list, entry_marker, player, allow_ai_usage, delete_after_scenario)
unit_list = {}
for k, unit_type in pairs(type_list) do
ref_type = Find_Object_Type(unit_type)
new_units= Spawn_Unit(ref_type, entry_marker, player)
for j, unit in pairs(new_units) do
table.insert(unit_list, unit)
if allow_ai_usage then
--MessageBox("allow_ai_usage: %s", tostring(unit))
unit.Prevent_AI_Usage(false)
else
unit.Prevent_AI_Usage(true) -- This doesn't happen automatically, unlike for Reinforce_Unit
end
if delete_after_scenario then
--MessageBox("deleting after scenario: %s", tostring(unit))
unit.Mark_Parent_Mode_Object_For_Death()
end
end
end
new_units = nil
return unit_list
end

View File

@@ -0,0 +1,197 @@
-- $Id: //depot/Projects/StarWars_Expansion/Run/Data/Scripts/Library/PGStateMachine.lua#1 $
--/////////////////////////////////////////////////////////////////////////////////////////////////
--
-- (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/PGStateMachine.lua $
--
-- Original Author: Brian Hayes
--
-- $Author: Andre_Arsenault $
--
-- $Change: 37816 $
--
-- $DateTime: 2006/02/15 15:33:33 $
--
-- $Revision: #1 $
--
--/////////////////////////////////////////////////////////////////////////////////////////////////
require("pgcommands")
--
-- Define_State -- Define a new state in the state machine table.
--
-- @param state This is the tag used to identify the state. Usually
-- a text value or a number
-- @param function_value This is the function value that will process
-- all the messages associated with the given state.
-- @since 4/22/2005 7:26:01 PM -- BMH
--
function Define_State(state, function_value)
local curproc = StateMachine[state]
if curproc == nil then
StateMachineIndexes[DefineStateIndex] = state
StateMachineIndexLookup[state] = DefineStateIndex
DefineStateIndex = DefineStateIndex + 1
end
StateMachine[state] = function_value
if NextState == nil then
NextState = state
end
end
--
-- Advance_State -- Advance to the next state based on the
-- order of state definition
--
-- @since 4/22/2005 7:26:01 PM -- BMH
--
function Advance_State()
NextState = StateMachineIndexes[CurrentStateIndex + 1]
end
--
-- Set_Next_State -- Set the next state to transition to.
--
-- @param state tag specifying the state to transition to.
-- @since 4/22/2005 7:26:01 PM -- BMH
--
function Set_Next_State(state)
if state == nil or StateMachine[state] ~= nil then
NextState = state
end
end
--
-- Get_Current_State -- Returns what the current state is.
--
-- @return object detailing what the current state is.
-- @since 4/22/2005 7:12:14 PM -- BMH
--
function Get_Current_State()
return CurrentState
end
--
-- Get_Next_State -- Returns what the next state will be.
--
-- @return object detailing what the next state will be.
-- @since 4/22/2005 7:12:14 PM -- BMH
--
function Get_Next_State()
return NextState
end
--
-- Process_States -- This function is called to advance the State Machine through it's states
--
-- @since 4/22/2005 7:12:14 PM -- BMH
--
function Process_States()
while NextState ~= nil do
_curproc = StateMachine[NextState]
if type(_curproc) == "function" then
CurrentState = NextState
CurrentStateIndex = StateMachineIndexLookup[CurrentState]
_curproc(OnEnter)
while CurrentState == NextState do
_curproc(OnUpdate)
if CurrentState == NextState then
PumpEvents()
end
end
_curproc(OnExit)
DebugMessage("%s -- Advancing state from %s to %s.", tostring(Script), tostring(CurrentState), tostring(NextState))
else
ScriptError("%s -- Invalid State: %s, Function: %s", tostring(Script), tostring(NextState), tostring(_curproc))
NextState = nil
end
end
end
--
-- Base_Definitions -- This function is called once when the script is first created.
--
-- @since 4/22/2005 6:04:55 PM -- BMH
--
function Base_Definitions()
DebugMessage("%s -- In Base_Definitions", tostring(Script))
Common_Base_Definitions()
StateMachine = {}
StateMachineIndexes = {}
StateMachineIndexLookup = {}
OnEnter = 1
OnUpdate = 2
OnExit = 3
CurrentStateIndex = 1
DefineStateIndex = 1
NextState = nil
CurrentState = nil
_curproc = nil
StoryModeEvents = nil
-- This controls how often the script is serviced.
-- So try to process 5 times a second
ServiceRate = 0.2
if Definitions then
Definitions()
end
if PG_Story_Mode_Init then
PG_Story_Mode_Init()
end
end
--
-- main -- This is the main thread function for this script.
-- Upon return from this function the script will finish and be
-- destroyed by the system.
--
-- @since 4/22/2005 6:04:55 PM -- BMH
--
function main()
-- Enter your list of commands to execute here...
Process_States()
DebugMessage("%s -- Exiting.", tostring(Script))
-- ScriptExit will end the script no matter what state it's in.
ScriptExit()
end

View File

@@ -0,0 +1,92 @@
-- $Id: //depot/Projects/StarWars_Expansion/Run/Data/Scripts/Library/PGStoryMode.lua#1 $
--/////////////////////////////////////////////////////////////////////////////////////////////////
--
-- (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/PGStoryMode.lua $
--
-- Original Author: Brian Hayes
--
-- $Author: Andre_Arsenault $
--
-- $Change: 37816 $
--
-- $DateTime: 2006/02/15 15:33:33 $
--
-- $Revision: #1 $
--
--/////////////////////////////////////////////////////////////////////////////////////////////////
require("PGStateMachine")
require("PGSpawnUnits")
require("PGMoveUnits")
-- Story mode scripts shouldn't pool themselves.
ScriptPoolCount = 0
function PG_Story_Mode_Init()
Define_State("PG_Story_State_Init", PG_Story_State_Init);
if StoryModeEvents ~= nil then
for key,value in pairs(StoryModeEvents) do
if type(value) == "function" then
Define_State(key, value)
else
MessageBox("%s--Invalid function object for Storyevent: %s, got a \"%s\" instead.", tostring(Script), tostring(key), type(value))
end
end
end
end
function Story_Event_Trigger(name)
if StoryModeEvents == nil then
return
end
--MessageBox("%s--In Story_Event_Trigger: %s", tostring(Script), name)
local event = StoryModeEvents[name]
if event ~= nil then
if type(event) == "function" then
if Get_Current_State() == Get_Next_State() then
--MessageBox("%s--Setting next state %s", tostring(Script), name)
Set_Next_State(name)
end
end
end
end
function PG_Story_State_Init(message)
if message == OnEnter then
DebugMessage("%s -- PG_Story_State_Init(OnEnter)", tostring(Script))
elseif message == OnUpdate then
elseif message == OnExit then
end
end

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