Files
ORA-D2K-Map-Patto-Build-Mor…/scripts_new.lua
2024-06-12 22:20:51 +01:00

990 lines
32 KiB
Lua

BotPlayers = {}
IsAnyBotsHere = false
CurrentConyards = {}
CheckPlayerTechtree = false
ActivePlayers = {}
PlayersThatNotchoosedyet = 0 --Numbver of players that didnt choose any subfaction yet
FactionsMode = 0 -- default Faction mode: vannila
ExtendedStarport = 0
local CallAirstrike -- must be local fuction. otherwise it crash when multiple AirStrikes are called at ones.
ActorRegister={}
--Airstrike variables
SquadSpawnDelay = 0 -- Spawn delay betwwen every Aircraft. Use when Useoffest is false, else 0
SpawnWposOffsets = {-1256, 0, 1256} -- offset for each aircraft
Useoffest = true -- if false Air sqad will span in line. !!! If false SquadSpamDelay must be least 5 !!!!
ReinforcementSquads = {
{"light_inf.vet4","light_inf.vet3","light_inf.vet3","trooper.vet2","trooper.vet2"},
{"light_inf.vet3", "light_inf.vet3", "trooper.vet2", "trooper.vet2", "trooper.vet2"},
{"trooper.heavy","trooper.heavy","trooper.heavy", "officer", "trooper.heavy", "mpsardaukar", "mpsardaukar"},
{"trooper.heavy","trooper.heavy","trooper.heavy", "officer", "trooper.heavy", "fremen_fedaykin", "fremen_fedaykin"},
{"trooper.heavy","trooper.heavy","trooper.heavy", "officer", "trooper.heavy", "mortar_inf", "mortar_inf", "mortar_inf"},
{"mercenary","mercenary","mercenary","mercenary","mercenary"}
}
--different Squads for different Factons 1.Atreides, 2. Ordos 3. Harkonnen
AirSquads = {
{"ornithopter_a","ornithopter_a", "ornithopter_a"},
{"ornithopter_a","ornithopter_a"},
{"ornithopter_o", "ornithopter_o", "ornithopter_o"}
}
DropActor = {"carryall.reinforce_with_sound", "carryall.reinforce_with_sound", "frigate.harkonnen_cargo", "frigate.atreides_cargo", "frigate.ordos_cargo"}
SubfactionPrerequisitesList = {}
SubfactionPrerequisitesList["atreides"] = "subfaction.atreides"
SubfactionPrerequisitesList["fremen"] = "subfaction.fremen"
SubfactionPrerequisitesList["harkonnen"] = "subfaction.harkonnen"
SubfactionPrerequisitesList["corrino"] = "subfaction.corrino"
SubfactionPrerequisitesList["ordos"] = "subfaction.ordos"
SubfactionPrerequisitesList["smuggler"] = "subfaction.smuggler"
SubfactionPrerequisitesList["mercenary"] = "subfaction.mercenary"
Mergedsubfactions = { "merged.fremen","merged.corrino","merged.smuggler", "merged.mercenary"}
-- Experimental Starport variables - limited to 24 players
FrigateDeliveryDelay = 1500 --how much time to wait until frigate arrives
FrigateCapacity = 5 -- must be defined as n -1
-- must be set as: n - 1
StarportUnits = {}
StarportUnits["Multi0"] = {}
StarportUnits["Multi1"] = {}
StarportUnits["Multi2"] = {}
StarportUnits["Multi3"] = {}
StarportUnits["Multi4"] = {}
StarportUnits["Multi5"] = {}
StarportUnits["Multi6"] = {}
StarportUnits["Multi7"] = {}
StarportUnits["Multi8"] = {}
StarportUnits["Multi9"] = {}
StarportUnits["Multi10"] = {}
StarportUnits["Multi11"] = {}
StarportUnits["Multi12"] = {}
StarportUnits["Multi13"] = {}
StarportUnits["Multi14"] = {}
StarportUnits["Multi15"] = {}
StarportUnits["Multi16"] = {}
StarportUnits["Multi17"] = {}
StarportUnits["Multi18"] = {}
StarportUnits["Multi19"] = {}
StarportUnits["Multi20"] = {}
StarportUnits["Multi21"] = {}
StarportUnits["Multi22"] = {}
StarportUnits["Multi23"] = {}
RevokeTokens = {} --isFull and notEmpty revoke tokens
RevokeTokens["Multi0"] = {}
RevokeTokens["Multi1"] = {}
RevokeTokens["Multi2"] = {}
RevokeTokens["Multi3"] = {}
RevokeTokens["Multi4"] = {}
RevokeTokens["Multi5"] = {}
RevokeTokens["Multi6"] = {}
RevokeTokens["Multi7"] = {}
RevokeTokens["Multi8"] = {}
RevokeTokens["Multi9"] = {}
RevokeTokens["Multi10"] = {}
RevokeTokens["Multi11"] = {}
RevokeTokens["Multi12"] = {}
RevokeTokens["Multi13"] = {}
RevokeTokens["Multi14"] = {}
RevokeTokens["Multi15"] = {}
RevokeTokens["Multi16"] = {}
RevokeTokens["Multi17"] = {}
RevokeTokens["Multi18"] = {}
RevokeTokens["Multi19"] = {}
RevokeTokens["Multi20"] = {}
RevokeTokens["Multi21"] = {}
RevokeTokens["Multi22"] = {}
RevokeTokens["Multi23"] = {}
DummyActors = {} -- used for icon overiddes
DummyActors["Multi0"] = {}
DummyActors["Multi1"] = {}
DummyActors["Multi2"] = {}
DummyActors["Multi3"] = {}
DummyActors["Multi4"] = {}
DummyActors["Multi5"] = {}
DummyActors["Multi6"] = {}
DummyActors["Multi7"] = {}
DummyActors["Multi8"] = {}
DummyActors["Multi9"] = {}
DummyActors["Multi10"] = {}
DummyActors["Multi11"] = {}
DummyActors["Multi12"] = {}
DummyActors["Multi13"] = {}
DummyActors["Multi14"] = {}
DummyActors["Multi15"] = {}
DummyActors["Multi16"] = {}
DummyActors["Multi17"] = {}
DummyActors["Multi18"] = {}
DummyActors["Multi19"] = {}
DummyActors["Multi20"] = {}
DummyActors["Multi21"] = {}
DummyActors["Multi22"] = {}
DummyActors["Multi23"] = {}
RepairPadList = {} -- repairpad owned by Bots
WorldLoaded = function()
FrigateCapacity = tonumber(Map.LobbyOption("extendedStarport")) - 1
--get players
mp0=Player.GetPlayer("Multi0")
mp1=Player.GetPlayer("Multi1")
mp2=Player.GetPlayer("Multi2")
mp3=Player.GetPlayer("Multi3")
mp4=Player.GetPlayer("Multi4")
mp5=Player.GetPlayer("Multi5")
mp6=Player.GetPlayer("Multi6")
mp7=Player.GetPlayer("Multi7")
mp8=Player.GetPlayer("Multi8")
mp9=Player.GetPlayer("Multi9")
mp10=Player.GetPlayer("Multi10")
mp11=Player.GetPlayer("Multi11")
mp12=Player.GetPlayer("Multi12")
mp13=Player.GetPlayer("Multi13")
mp14=Player.GetPlayer("Multi14")
mp15=Player.GetPlayer("Multi15")
mp16=Player.GetPlayer("Multi16")
mp17=Player.GetPlayer("Multi17")
mp18=Player.GetPlayer("Multi18")
mp19=Player.GetPlayer("Multi19")
mp20=Player.GetPlayer("Multi20")
mp21=Player.GetPlayer("Multi21")
mp22=Player.GetPlayer("Multi22")
mp23=Player.GetPlayer("Multi23")
mp24=Player.GetPlayer("Multi24")
mp25=Player.GetPlayer("Multi25")
mp26=Player.GetPlayer("Multi26")
mp27=Player.GetPlayer("Multi27")
Players = {mp0, mp1, mp2, mp3, mp4, mp5, mp6, mp7, mp8, mp9, mp10, mp11, mp12, mp13, mp14, mp15, mp16, mp17, mp18, mp19, mp20, mp21, mp22, mp23, mp24, mp25, mp26, mp27}
FactionsMode = tonumber(Map.LobbyOption("fation_mode"))
if (FactionsMode == 0) then
--Media.DisplayMessage("you play with standart d2k mode", "Mentat", HSLColor.DarkRed)
end
if (FactionsMode == 1) then
Media.DisplayMessage("Sub-faction Mode - Choose between Major faction or one of its sub-factions", "Mentat", HSLColor.DarkRed)
end
if (FactionsMode == 2) then
Media.DisplayMessage("Merge Faction mode - chosen subfaction will be merged in to your Major faction","Mentat", HSLColor.DarkRed)
end
for i, player in pairs(Players)
do
-- freecarryall
if player.HasPrerequisites({"FreeCarry"})
then
addCarryToPlayer(player)
end
-- factions option check
if (FactionsMode == 0)
then
player.GrantCondition("vanilla_factions_Only")
addmcv(player)
elseif (FactionsMode == 1) then
CheckPlayerTechtree = true
player.GrantCondition("subfactions")
botsubfaction(player)
elseif (FactionsMode == 2) then
player.GrantCondition("mergedsubfactions")
botsubfaction(player)
CheckPlayerTechtree = true
end
--adding bots to table
if player.IsBot then
table.insert(BotPlayers, player)
end
if not player.IsNonCombatant then
table.insert(ActivePlayers, player)
end
end
-- worm delay
local wormDelay = Map.LobbyOption("WormsSpawnDelay")
if tonumber(wormDelay) > 0
then
local delay = tonumber(Map.LobbyOption("WormsSpawnDelay"))
Trigger.AfterDelay(DateTime.Minutes(delay), function()
--in teory any player can own wormspawner actor
wormSpawnFunction(Player.GetPlayer("Creeps"))
wormSpawnFunction(Player.GetPlayer("Neutral"))
for i, player in pairs(Players)
do
wormSpawnFunction(player)
end
end)
end
-- Scripts for BOTS
for i, bot in pairs(BotPlayers)
do
IsAnyBotsHere = true
FindSaboteur(bot)
end
--Production trriggers - Starport, AI Engi, AI Repairing
Trigger.OnAnyProduction( function(producer, produced, productionQueue)
local actor = produced.Type
if productionQueue == "Starport" then
if actor == "purchase.starport" then
CHOAMDelivery(produced.Owner)
-- Mercenary support power
elseif actor == "dummy_mercenary_spawnpoint" then
CHOAMDeliverCustomUnits(producer.Owner, ReinforcementSquads[4])
produced.Destroy()
elseif actor=="dummy.trike" or actor=="dummy.quad" or actor=="dummy.harvester" or actor=="dummy.mcv" or actor=="dummy.hunter" or actor=="dummy.bombardment_tank" or actor=="dummy.combat_tank_a" or actor=="dummy.combat_tank_o" or actor=="dummy.combat_tank_h" or actor=="dummy.siege_tank" or actor=="dummy.missile_tank" or actor=="dummy.carryall" or actor=="dummy.combat_tank_cheap"or actor=="dummy.combat_tank_corrino" then
ExperimentalStarport(producer.Owner, produced)
end
end
if produced.Owner.IsBot then
if actor == "engineer" then
EnginnerLogic(produced)
end
if productionQueue == "Armor" or productionQueue== "Vehicle" then
CheckForRepair(produced, produced.MaxHealth, produced.Owner.InternalName)
end
end
end)
end
function addCarryToPlayer(player)
local actors = player.GetActorsByTypes({"mcv", "construction_yard", "choosefaction"})
for i, actor in pairs(actors) do
if (actor.Type == "mcv") or (actor.Type == "construction_yard") or (actor.Type == "choosefaction") then
Reinforcements.Reinforce(player, { "carryall" }, { actor.Owner.HomeLocation}, 20)
return
end
end
end
function wormSpawnFunction(owner)
local actorsSpawner = owner.GetActorsByType("wormspawner")
if actorsSpawner ~= nil
then
for i, spawner in pairs(actorsSpawner)
do
if spawner.AcceptsCondition("WormSpamDelayed")
then
spawner.GrantCondition("WormSpamDelayed")
end
end
end
end
Tick = function()
--everything execute's one's per 2 second, because preformance :( - will case lags
if DateTime.GameTime % DateTime.Seconds(2) == 0 then
local New_actors = ActorsAddedToWorld(Map.ActorsInWorld, ActorRegister)
for _,actor in pairs(New_actors) do
local actType = actor.Type --less expensive that act.Type
-- Air support powers
if actType == "waypoint.airtstrike_a" then
CallAirstrike(actor)
end
if actType == "waypoint.airtstrike_o" then
CallAirstrike(actor)
end
if actType == "waypoint.reinforce_h" or actType == "waypoint.reinforce_o" then
DropAirReinforcements(actor)
end
if actType == "waypoint.reinforce_or" or actType == "waypoint.reinforce_or" then
DropAirReinforcements(actor)
end
if actType == "waypoint.reinforce_at" or actType == "waypoint.reinforce_at" then
DropAirReinforcements(actor)
end
if actType == "repair_pad.bot"then
RepairPadList[actor.Owner.InternalName] = actor
end
end
end
-- Bot engi protection scripts: executed ones per 2 sec.
if IsAnyBotsHere then
if DateTime.GameTime % DateTime.Seconds(2) == 0 then
findConyards()
engiProtection()
end
end
-- check if player already choose subfaction
if(CheckPlayerTechtree == true and PlayersThatNotchoosedyet > 0) then
-- Media.DisplayMessage("cheking")
techtreecheck()
end
end
-------------------------
--FactionsModes Scripts--
-------------------------
function addmcv(player)
local actors = player.GetActorsByType("choosefaction")
for pom, actor in pairs(actors) do
Actor.Create("mcv", true, { Owner = player, Facing = Angle.SouthWest, Location = actor.Location})
actor.Kill();
end
end
function techtreecheck()
for i, player in pairs(Players) do
local actors = player.GetActorsByType("choosefaction")
if FactionsMode == 1 then
for faction, prerequisite in pairs(SubfactionPrerequisitesList) do
if player.HasPrerequisites({prerequisite}) then
for pom, actor in pairs(actors) do
Actor.Create("mcv", true, { Owner = player, Facing = Angle.North, Location = actor.Location, Faction = faction})
actor.Kill();
PlayersThatNotchoosedyet = PlayersThatNotchoosedyet - 1
--Media.DisplayMessage("Subfaction choosed", tostring(PlayersThatNotchoosedyet))
end
end
end
elseif FactionsMode == 2 then
for faction, prerequisite in pairs(Mergedsubfactions) do
if player.HasPrerequisites({prerequisite}) then
for pom, actor in pairs(actors) do
Actor.Create("mcv", true, { Owner = player, Facing = Angle.North, Location = actor.Location, Faction = player.Faction})
actor.Kill();
PlayersThatNotchoosedyet = PlayersThatNotchoosedyet - 1
--Media.DisplayMessage("Subfaction choosed Remaining"..tostring(PlayersThatNotchoosedyet))
end
end
end
end
end
end
function botsubfaction(player)
if(not player.IsBot)
then
PlayersThatNotchoosedyet = PlayersThatNotchoosedyet + 1
--Media.DisplayMessage("got the player",tostring(PlayersThatNotchoosedyet) )
else
local bluefactions = {"atreides", "fremen"}
local redfactions = {"harkonnen", "corrino"}
local greenfactions = {"ordos", "smuggler", "mercenary"}
local faction = {}
local actors = player.GetActorsByType("choosefaction")
if (FactionsMode == 1) then
if player.Faction == "atreides" then
faction = bluefactions
end
if player.Faction == "harkonnen" then
faction = redfactions
end
if player.Faction == "ordos" then
faction = greenfactions
end
--Media.DisplayMessage("got the bot")
for pom, actor in pairs(actors) do
Actor.Create("mcv", true, { Owner = player, Facing = Angle.North, Location = actor.Location, Faction = Utils.Random(faction)})
actor.Kill();
end
else
faction = player.Faction
for pom, actor in pairs(actors) do
Actor.Create("mcv", true, { Owner = player, Facing = Angle.North, Location = actor.Location, Faction = player.Faction})
Actor.Create( Utils.Random(Mergedsubfactions), true, { Owner = player, Facing = Angle.North, Location = actor.Location, Faction = player.Faction})
actor.Kill();
end
end
end
end
-----------------------------------
---AI protection against engineer--
-----------------------------------
function engiProtection()
for i, conyard in pairs(CurrentConyards) do
if conyard.IsDead then
--Media.DisplayMessage("conyard dead")
else
actorsInRadius = Map.ActorsInCircle(conyard.CenterPosition, WDist.New(3036))
local owner = conyard.Owner
for _, actor in pairs(actorsInRadius) do
if actor.Type == "engineer" and not owner.IsAlliedWith(actor.Owner) then
--Media.DisplayMessage(actor.Type)
conyard.Sell()
--CurrentConyards[i] = nil
end
end
end
end
end
function findConyards()
local newConyards = {}
for i, bot in pairs(BotPlayers)
do
local conyards = bot.GetActorsByType("construction_yard")
for _, conyard in pairs(conyards) do
table.insert(newConyards, conyard)
end
end
CurrentConyards = newConyards
end
-----------------------------
---AI scripts--engi/Saboteur/repairing
-----------------------------
function CheckForRepair(actor, maxHP, internalName)
Trigger.AfterDelay(300, function()
if not actor.IsDead then
if maxHP * 0.4 > actor.Health then
if RepairPadList[internalName] ~= nil then
if not RepairPadList[internalName].IsDead then
local token = actor.GrantCondition("reject_control", 3000) -- if unit stuck, expire after 3000 ticks
--Media.Debug("send to repair_pad "..tostring(actor))
actor.Stop()
actor.Move(RepairPadList[internalName].Location + CVec.New(1,1), 2)
actor.CallFunc(function ()
if not actor.IsDead then
actor.RevokeCondition(token)
CheckForRepair(actor, maxHP, internalName)
end
end)
end
else
CheckForRepair(actor, maxHP, internalName)
end
else
CheckForRepair(actor, maxHP, internalName)
end
end
end)
end
EnginnerLogic = function(enginner)
if enginner.HasTag("close_target") == false then
local closeActors = Map.ActorsInCircle(enginner.CenterPosition, WDist.FromCells(15))
local targets = Utils.Where(closeActors, function(actor)
return
actor.HasProperty("Capture") and
actor.Type ~= "wall" and
actor.Type ~= "medium_gun_turret" and
actor.Type ~= "large_gun_turret" and
actor.Type ~= "engineer" and
actor.Type ~= "silo" and not
enginner.Owner.IsAlliedWith(actor.Owner)
end)
if targets[1] ~= nil then
local token = enginner.GrantCondition("reject_control")
enginner.Stop()
local target = Utils.Random(targets)
enginner.Capture(target)
enginner.AddTag("close_target")
--Media.Debug("redirection to close target"..tostring(enginner))
enginner.CallFunc( function ()
if enginner.IsDead == false then
--Media.Debug("cancel, target destroyed"..tostring(enginner))
enginner.RevokeCondition(token)
enginner.RemoveTag("close_target")
end
end)
end
end
Trigger.AfterDelay(500, function()
if enginner.IsDead == false then
EnginnerLogic(enginner)
end
end)
end
FindCloseTarget = function (saboteur, distance)
local closeActors = Map.ActorsInCircle(saboteur.CenterPosition, WDist.FromCells(distance))
return Utils.Where(closeActors, function(actor)
return
actor.HasProperty("Sell") and
actor.Type ~= "wall" and
actor.Type ~= "medium_gun_turret" and
actor.Type ~= "large_gun_turret" and
actor.Type ~= "silo" and not
saboteur.Owner.IsAlliedWith(actor.Owner) and not
actor.Owner.IsNonCombatant
end)
end
FindAnyTarget = function (saboteur)
local filteredPlayers = FilterPlayers(saboteur.Owner)
if filteredPlayers[1] == nil then
-- no suitable players for targeting
return nil
end
local randomplayer = Utils.Random(filteredPlayers)
if randomplayer ~= nil then
local suitableActors = Utils.Where(randomplayer.GetActors(), function(actor)
return
actor.HasProperty("Sell") and
actor.Type ~= "wall" and
actor.Type ~= "medium_gun_turret" and
actor.Type ~= "large_gun_turret" and
actor.Type ~= "silo"
end)
if (next(suitableActors) ~= nil) then
return suitableActors
else
-- case when random player is dead or have no buildings
return nil
end
else
-- case when no suitable players found
return nil
end
end
FindSaboteur = function(bot)
local saboteurs = bot.GetActorsByType("saboteur")
for i, saboteur in pairs(saboteurs) do
if saboteur.HasTag("close_target") == false and saboteur.HasTag("random_target") == false then
local targets = FindCloseTarget(saboteur, 15)
if (next(targets) ~= nil) then
saboteur.AddTag("close_target")
SendSaboteur(saboteur, targets)
else
targets = FindAnyTarget(saboteur)
if targets ~= nil then
saboteur.AddTag("random_target")
SendSaboteur(saboteur, targets)
end
end
elseif not saboteur.HasTag("close_target") and saboteur.HasTag("random_target") then
local targets = FindCloseTarget(saboteur, 15)
if (next(targets) ~= nil) then
saboteur.AddTag("close_target")
SendSaboteur(saboteur, targets)
end
end
end
Trigger.AfterDelay(400, function ()
FindSaboteur(bot) end)
end
SendSaboteur = function(saboteur, targets)
if targets == nil then
--Media.Debug("no targets for", saboteur.Owner.Name)
saboteur.RemoveTag("close_target")
saboteur.RemoveTag("random_target")
return
end
saboteur.Stop()
local target = Utils.Random(targets)
saboteur.Demolish(target)
-- 'target' was removed from the world in the meantime
saboteur.CallFunc(function()
saboteur.RemoveTag("close_target")
saboteur.RemoveTag("random_target")
end)
end
function FilterPlayers(forPlayer)
local filteredPlayers = ActivePlayers
for i, player in pairs(filteredPlayers) do
if forPlayer.IsAlliedWith(player) or forPlayer.InternalName == player.InternalName then
table.remove(filteredPlayers, i)
end
end
return filteredPlayers
end
------------------------------------------------------------
--Experimental starport---Original D2k Starport behaviour---
------------------------------------------------------------
function ExperimentalStarport(player, dummy)
local playerInternalName = player.InternalName
local unit = dummy.Type
local cutDummyFromString = unit:sub(7, #unit)
-- Icons number Overlays
table.insert(DummyActors[playerInternalName], dummy)
if #DummyActors[playerInternalName] > FrigateCapacity + 1 then
--Media.Debug("Index above Fridate capacity, unit rejected "..playerInternalName)
return
end
dummy.GrantCondition("order_"..tostring(#DummyActors[playerInternalName]))
-- remove not needed number in icon
for i, dummyActor in pairs(DummyActors[playerInternalName]) do
if dummyActor.Type == unit and i < #DummyActors[playerInternalName] then
dummyActor.RevokeCondition(1)
end
end
if not player.HasPrerequisites({"frigate.not_empty"}) then
local token = player.GrantCondition("frigate_not_empty")
table.insert(RevokeTokens[playerInternalName], token)
end
-- add unit to the Shopping list
if StarportUnits[playerInternalName] == nil then
table.insert(StarportUnits[playerInternalName], cutDummyFromString)
elseif #StarportUnits[playerInternalName] < FrigateCapacity then
table.insert(StarportUnits[playerInternalName], cutDummyFromString)
elseif #StarportUnits[playerInternalName] == FrigateCapacity then
table.insert(StarportUnits[playerInternalName], cutDummyFromString)
local token = player.GrantCondition("frigate_full")
table.insert(RevokeTokens[playerInternalName], token)
--for i, name in pairs(StarportUnits[playerInternalName]) do
-- Media.Debug(name.." shoping list")
--end
else
Media.Debug("Frigate full - unit rejected"..player.Name)
local token = player.GrantCondition("frigate_full")
table.insert(RevokeTokens[playerInternalName], token)
end
end
function SelectStarport(player)
local chosenStarport
for i, starport in pairs(player.GetActorsByTypes({"starport","merged.starport","merged.starport_smuggler"})) do
if not starport.IsDead then
if starport.IsPrimaryBuilding then
return starport
else
chosenStarport = starport
end
end
end
return chosenStarport
end
function CHOAMDelivery(player)
DeliveryNotifications(player)
Trigger.AfterDelay(FrigateDeliveryDelay, function ()
--Media.Debug("starting delivery process")
local starport = SelectStarport(player)
if starport == nil then
--Media.Debug("Error, cant find any starport. Starport reset"..player.Name)
ResetStartport(player)
return
end
local rallypoint = starport.RallyPoint
local path = {Map.ClosestEdgeCell(starport.Location),starport.Location + CVec.New(1,1)}
local airUnits = FilterAirUnits(player.InternalName)
--wait for Choam to come
local units = Reinforcements.ReinforceWithTransport(player,"frigate_choam",StarportUnits[player.InternalName], path,{path[2], path[1]})
local frigate = units[1]
Reinforcements.Reinforce(player, airUnits,path)
-- when killed or deliver finish remove Frigade and reset Starport settings
Trigger.OnRemovedFromWorld(starport, function()
--Media.Debug("Starport removed redirecting order "..frigate.Type)
local starport_new = SelectStarport(player)
if starport_new == nil then
if not frigate.IsDead then
--Media.Debug("no more starports, canceling order"..player.Name)
frigate.Stop()
frigate.Move(path[1])
end
else
-- Media.Debug("Starport removed redirecting order "..frigate.Type)
if not frigate.IsDead then
frigate.Stop()
rallypoint = starport_new.RallyPoint
frigate.Move(starport_new.Location + CVec.New(1,1))
frigate.UnloadPassengers()
else
Media.Debug("Cant redirect, frigate is dead"..player.Name)
end
end
end)
-- when killed or deliver finish. Remove Frigade and reset Starport settings
Trigger.OnRemovedFromWorld(frigate, function()
ResetStartport(player)
if not starport.IsDead then
Trigger.ClearAll(starport)
end
end)
--in case frigate stuck
Trigger.OnIdle(frigate, function()
frigate.UnloadPassengers()
end)
Trigger.OnPassengerExited(frigate,
function(carry, pass)
Media.PlaySpeechNotification(carry.Owner,"Reinforce")
if pass ~= nil then
-- triggered when actor is in the world (dont use OnAddedToWorld triger!!!)
Trigger.AfterDelay(10, function()
if pass.HasProperty("AttackMove") then
pass.AttackMove(rallypoint,1)
elseif pass.HasProperty("FindResources") then
pass.Move(rallypoint)
pass.FindResources()
else
pass.Move(rallypoint)
end
end)
end
end)
end)
end
function ResetStartport(player)
local playerInternalName = player.InternalName
if RevokeTokens[playerInternalName][1] ~= nil then
player.RevokeCondition(RevokeTokens[player.InternalName][1])
RevokeTokens[playerInternalName][1] = nil
end
if RevokeTokens[playerInternalName][2] ~= nil then
player.RevokeCondition(RevokeTokens[player.InternalName][2])
RevokeTokens[playerInternalName][1] = nil
end
for i, dummy in pairs(DummyActors[playerInternalName]) do
--edge case check. when player surrender while delivery is in progress
if not dummy.IsDead then
dummy.Destroy()
end
end
DummyActors[playerInternalName] = {}
RevokeTokens[playerInternalName] = {}
StarportUnits[playerInternalName] = {}
local purchaseActors = player.GetActorsByType("purchase.starport")
if purchaseActors[1] ~= nil then
purchaseActors[1].Destroy()
end
end
function FilterAirUnits(playerInternalName)
local airUnits = {}
for i,unit in pairs(StarportUnits[playerInternalName]) do
if unit == "carryall" then
--Media.Debug("removing carryall")
StarportUnits[playerInternalName][i] = nil
table.insert(airUnits, "carryall")
end
end
return airUnits
end
function DeliveryNotifications(player)
Media.PlaySpeechNotification(player,"OrderPlaced")
local time = 0
local timeBetweenNotifications = FrigateDeliveryDelay / 5
time = time + timeBetweenNotifications
Trigger.AfterDelay(time -15, function()
Media.PlaySpeechNotification(player,"TMinusFive")
end)
time = time + timeBetweenNotifications
Trigger.AfterDelay(time, function()
Media.PlaySpeechNotification(player,"TMinusFour")
end)
time = time + timeBetweenNotifications
Trigger.AfterDelay(time, function()
Media.PlaySpeechNotification(player,"TMinusThree")
end)
time = time + timeBetweenNotifications
Trigger.AfterDelay(time, function()
Media.PlaySpeechNotification(player,"TMinusTwo")
end)
time = time + timeBetweenNotifications
Trigger.AfterDelay(time, function()
Media.PlaySpeechNotification(player,"TMinusOne")
end)
end
-- Reinforcements via Starport
function CHOAMDeliverCustomUnits(player, squad)
local starport = SelectStarport(player)
--Media.Debug("Starting custom units delivery "..player.InternalName)
if starport == nil then
--Media.Debug("Error, cant find any starport. Starport reset"..player.Name)
ResetStartport(player)
return
end
local rallypoint = starport.RallyPoint
local path = {Map.ClosestEdgeCell(starport.Location),starport.Location + CVec.New(1,1)}
local airUnits = FilterAirUnits(player.InternalName)
--wait for Choam to come
local units = Reinforcements.ReinforceWithTransport(player,"frigate_choam",squad, path,{path[2], path[1]})
local frigate = units[1]
Reinforcements.Reinforce(player, airUnits,path)
-- when killed or deliver finish remove Frigade and reset Starport settings
Trigger.OnRemovedFromWorld(starport, function()
--Media.Debug("Starport removed redirecting order "..frigate.Type)
local starport_new = SelectStarport(player)
if starport_new == nil then
if not frigate.IsDead then
--Media.Debug("no more starports canceling order"..player.Name)
frigate.Stop()
frigate.Move(path[1])
end
else
-- Media.Debug("Starport removed redirecting order "..frigate.Type)
if not frigate.IsDead then
frigate.Stop()
frigate.Move(starport_new.Location + CVec.New(1,1))
frigate.UnloadPassengers()
end
end
end)
--in case frigate stuck
Trigger.OnIdle(frigate, function()
frigate.UnloadPassengers()
end)
Trigger.OnPassengerExited(frigate,
function(carry, pass)
if pass ~= nil then
Trigger.AfterDelay(10, function()
pass.Move(rallypoint)
end)
end
end)
end
-------------------------------
-- Multi pass Airstrikes -
--warring use only as local function (global function can crash)
--------------------------------
CallAirstrike = function(dummy)
local dummyPosition = dummy.Location
local spawnEdgeCell = Map.ClosestEdgeCell(dummyPosition)
local angle = CalculateBestAngle(spawnEdgeCell)
local wposDummyLocation = Map.CenterOfCell(dummyPosition)
Beacon.New(dummy.Owner,wposDummyLocation, 250)
local wposAirCraftSpawnLocation = Map.CenterOfCell(spawnEdgeCell)
local airUnits = GiveAirSquad(dummy.Type)
local squadRefference = {}
local dummyRefference = {}
local pon = 1
local arrayLenght = #SpawnWposOffsets + 1
-- calculate WPos offset for every aircraft
while pon <= #airUnits do
local newLocation
if Useoffest == true then
if angle == Angle.West or angle == Angle.East then
newLocation =WPos.New( wposDummyLocation.X + SpawnWposOffsets[arrayLenght - pon], wposDummyLocation.Y+SpawnWposOffsets[pon], 0)
else
newLocation =WPos.New( wposDummyLocation.X + SpawnWposOffsets[pon], wposDummyLocation.Y+SpawnWposOffsets[pon], 0)
end
else
newLocation = wposDummyLocation
end
dummyRefference[pon] = Actor.Create("dummy.generic",true, {Owner = dummy.Owner, CenterPosition = newLocation,Location })
pon = pon + 1
end
--Media.Debug("calling Airstrike"..tostring(spawnPosition.X).." , "..tostring(spawnPosition.Y))
-- calculate squadron
for i, actorName in pairs(airUnits) do
local spamDelay = i * SquadSpawnDelay
Trigger.AfterDelay(spamDelay, function()
local airUnit
local finalWposPosition
if angle == Angle.West or angle == Angle.East then
finalWposPosition = wposAirCraftSpawnLocation + WVec.New(SpawnWposOffsets[arrayLenght - i], SpawnWposOffsets[i], Actor.CruiseAltitude(actorName))
else
finalWposPosition = wposAirCraftSpawnLocation + WVec.New(SpawnWposOffsets[i], SpawnWposOffsets[i], Actor.CruiseAltitude(actorName))
end
if Useoffest == true then
airUnit = Actor.Create(actorName ,true, {Owner = dummy.Owner ,Facing = angle, CenterPosition = finalWposPosition })
airUnit.Attack(dummyRefference[i], true, true)
else
airUnit = Actor.Create(actorName ,true, {Owner = dummy.Owner, Location = spawnEdgeCell, Facing = angle})
airUnit.Attack(dummyRefference[i], true, true)
end
table.insert(squadRefference, airUnit)
LeaveOnEmpty(airUnit)
end)
end
Trigger.AfterDelay(SquadSpawnDelay + 1 * 5, function()
Trigger.OnAllRemovedFromWorld(squadRefference, function ()
-- edge case check. if player surrender while airstrike is in progress -> crash
if not dummy.IsDead then
dummy.Destroy()
for i, dummy_generic in pairs(dummyRefference) do
dummy_generic.Kill()
end
end
end)
end)
end
function LeaveOnEmpty(unit)
if not unit.IsDead then
if unit.AmmoCount("primary") < 1 then
unit.Stop()
local position = Map.ClosestEdgeCell(unit.Location)
unit.Move(position)
unit.Destroy()
else
Trigger.AfterDelay(30, function()
LeaveOnEmpty(unit)
end)
end
end
end
function CalculateBestAngle(position)
if position.X <= 2 then
return Angle.East
elseif position.Y <= 2 then
return Angle.South
elseif position.X < position.Y then
return Angle.North
else
return Angle.West
end
end
function GiveAirSquad(faction)
if faction == "waypoint.airtstrike_a" then
--Media.DisplayMessage("atreides squad")
return AirSquads[1]
elseif faction == "waypoint.airtstrike_h"then
return AirSquads[2]
elseif faction == "waypoint.airtstrike_o"then
return AirSquads[3]
end
end
----------------------
---Air Reinforcements-
----------------------
function DropAirReinforcements(dummy)
local squad
if dummy.Type=="waypoint.reinforce_a" then squad=1
elseif dummy.Type=="waypoint.reinforce_o" then squad=2
elseif dummy.Type=="waypoint.reinforce_h" then squad=3
elseif dummy.Type=="waypoint.reinforce_at" then squad=4
elseif dummy.Type=="waypoint.reinforce_or" then squad=5
end
--Carryall reinforcements
local spawnCell = GetSpawnPoint(dummy)
local path = {spawnCell,dummy.Location}
local exitPath = {dummy.Location, Map.ClosestEdgeCell(dummy.Location) }
Media.Debug("reinforcements on the way"..dummy.Owner.InternalName)
Beacon.New(dummy.Owner,Map.CenterOfCell(dummy.Location))
local units = Reinforcements.ReinforceWithTransport(dummy.Owner,DropActor[squad] , ReinforcementSquads[squad], path, exitPath, nil, nil, 5)
local carryall = units[1]
Trigger.OnIdle(carryall, function()
carryall.UnloadPassengers()
end)
Trigger.OnPassengerExited(carryall,
function(carry, pass)
if not carry.HasPassengers
then
carry.Stop()
carry.Move(path[1])
carry.Destroy()
end
end
)
end
function GetSpawnPoint(dummy)
local buildings = dummy.Owner.GetActorsByType("high_tech_factory")
for i, building in pairs(buildings) do
if building.IsPrimaryBuilding then
return Map.ClosestEdgeCell(building.Location)
end
end
if (buildings[1].Location ~= nil) then
return Map.ClosestEdgeCell(buildings[1].Location)
else
return dummy.Owner.HomeLocation
end
end
-- adds new actors into the list (used only in tick function)
function ActorsAddedToWorld(newlist,register)
local new_actor_list={}
for key,act in pairs(newlist)
do
if not register[tostring(act)]
then
register[tostring(act)]=true
table.insert(new_actor_list,act)
end
end
return new_actor_list
end