Guest User

Untitled

a guest
Jun 8th, 2009
523
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 34.67 KB | None | 0 0
  1.  
  2. -- In-game, type /luarules kpai in the console to toggle the ai debug messages
  3.  
  4. function gadget:GetInfo()
  5.     return {
  6.         name = "Kernel Panic AI",
  7.         desc = "An AI that knows how to play Kernel Panic",
  8.         author = "KDR_11k (David Becker), modified by zwzsg",
  9.         date = "2008-04-09",
  10.         license = "Public Domain",
  11.         layer = 82,
  12.         enabled = true
  13.     }
  14. end
  15.  
  16. local STATE_EMPTY    =0
  17. local STATE_OWN      =1
  18. local STATE_ENEMY    =2
  19. local STATE_HOMEBASE =3 -- Not used anymore
  20. local STATE_LOCKED   =4
  21.  
  22. local KPAI_Debug_Mode=0 -- Must be 0 or 1
  23.  
  24. if (gadgetHandler:IsSyncedCode()) then
  25.  
  26. --SYNCED
  27.  
  28. local teamData={}
  29. local unitPos={}
  30. local spots={}
  31.  
  32. local orders={}
  33. local minifacCreated={}
  34.  
  35. local minifacLimit=4
  36.  
  37. local dispatchTimer={}
  38. dispatchCoolDown = 5 -- in seconds
  39. dispatchRange = 300
  40.  
  41. local teamBufferSize=0
  42.  
  43. local PositionsStatesChanged=true
  44.  
  45. local weirdFactions=false
  46. if math.random(47)==9 then
  47.     weirdFactions=true
  48. else
  49.     weirdFactions=false
  50. end
  51.  
  52.  
  53. VFS.Include("LuaRules/Gadgets/kpunittypes.lua",nil)
  54. VFS.Include("LuaRules/Gadgets/new_cmd_id.lua",nil)
  55.  
  56. local function ChangeAIDebugVerbosity(cmd,line,words,player)
  57.     local lvl=tonumber(words[1])
  58.     if lvl then
  59.         KPAI_Debug_Mode=lvl
  60.         Spring.Echo("KPAI debug verbosity set to "..KPAI_Debug_Mode)
  61.     else
  62.         if KPAI_Debug_Mode>0 then
  63.             KPAI_Debug_Mode=0
  64.         else
  65.             KPAI_Debug_Mode=1
  66.         end
  67.         Spring.Echo("KPAI debug verbosity toggled to "..KPAI_Debug_Mode)
  68.     end
  69.     return true
  70. end
  71.  
  72. local function SetupCmdChangeAIDebugVerbosity()
  73.     local cmd,func,help
  74.     cmd  = "kpai"
  75.     func = ChangeAIDebugVerbosity
  76.     help = " [0|1]: make the KP LUA AI shut up or fill your infolog"
  77.     gadgetHandler:AddChatAction(cmd,func,help)
  78.     Script.AddActionFallback(cmd..' ',help)
  79. end
  80.  
  81. local function KPAIDebugMessage(t,message)
  82.     if(KPAI_Debug_Mode>0) then
  83.         Spring.Echo("Team["..t.."] "..message)
  84.     end
  85. end
  86.  
  87. function gadget:Initialize()
  88.     bufferSize = GG.bufferSize -- Network faction special ressource
  89.     SetupCmdChangeAIDebugVerbosity()
  90. end
  91.  
  92.  
  93. local function RemoveSelfIfNoTeam()
  94.     local AIcount=0
  95.     for t,td in pairs(teamData) do
  96.         AIcount=AIcount+1
  97.     end
  98.     if(AIcount==0) then -- #teamData is 0 even when there are teams, and teamData=={} is untrue even when teamData={}
  99.         KPAIDebugMessage("none",gadget:GetInfo().name.." removing self")
  100.         gadgetHandler:RemoveGadget()
  101.     end
  102. end
  103.  
  104. function gadget:GameStart()
  105.     KPAIDebugMessage(gadget:GetInfo().name," GameStart!")
  106.  
  107.     -- In ONS must kill all sockets before attacking kernel
  108.     if Spring.GetModOptions().ons and Spring.GetModOptions().ons ~= "0" then
  109.         minifacLimit=1
  110.     end
  111.  
  112.     -- Create tables of Geos
  113.     for _,f in ipairs(Spring.GetAllFeatures()) do
  114.         if FeatureDefs[Spring.GetFeatureDefID(f)].name == "geovent" then
  115.             local x,y,z = Spring.GetFeaturePosition(f)
  116.             --Merging algorithm because some KP maps have multiple geos in one spot
  117.             local newSpot=true
  118.             for i,s in pairs(spots) do
  119.                 if math.sqrt((x-s.x)*(x-s.x) + (z-s.z)*(z-s.z)) < 64 then
  120.                     newSpot = false
  121.                     break
  122.                 end
  123.             end
  124.             if newSpot then
  125.                 table.insert(spots, {x=x, y=y, z=z})
  126.             end
  127.         end
  128.     end
  129.  
  130.     -- Initialise AI for all team that are set to use it
  131.     for _,t in ipairs(Spring.GetTeamList()) do
  132.         local _,_,_,ai,side = Spring.GetTeamInfo(t)
  133.         if Spring.GetTeamLuaAI(t)==gadget:GetInfo().name then
  134.             KPAIDebugMessage(t," assigned to "..gadget:GetInfo().name)
  135.             local pos={}
  136.             local home_x,home_y,home_z = Spring.GetTeamStartPosition(t)
  137.             pos[0]={x=home_x, y=home_y, z=home_z, dist=0, state=HOMEBASE, spams = 0, underConstruction=false}
  138.             for i,s in pairs(spots) do
  139.                 local dist = math.sqrt((home_x-s.x)*(home_x-s.x) + (home_z-s.z)*(home_z-s.z))
  140.                 if dist >= 64 then
  141.                     table.insert(pos,{x=s.x, y=s.y, z=s.z,dist = dist, state = STATE_EMPTY, spams = 0, underConstruction=false})
  142.                 end
  143.             end
  144.             for i,_ in pairs(pos) do
  145.                 KPAIDebugMessage(t,"pos["..i.."] @(x="..math.floor(pos[i].x)..",z="..math.floor(pos[i].z)..") dist="..math.floor(pos[i].dist))
  146.             end
  147.             if #pos==0 then
  148.                 table.insert(pos,pos[0]) -- just to prevent bug on geoless maps
  149.             end
  150.             local _,_,_,_,_,at = Spring.GetTeamInfo(t)
  151.             teamData[t]= {
  152.                 positions=pos,
  153.                 missions={},
  154.                 constructors={},
  155.                 factories={},
  156.                 dangers={},
  157.                 threatRating=0,
  158.                 com={},
  159.                 lastMove=0,
  160.                 forceSize=0,
  161.                 allyTeam=at,
  162.                 lastNuke=0,
  163.                 no_more_enemies_since=0,
  164.                 lastAllyDamage=nil,
  165.             }
  166.         end
  167.     end
  168.     -- RemoveSelfIfNoTeam() -- Somehow gadgetHandler:RemoveGadget() remove other gadgets when executed at GameStart stage. Moved to GameFrame
  169. end
  170.  
  171.  
  172. local function SuicideIfAlone(t)
  173.     if Spring.GetTeamUnitCount(t) and Spring.GetTeamUnitCount(t)>1 then
  174.         local td = teamData[t]
  175.         local living_enemy_teams=0
  176.         for _,ot in ipairs(Spring.GetTeamList()) do
  177.             if not Spring.AreTeamsAllied(ot,t) then
  178.                 local _,_,isDead,isAiTeam,side,_=Spring.GetTeamInfo(ot)
  179.                 if not isDead and Spring.GetTeamUnitCount(ot) and Spring.GetTeamUnitCount(ot)>0 then
  180.                     KPAIDebugMessage(t,"Other enemy is "..side)
  181.                     living_enemy_teams=1+living_enemy_teams
  182.                 end
  183.             end
  184.         end
  185.         if living_enemy_teams==0 then
  186.             if (not td.no_more_enemies_since) or (td.no_more_enemies_since==0) then
  187.                 td.no_more_enemies_since=Spring.GetGameSeconds()       
  188.             else
  189.                 if Spring.GetGameSeconds() - td.no_more_enemies_since > 30+(7*t)%16 then
  190.                     KPAIDebugMessage(t,"suicide because of loneliness")
  191.                     Spring.GiveOrderToUnitArray(Spring.GetTeamUnits(t),CMD.SELFD,{},{})
  192.                     td.no_more_enemies_since=7+Spring.GetGameSeconds()
  193.                 end
  194.             end
  195.         else
  196.             td.no_more_enemies_since=0
  197.             KPAIDebugMessage(t,"I have enemies!")
  198.         end
  199.     end
  200. end
  201.  
  202. local function MorphToWeird(t)
  203.     KPAIDebugMessage(t," should go 2/3 weird")
  204.     local MorphToWeirdQueue={}
  205.     for _,u in ipairs(Spring.GetTeamUnitsByDefs(t,hole)) do
  206.         if math.random(3)~=1 then
  207.             table.insert(MorphToWeirdQueue,{unit=u, team=t, target="holeold"})
  208.         end
  209.     end
  210.     for _,u in ipairs(Spring.GetTeamUnitsByDefs(t,carrier)) do
  211.         if math.random(3)~=1 then
  212.             table.insert(MorphToWeirdQueue,{unit=u, team=t, target="thbase"})
  213.         end
  214.     end
  215.     for i,u in pairs(MorphToWeirdQueue) do
  216.         local x, y, z
  217.         x, y, z = Spring.GetUnitPosition(u.unit)
  218.         nu = Spring.CreateUnit(u.target,x,y,z,0,u.team)
  219.         Spring.SetUnitBlocking(nu, false)
  220.         Spring.SetUnitCOBValue(nu, 82, Spring.GetUnitHeading(u.unit))
  221.         Spring.SetUnitHealth(nu, Spring.GetUnitHealth(u.unit) / UnitDefs[Spring.GetUnitDefID(u.unit)].health * UnitDefs[Spring.GetUnitDefID(nu)].health)
  222.         local c = Spring.GetUnitCommands(u.unit)
  223.         for i = 1, c.n do
  224.             Spring.GiveOrderToUnit(nu, c[i].id, c[i].params, c[i].options.coded)
  225.         end
  226.         Spring.DestroyUnit(u.unit, false, true, u.unit)
  227.         MorphToWeirdQueue[i] = nil
  228.     end
  229. end
  230.  
  231. local function SelectForceFor(t,pos)
  232.     local spams=5
  233.     local cnstrs=1
  234.     local heavies=1
  235.     local arties=1
  236.     local crowdedarea=0
  237.     local td = teamData[t]
  238.     local p = td.positions[pos]
  239.     if bufferSize and bufferSize[t] then
  240.         teamBufferSize=bufferSize[t]
  241.     else
  242.         teamBufferSize=0
  243.     end
  244.     if p.state == STATE_ENEMY then
  245.         local ts={}
  246.         for _,t in ipairs(Spring.GetTeamList()) do
  247.             local _,_,_,_,_,at = Spring.GetTeamInfo(t)
  248.             if at ~= td.allyTeam then
  249.                 table.insert(ts,t)
  250.             end
  251.         end
  252.         local es = #Spring.GetUnitsInCylinder(p.x,p.z,300)--,t)
  253.         cnstrs=0
  254.         spams = 20 + .2 * (td.forceSize+teamBufferSize)
  255.         arties = math.random(2)
  256.         heavies = 1+ math.floor(es / 15)
  257.         if es > 15 then
  258.             crowdedarea=1
  259.         end
  260.     elseif p.state == STATE_LOCKED then
  261.         spams=0
  262.         cnstrs=0
  263.         heavies=0
  264.         arties=0
  265.         crowdedarea=0
  266.     elseif p.state == STATE_EMPTY then
  267.         if p.underConstruction == false then
  268.             cnstrs = 1
  269.         else
  270.             cnstrs = 0
  271.         end
  272.         heavies = 2
  273.         spams = 20 - p.spams
  274.         arties = math.random(1)
  275.     end
  276.     return cnstrs, spams, heavies, arties, crowdedarea
  277. end
  278.  
  279. local function GetAttackPositionsFor(t,x,z)
  280.     local ps={}
  281.     for i,p in pairs(teamData[t].positions) do
  282.         local d = math.sqrt((x-p.x)*(x-p.x) + (z-p.z)*(z-p.z))
  283.         if p.state == STATE_OWN then
  284.             if p.spams > .003 * d then
  285.                 table.insert(ps, i)
  286.             end
  287.         elseif p.state == STATE_EMPTY then
  288.             if p.spams > 10 and d < 1500 then
  289.                 table.insert(ps, i)
  290.             end
  291.         elseif p.state == STATE_HOMEBASE then
  292.             table.insert(ps, i)
  293.         end
  294.     end
  295.     return ps
  296. end
  297.  
  298. local function GetWeightFor(t,pos)
  299.     local td = teamData[t]
  300.     local p = td.positions[pos]
  301.     local w = 1.0
  302.     if p.dist < 64 and p.state ~= STATE_HOMEBASE then
  303.         return 0
  304.     end
  305.     if p.state == STATE_ENEMY then
  306.         w = (1.0 + 1/p.dist) * (1+td.forceSize)
  307.     elseif p.state == STATE_LOCKED then
  308.         w = (0.3 + 1/p.dist) * (1+td.forceSize)
  309.     elseif p.state == STATE_EMPTY and not p.underConstruction then
  310.         w = 1.0/math.sqrt(p.dist) * (1+td.forceSize)/(10 * p.spams+1)
  311.     else
  312.         w = 1.0
  313.     end
  314.     return w
  315. end
  316.  
  317. local function IsItOccupiedByAnyHomeBase(testedX,testedZ)
  318.     for _,anyteam in ipairs(Spring.GetTeamList()) do
  319.         for _,u in ipairs(Spring.GetTeamUnitsByDefs(anyteam,HomeBase)) do
  320.             local ux,_,uz=Spring.GetUnitPosition(u)
  321.             if math.abs(ux - testedX)<64 and math.abs(uz - testedZ)<64 then
  322.                 return 1
  323.             end
  324.         end
  325.     end
  326.     return nil
  327. end
  328.  
  329. local function IsItOccupied(testedX,testedZ)
  330.     for _,anyteam in ipairs(Spring.GetTeamList()) do
  331.         for _,u in ipairs(Spring.GetTeamUnitsByDefs(anyteam,AnyBuilding)) do
  332.             local ux,_,uz=Spring.GetUnitPosition(u)
  333.             if math.abs(ux - testedX)<48 and math.abs(uz - testedZ)<48 then
  334.                 return 1
  335.             end
  336.         end
  337.     end
  338.     return nil
  339. end
  340.  
  341. local function GetNiceGeo(t,oriX,oriZ)
  342.     local td = teamData[t]
  343.     local nicest_geo_so_far = nil
  344.     local nicest_geo_dist = 0
  345.  
  346.     for _=1,math.max(#td.positions/2,2) do
  347.         local p = math.random(#td.positions)
  348.         local pos = td.positions[p]
  349.         if((pos.state==STATE_EMPTY and (not pos.underConstruction) and (not IsItOccupied(pos.x,pos.z))) and ((nicest_geo_so_far==nil) or (pos.dist<=nicest_geo_dist))) then
  350.             nicest_geo_so_far = p
  351.             nicest_geo_dist = math.sqrt((pos.x-oriX)*(pos.x-oriX) + (pos.z-oriZ)*(pos.z-oriZ))
  352.         end
  353.     end
  354.  
  355.     if not nicest_geo_so_far then
  356.         for _=1,2*#td.positions do
  357.             local p = math.random(#td.positions)
  358.             local pos = td.positions[p]
  359.             if((pos.state~=STATE_OWN and (not pos.underConstruction) and (not IsItOccupied(pos.x,pos.z))) and ((nicest_geo_so_far==nil) or (pos.dist<=nicest_geo_dist))) then
  360.                 nicest_geo_so_far = p
  361.                 if(pos.state==STATE_EMPTY) then
  362.                     nicest_geo_dist = math.sqrt((pos.x-oriX)*(pos.x-oriX) + (pos.z-oriZ)*(pos.z-oriZ))
  363.                 else
  364.                     nicest_geo_dist = 2*math.sqrt((pos.x-oriX)*(pos.x-oriX) + (pos.z-oriZ)*(pos.z-oriZ))
  365.                 end
  366.             end
  367.         end
  368.     end
  369.  
  370.     return nicest_geo_so_far
  371. end
  372.  
  373. local function RecalculatePositionsStates(t)
  374.     KPAIDebugMessage(t,"recalculating positions states")
  375.     if Spring.GetModOptions()["ons"]==nil or Spring.GetModOptions()["ons"]=="0" then
  376.         return
  377.     end
  378.     for i,s in pairs(teamData[t].positions) do
  379.         local state = STATE_EMPTY
  380.         for _,team in ipairs(Spring.GetTeamList()) do
  381.             for _,u in ipairs(Spring.GetTeamUnitsByDefs(team,AnyBuilding)) do
  382.                 local x,_,z = Spring.GetUnitPosition(u)
  383.                 if math.sqrt((x-s.x)*(x-s.x) + (z-s.z)*(z-s.z)) < 64 then
  384.                     if t==team or Spring.AreTeamsAllied(team,t) then
  385.                         state = STATE_OWN
  386.                     else
  387.                         state = STATE_ENEMY
  388.                         if Spring.GetModOptions()["ons"] and Spring.GetModOptions()["ons"]~="0" then
  389.                             if GG.GetUnitONSInfo then
  390.                                 local UnitExists,Shielded,GreenShield,RedShield,SourceFound,SourceID = GG.GetUnitONSInfo(u)
  391.                                 if Shielded then
  392.                                     state = STATE_LOCKED
  393.                                 end
  394.                             end
  395.                         end
  396.                     end
  397.                 end
  398.             end
  399.         end
  400.         teamData[t].positions[i].state=state
  401.     end
  402. end
  403.  
  404. local function AddSpam(t,u,from)
  405.     KPAIDebugMessage(t,"I got a spam!")
  406.  
  407.     -- Hook to closest factory if virus or packet
  408.     if (not Spring.ValidUnitID(from)) or (not isMiniFac[Spring.GetUnitDefID(from)]) then
  409.         KPAIDebugMessage(t,"orphan spam!")
  410.         local closest = nil
  411.         local min_dist = 0
  412.         for _,f in ipairs(Spring.GetTeamUnitsByDefs(t,MiniFac)) do
  413.             if(not closest or Spring.GetUnitSeparation(u,f)<min_dist) then
  414.                 closest = f
  415.                 min_dist=Spring.GetUnitSeparation(u,f)
  416.             end
  417.         end
  418.         if closest then
  419.             from = closest
  420.             local ud=Spring.GetUnitDefID(u)
  421.             if ud==virus then
  422.                 table.insert(orders,{u,CMD.MOVE,{Spring.GetUnitPosition(closest)},{}})
  423.             end
  424.         end
  425.     end
  426.  
  427.     if from and teamData[t].factories[from] then
  428.         local td = teamData[t]
  429.         local pos = td.factories[from].position
  430.         td.positions[pos].spams = td.positions[pos].spams + 1
  431.         unitPos[u]=pos
  432.     end
  433. end
  434.  
  435. local function AddMiniFac(t,u)
  436.     local x,_,z = Spring.GetUnitPosition(u)
  437.     for i,s in pairs(teamData[t].positions) do
  438.         if math.sqrt((x-s.x)*(x-s.x) + (z-s.z)*(z-s.z)) < 64 then
  439.             teamData[t].positions[i].state = STATE_OWN
  440.             teamData[t].positions[i].underConstruction = false
  441.             teamData[t].factories[u] = {position = i}
  442.             break
  443.         end
  444.     end
  445.     if Spring.GetUnitDefID(u) ~= port then
  446.         table.insert(orders,{u,CMD.REPEAT,{1},{}})
  447.     end
  448.     if Spring.GetUnitDefID(u) == socket then
  449.         table.insert(orders,{u,-bit,{},{}})
  450.     end
  451.     if Spring.GetUnitDefID(u) == window then
  452.         table.insert(orders,{u,-bug,{},{}})
  453.     end
  454.     if Spring.GetUnitDefID(u) == windowold then
  455.         table.insert(orders,{u,-bugold,{},{}})
  456.     end
  457.     if Spring.GetUnitDefID(u) == thminifac then
  458.         table.insert(orders,{u,-fairy,{},{}})
  459.     end
  460. end
  461.  
  462.  
  463. local function DispatchCon(t,u,p)
  464.     local cux,_,cuz=Spring.GetUnitPosition(u)
  465.     if IsItOccupiedByAnyHomeBase(cux,cuz) then -- Don't start building while the cons is still inside homebase
  466.         KPAIDebugMessage(t,"found idle cons["..u.."] too close to homebase")
  467.         return
  468.     end
  469.     local geo=GetNiceGeo(t,cux,cuz)
  470.     if geo then
  471.         KPAIDebugMessage(t,"dispatching idle cons["..u.."] to geo["..geo.."]")
  472.         local td = teamData[t]
  473.         td.missions[u]=true
  474.         unitPos[u]=geo
  475.         pos=teamData[t].positions[geo]
  476.         local WhatToBuild=nil;
  477.         local ud=Spring.GetUnitDefID(u)
  478.         if ud == assembler then
  479.             WhatToBuild=socket
  480.         end
  481.         if ud == trojan then
  482.             WhatToBuild=window
  483.         end
  484.         if ud == trojanold then
  485.             WhatToBuild=windowold
  486.         end
  487.         if ud == gateway then
  488.             WhatToBuild=port
  489.         end
  490.         if ud == alice then
  491.             WhatToBuild=thminifac
  492.         end
  493.         local ListOfMiniFacs=Spring.GetTeamUnitsByDefs(t,MiniFac)
  494.         if ListOfMiniFacs and #ListOfMiniFacs>= 3 and math.random(3)==1 then
  495.             if ud == assembler then
  496.                 WhatToBuild=terminal
  497.             end
  498.             if ud == trojan then
  499.                 WhatToBuild=obelisk
  500.             end
  501.             -- I don't feel like letting trojanold build obelisks
  502.             if ud == gateway then
  503.                 WhatToBuild=firewall
  504.             end
  505.         end
  506.         if WhatToBuild then
  507.             local dir
  508.             if math.abs(Game.mapSizeX - 2*pos.x) > math.abs(Game.mapSizeZ - 2*pos.z) then
  509.                 if (2*pos.x>Game.mapSizeX) then
  510.                     dir=3
  511.                 else
  512.                     dir=1
  513.                 end
  514.             else
  515.                 if (2*pos.z>Game.mapSizeZ) then
  516.                     dir=2
  517.                 else
  518.                     dir=0
  519.                 end
  520.             end
  521.             Spring.GiveOrderToUnit(u,-WhatToBuild,{pos.x,0,pos.z,dir},{})
  522.         end
  523.     else
  524.         KPAIDebugMessage(t,"failed to dispatch con")
  525.     end
  526. end
  527.  
  528. local function BufferizePacket(t,u)
  529.     local closest = nil
  530.     local min_dist = 0
  531.     for _,f in ipairs(Spring.GetTeamUnitsByDefs(t,port)) do
  532.         if(not closest or Spring.GetUnitSeparation(u,f)<min_dist) then
  533.             closest = f
  534.             mind_dist=Spring.GetUnitSeparation(u,f)
  535.         end
  536.     end
  537.     if closest then
  538.         table.insert(orders,{u,CMD_ENTER,{closest},{"shift"}})
  539.     end
  540. end
  541.  
  542. local function DispatchSpam(t,u,p)
  543.     local td = teamData[t]
  544.     td.missions[u]=true
  545.     if unitPos[u] then
  546.         td.positions[unitPos[u]].spams = td.positions[unitPos[u]].spams - 1
  547.     end
  548.     unitPos[u] = p
  549.     td.positions[unitPos[u]].spams = td.positions[unitPos[u]].spams + 1
  550.     local phase = math.random(6.3)
  551.     local amp = 40 + math.random(90)
  552.     Spring.GiveOrderToUnit(u,CMD.MOVE,{teamData[t].positions[p].x + math.cos(phase)*amp,0,teamData[t].positions[p].z + math.sin(phase)*amp},{})
  553. end
  554.  
  555. local function DispatchArty(t,u,p,nx)
  556.     local cux,_,cuz=Spring.GetUnitPosition(u)
  557.     if IsItOccupiedByAnyHomeBase(cux,cuz) then -- Don't because too close to homebase, could clog it
  558.         return
  559.     end
  560.     local td = teamData[t]
  561.     td.missions[u]=true
  562.     unitPos[u] = p
  563.     KPAIDebugMessage(t,"dispatching arty "..p)
  564.     if td.positions[p].state == STATE_EMPTY then
  565.         Spring.GiveOrderToUnit(u,CMD.FIGHT,{teamData[t].positions[p].x,0,teamData[t].positions[p].z},{})
  566.     elseif td.positions[p].state == STATE_ENEMY then
  567.         if nx and (Spring.GetUnitDefID(u) == pointer) then
  568.             Spring.GiveOrderToUnit(u,CMD_NX,{teamData[t].positions[p].x - 50 + math.random(100),teamData[t].positions[p].y,teamData[t].positions[p].z - 50 + math.random(100)},{}) --NX flag
  569.         else
  570.             Spring.GiveOrderToUnit(u,CMD.ATTACK,{teamData[t].positions[p].x,teamData[t].positions[p].y,teamData[t].positions[p].z},{})
  571.         end
  572.     end
  573. end
  574.  
  575. local function DispatchHeavy(t,u,p)
  576.     local td = teamData[t]
  577.     td.missions[u]=true
  578.     unitPos[u] = p
  579.     Spring.GiveOrderToUnit(u,CMD.MOVE,{teamData[t].positions[p].x,0,teamData[t].positions[p].z},{})
  580. end
  581.  
  582. local function RetreatToGuard(t,u)
  583.     KPAIDebugMessage(t,"Wanna Retreat!")
  584.     local closest = nil
  585.     local min_dist = 0
  586.     for _,f in ipairs(Spring.GetTeamUnitsByDefs(t,AnyBuilding)) do
  587.         if(not closest or Spring.GetUnitSeparation(u,f)<min_dist) then
  588.             closest = f
  589.             mind_dist=Spring.GetUnitSeparation(u,f)
  590.         end
  591.     end
  592.     if closest then
  593.         KPAIDebugMessage(t,"Retreating!")
  594.         table.insert(orders,{u,CMD.GUARD,{closest},{}})
  595.         local x,_,z=Spring.GetUnitPosition(closest)
  596.         for i,s in pairs(teamData[t].positions) do
  597.             if math.sqrt((x-s.x)*(x-s.x) + (z-s.z)*(z-s.z)) < 64 then
  598.                 unitPos[u]= i
  599.                 break
  600.             end
  601.         end
  602.     end
  603. end
  604.  
  605. local function OrderHomeBase(u,ud,team)
  606.     if Spring.GetUnitStates(u)["repeat"] then
  607.         table.insert(orders,{u,CMD.REPEAT,{0},{}})
  608.     end
  609.     local cnstr,spam,arty,heavy
  610.     if(ud==kernel) then
  611.         cnstr=assembler
  612.         spam=bit
  613.         arty=pointer
  614.         heavy=byte
  615.     end
  616.     if(ud==hole) then
  617.         cnstr=trojan
  618.         spam=bug
  619.         arty=dos
  620.         heavy=worm
  621.     end
  622.     if(ud==holeold) then
  623.         cnstr=trojanold
  624.         spam=bugold
  625.         arty=dos
  626.         heavy=wormold
  627.     end
  628.     if(ud==carrier) then
  629.         cnstr=gateway
  630.         spam=packet
  631.         arty=flow
  632.         heavy=connection
  633.     end
  634.     if(ud==thbase) then
  635.         cnstr=alice
  636.         spam=fairy
  637.         arty=marisa
  638.         heavy=reimu
  639.     end
  640.     local n = 0
  641.     for _,_ in pairs(teamData[team].constructors) do
  642.         n=n+1
  643.     end
  644.     local r = math.random(1000)
  645.     if n*200 < r then
  646.         table.insert(orders, {
  647.             u,
  648.             -cnstr,
  649.             {},
  650.             {},
  651.         })
  652.     else
  653.         if r > 1000 - (teamData[team].forceSize+teamBufferSize) * 20 then
  654.             local n = math.random(2)
  655.             if n == 1 then
  656.                 table.insert(orders, {
  657.                     u,
  658.                     -heavy,
  659.                     {},
  660.                     {},
  661.                 })
  662.             else
  663.                 table.insert(orders, {
  664.                     u,
  665.                     -arty,
  666.                     {},
  667.                     {},
  668.                 })
  669.             end
  670.         else
  671.             for i = 1,3 do
  672.                 table.insert(orders, {
  673.                     u,
  674.                     -spam,
  675.                     {},
  676.                     {},
  677.                 })
  678.             end
  679.         end
  680.     end
  681. end
  682.  
  683. local function BuilderDone(t,u)
  684.     teamData[t].missions[u]=nil
  685.     local ud=Spring.GetUnitDefID(u)
  686.     if isHomeBase[Spring.GetUnitDefID(u)] then
  687.         OrderHomeBase(u,ud,t)
  688.     end
  689. end
  690.  
  691. local function AddHomeBase(t,u)
  692.     KPAIDebugMessage(t,"I got a com!")
  693.     table.insert(teamData[t].com,u)
  694.     teamData[t].factories[u]={position=0}
  695.     OrderHomeBase(u,Spring.GetUnitDefID(u),t)
  696. end
  697.  
  698. local function AddConstructor(t,u)
  699.     KPAIDebugMessage(t,"I got a cons!")
  700.     teamData[t].constructors[u]={position=0,}
  701. end
  702.  
  703. local function AttackHomeBase(t,targetTeam)
  704.     KPAIDebugMessage(t,"GO!",t,targetTeam)
  705.     local k = Spring.GetTeamUnitsByDefs(targetTeam,HomeBase)[1]
  706.     local td = teamData[t]
  707.     if k then
  708.         KPAIDebugMessage(t,"GO!GO!GO!")
  709.         for _,u in ipairs(Spring.GetTeamUnitsByDefs(t,spam)) do
  710.             if not td.missions[u] then
  711.                 td.missions[u]=true
  712.                 if unitPos[u] then
  713.                     td.positions[unitPos[u]].spams = td.positions[unitPos[u]].spams - 1
  714.                 end
  715.                 unitPos[u] = nil
  716.                 Spring.GiveOrderToUnit(u,CMD.ATTACK,{k},{})
  717.             end
  718.         end
  719.     end
  720. end
  721.  
  722. function gadget:UnitCreated(u,ud,team,builder)
  723.     if isAnyBuilding[ud] then
  724.         PositionsStatesChanged=true
  725.     end
  726.     if isSmallBuilding[ud] then
  727.         local pos = nil
  728.         local x,_,z = Spring.GetUnitPosition(u)
  729.         for t,td in pairs(teamData) do
  730.             for i,s in pairs(td.positions) do
  731.                 if math.sqrt((x-s.x)*(x-s.x) + (z-s.z)*(z-s.z)) < 64 then
  732.                     pos = i
  733.                     break
  734.                 end
  735.             end
  736.             if pos then
  737.                 local at = Spring.GetUnitAllyTeam(u)
  738.                 if t ~= team then
  739.                     if at ~= td.allyTeam then
  740.                         td.positions[pos].state=STATE_ENEMY
  741.                     else
  742.                         td.positions[pos].state=STATE_OWN
  743.                     end
  744.                 end
  745.             end
  746.         end
  747.     elseif (isSpam[ud]) and teamData[team] then
  748.         AddSpam(team,u,builder)
  749.     end
  750. end
  751.  
  752. function gadget:UnitDamaged(u,ud,team, damage, para, weapon,attacker,aud,ateam)
  753.     if damage<0.5 then
  754.         return
  755.     end
  756.     if isHeavy[aud] and teamData[team] and not teamData[team].dangers[attacker] then
  757.         if teamData[team].allyTeam ~= Spring.GetUnitAllyTeam(attacker) then
  758.             local x,_,z = Spring.GetUnitPosition(attacker)
  759.             teamData[team].dangers[attacker]={ud = aud, x = x, z = z}
  760.         end
  761.     end
  762.     if isTeleporter[ud] and teamData[team] then
  763.         if attacker and Spring.ValidUnitID(attacker) and Spring.GetUnitSeparation(u,attacker)<=dispatchRange then
  764.             if bufferSize and bufferSize[team] then
  765.                 teamBufferSize=bufferSize[team]
  766.             else
  767.                 teamBufferSize=0
  768.             end
  769.             if teamBufferSize>=3 then
  770.                 if (dispatchTimer[u]==nil) or Spring.GetGameSeconds()>dispatchCoolDown+dispatchTimer[u] then
  771.                     dispatchTimer[u]=Spring.GetGameSeconds()
  772.                     table.insert(orders,{u,CMD_DISPATCH,{Spring.GetUnitPosition(attacker)},{}})
  773.                     KPAIDebugMessage(team,"Counter Damage Dispatch!")
  774.                     if old_queue and old_queue[1] then
  775.                         table.insert(orders,{u,old_queue[1].params,{"shift"}})
  776.                     end
  777.                 end
  778.             end
  779.         end
  780.     end
  781.     for t,td in pairs(teamData) do
  782.         if Spring.AreTeamsAllied(team,t) then
  783.             local x,y,z=Spring.GetUnitPosition(u)
  784.             teamData[t].lastAllyDamage={x=x,y=y,z=z,t=Spring.GetGameSeconds()}
  785.             -- KPAIDebugMessage(t,"got damage at {x="..math.floor(x).." ,y="..math.floor(y).." ,z="..math.floor(z).." ,t="..math.floor(teamData[t].lastAllyDamage.t).." }")
  786.         end
  787.     end
  788. end
  789.  
  790. function gadget:UnitFinished(u, ud, team, builder)
  791.     if isAnyBuilding[ud] then
  792.         PositionsStatesChanged=true
  793.     end
  794.     if teamData[team] then
  795.         teamData[team].forceSize = teamData[team].forceSize + 1
  796.         if isHomeBase[ud] then
  797.             AddHomeBase(team,u)
  798.         elseif isCons[ud] then
  799.             AddConstructor(team,u)
  800.         elseif isMiniFac[ud] then
  801.             AddMiniFac(team,u)
  802.         end
  803.     end
  804. end
  805.  
  806. function gadget:UnitDestroyed(u,ud,team)
  807.     if isAnyBuilding[ud] then
  808.         PositionsStatesChanged=true
  809.     end
  810.     if teamData[team] then
  811.         local td = teamData[team]
  812.         td.forceSize = td.forceSize - 1
  813.         if isHomeBase[ud] then
  814.             for ii,iu in ipairs(td.com) do
  815.                 if iu==u then
  816.                     td.com[ii]=nil
  817.                 end
  818.             end
  819.         elseif isMiniFac[ud] then
  820.             if td.factories[u] then
  821.                 local pos = td.factories[u].position
  822.                 td.factories[u]=nil
  823.                 if td.positions[pos].spams <= 0 then
  824.                     td.positions[pos].state=STATE_ENEMY
  825.                 else
  826.                     td.positions[pos].state=STATE_EMPTY
  827.                 end
  828.             end
  829.         elseif isSpam[ud] then
  830.             if unitPos[u] then
  831.                 local pos = unitPos[u]
  832.                 unitPos[u]=nil
  833.                 td.positions[pos].spams = td.positions[pos].spams - 1
  834.                 KPAIDebugMessage(team,"Lost a spam!")
  835.                 if td.positions[pos].spams <= 0 and td.positions[pos].state == STATE_EMPTY then
  836.                     td.positions[pos].state = STATE_ENEMY
  837.                 end
  838.             end
  839.         elseif isCons[ud] then
  840.             if unitPos[u] then
  841.                 local pos = unitPos[u]
  842.                 td.positions[pos].underConstruction=false
  843.                 td.constructors[u]=nil
  844.                 unitPos[u]=nil
  845.                 if td.positions[pos].spams <= 0 and td.positions[pos].state == STATE_EMPTY then
  846.                     td.positions[pos].state = STATE_ENEMY
  847.                 end
  848.             end
  849.         end
  850.         td.missions[u]=nil
  851.     end
  852.     for i,o in pairs(orders) do
  853.         if o[1]==u then
  854.             orders[i]=nil
  855.         end
  856.     end
  857.     dispatchTimer[u]=nil
  858. end
  859.  
  860. function gadget:UnitTaken(u,ud,team,newteam)
  861.     if isAnyBuilding[ud] then
  862.         PositionsStatesChanged=true
  863.     end
  864. end
  865.  
  866. function gadget:UnitGiven(u,ud,team,oldteam)
  867.     if isAnyBuilding[ud] then
  868.         PositionsStatesChanged=true
  869.     end
  870. end
  871.  
  872. function gadget:GameFrame(f)
  873.  
  874.     for i,o in pairs(orders) do
  875.         if orders[i][5]==2 then -- delete that order in case displaying it causes error
  876.             orders[i]=nil
  877.         elseif orders[i][5]==1 then -- display that order in case executing it causes error
  878.             orders[i][5]=2
  879.             Spring.Echo("Spring.GiveOrderToUnit(",o[1],o[2],o[3],o[4],")")
  880.             local cmd_name=o[2]
  881.             for name,cmd in pairs(CMD) do
  882.                 if cmd == o[2] then
  883.                     cmd_name = name
  884.                 end
  885.             end
  886.             Spring.Echo(UnitDefs[Spring.GetUnitDefID(o[1])].name.." given invalid "..cmd_name.." order")
  887.         elseif Spring.ValidUnitID(o[1]) and not Spring.GetUnitIsDead(o[1]) then
  888.             orders[i][5]=1
  889.             Spring.GiveOrderToUnit(o[1],o[2],o[3],o[4])
  890.         else
  891.             KPAIDebugMessage("all","attempted to give order to ID="..o[1].." non-existant unit")
  892.         end
  893.         orders[i]=nil
  894.     end
  895.    
  896.     _G.teamData=teamData
  897.     _G.KPAI_Debug_Mode=KPAI_Debug_Mode
  898.  
  899.     -- AI update
  900.     if f % 128 < .1 then
  901.         RemoveSelfIfNoTeam()
  902.         for t,td in pairs(teamData) do
  903.             if f==128 and weirdFactions then
  904.                 MorphToWeird(t)
  905.             end
  906.             KPAIDebugMessage(t,gadget:GetInfo().name.." I live!")
  907.             if bufferSize and bufferSize[t] then
  908.                 teamBufferSize=bufferSize[t]
  909.             else
  910.                 teamBufferSize=0
  911.             end
  912.             td.threatRating = td.threatRating * .95
  913.             for _,u in ipairs(Spring.GetTeamUnitsByDefs(t,HomeBase)) do
  914.                 local known=false
  915.                 for ii,iu in ipairs(td.com) do
  916.                     if iu==u then
  917.                         known=true
  918.                     end
  919.                 end
  920.                 if not known then
  921.                     AddHomeBase(t,u);
  922.                 end
  923.             end
  924.             for _,com in ipairs(td.com) do
  925.                 local fc = Spring.GetFactoryCommands(com)
  926.                 if fc and #fc < 1 then
  927.                     OrderHomeBase(com,Spring.GetUnitDefID(com),t)
  928.                 end
  929.             end
  930.             if PositionsStatesChanged then
  931.                 RecalculatePositionsStates(t)
  932.             end
  933.             for u,_ in pairs(td.missions) do
  934.                 local c = Spring.GetUnitCommands(u)
  935.                 if isArty[Spring.GetUnitDefID(u)] then
  936.                     if td.missions[u] == true and td.missions[u] ~= "busy" then
  937.                         KPAIDebugMessage(t,"toot")
  938.                         local p = unitPos[u]
  939.                         if p and td.positions[p] and td.positions[p].state ~= STATE_ENEMY then
  940.                             if td.positions[p].state ~= STATE_LOCKED then
  941.                                 Spring.GiveOrderToUnit(u,CMD.FIGHT,{teamData[t].positions[p].x,0,teamData[t].positions[p].z},{})
  942.                             else
  943.                                 RetreatToGuard(t,u)
  944.                             end
  945.                             td.missions[u]=nil
  946.                         end
  947.                     else
  948.                         if c and #c < 1 then
  949.                             td.missions[u]=nil
  950.                         end
  951.                     end
  952.                 else
  953.                     if c and #c < 1 then
  954.                         td.missions[u]=nil
  955.                     end
  956.                 end
  957.             end
  958.             for d,dd in pairs(td.dangers) do
  959.                 for _,u in ipairs(Spring.GetTeamUnitsByDefs(t,arty)) do
  960.                     if td.missions[u]~="busy" then
  961.                         local x,_,z = Spring.GetUnitPosition(u)
  962.                         if math.sqrt((x-dd.x)*(x-dd.x) + (z-dd.z)*(z-dd.z)) < 2000 then
  963.                             local cux,_,cuz=Spring.GetUnitPosition(u)
  964.                             if not IsItOccupiedByAnyHomeBase(cux,cuz) then -- Don't because too close to homebase, could clog it
  965.                                 Spring.GiveOrderToUnit(u,CMD.ATTACK,{d},{})
  966.                                 td.missions[u]="busy"
  967.                             end
  968.                             break
  969.                         end
  970.                     end
  971.                 end
  972.                 td.dangers[d]=nil
  973.             end
  974.             for _,p in pairs(td.positions) do
  975.                 if p.state == STATE_ENEMY then
  976.                     local enemies = false
  977.                     for _,u in ipairs(Spring.GetUnitsInCylinder(p.x,p.z,160)) do
  978.                         if Spring.GetUnitAllyTeam(u) ~= td.allyTeam then
  979.                             enemies = true
  980.                             break
  981.                         end
  982.                     end
  983.                     if not enemies then
  984.                         p.state = STATE_EMPTY
  985.                     end
  986.                 end
  987.             end
  988.             if td.forceSize+teamBufferSize > 50 and math.random(5) == 1 then
  989.                 local tl = Spring.GetTeamList()
  990.                 local m =math.random(#tl-1)
  991.                 local target = tl[m] --not gaia
  992.                 KPAIDebugMessage(t,m,target,#tl)
  993.                 local _,_,_,_,_,at = Spring.GetTeamInfo(target)
  994.                 KPAIDebugMessage(t,"allies",at,td.allyTeam)
  995.                 if at ~= td.allyTeam then
  996.                     local ListOfSmallBuildings=Spring.GetTeamUnitsByDefs(target,SmallBuilding)
  997.                     if ListOfSmallBuildings and #ListOfSmallBuildings<minifacLimit then
  998.                         AttackHomeBase(t,target)
  999.                     end
  1000.                 end
  1001.             end
  1002.             for _=1,1+(td.forceSize+teamBufferSize)*.02 do
  1003.                 local maxWeight = -10
  1004.                 local sp = nil
  1005.                 for i=1,math.max(#td.positions/3,2) do
  1006.                     local p = math.random(#td.positions)
  1007.                     -- KPAIDebugMessage(t,"testing spot["..p.."] weight="..GetWeightFor(t,p))
  1008.                     if GetWeightFor(t,p) > maxWeight then
  1009.                         maxWeight=GetWeightFor(t,p)
  1010.                         sp = p
  1011.                     end
  1012.                 end
  1013.                 if sp then
  1014.                     KPAIDebugMessage(t,"likes spot "..sp)
  1015.                     local cnstrs, spams, heavies, arties, crowdedarea = SelectForceFor(t,sp)
  1016.                     if cnstrs > 0 then
  1017.                         for i,_ in pairs(td.constructors) do
  1018.                             if not td.missions[i] then
  1019.                                 -- DispatchCon(t,i,sp)
  1020.                                 break
  1021.                             end
  1022.                         end
  1023.                     end
  1024.                     if spams > 0 then
  1025.                         for _,p in ipairs(GetAttackPositionsFor(t,td.positions[sp].x,td.positions[sp].z)) do
  1026.                             for _,u in ipairs(Spring.GetUnitsInCylinder(td.positions[p].x, td.positions[p].z, 300, t)) do
  1027.                                 if Spring.GetUnitDefID(u)==port then
  1028.                                     Spring.GiveOrderToUnit(u,CMD_DISPATCH,{teamData[t].positions[p].x,0,teamData[t].positions[p].z},{})
  1029.                                     spams = spams - math.min(teamBufferSize,12)
  1030.                                     teamBufferSize=math.max(0,teamBufferSize-12)
  1031.                                     if spams <= 0 then
  1032.                                         break
  1033.                                     end
  1034.                                 end
  1035.                                 if (isSpam[Spring.GetUnitDefID(u)]) and not td.missions[u] then
  1036.                                     DispatchSpam(t,u,sp)
  1037.                                     spams = spams - 1
  1038.                                     if spams <= 0 then
  1039.                                         break
  1040.                                     end
  1041.                                 end
  1042.                             end
  1043.                         end
  1044.                     end
  1045.                     local spt = td.positions[sp].state
  1046.                     if arties > 0 then
  1047.                         for _,u in ipairs(Spring.GetTeamUnitsByDefs(t,arty)) do
  1048.                             if not td.missions[u] or (td.missions[u]==true and spt==STATE_ENEMY) then
  1049.                                 DispatchArty(t,u,sp,crowdedarea > 0)
  1050.                                 arties=arties-1
  1051.                                 if arties <=0 then
  1052.                                     break
  1053.                                 end
  1054.                             end
  1055.                         end
  1056.                     end
  1057.                     if heavies > 0 then
  1058.                         for _,u in ipairs(Spring.GetTeamUnitsByDefs(t,heavy)) do
  1059.                             if not td.missions[u] then
  1060.                                 DispatchHeavy(t,u,sp)
  1061.                                 heavies=heavies-1
  1062.                                 if heavies <=0 then
  1063.                                     break
  1064.                                 end
  1065.                             end
  1066.                         end
  1067.                     end
  1068.                     if crowdedarea > 0 and td.lastNuke < f - 15*30 then
  1069.                         KPAIDebugMessage(t,"wanna nux")
  1070.                         for _,u in ipairs(Spring.GetTeamUnitsByDefs(t,terminal)) do
  1071.                             if not GG.rechargeList[u] then
  1072.                                 td.lastNuke=f
  1073.                                 KPAIDebugMessage(t,"Did nux!")
  1074.                                 Spring.GiveOrderToUnit(u, CMD_AIRSTRIKE, {td.positions[sp].x, td.positions[sp].y, td.positions[sp].z}, {})
  1075.                                 break
  1076.                             end
  1077.                         end
  1078.                     end
  1079.                     for _,u in ipairs(Spring.GetTeamUnitsByDefs(t,obelisk)) do
  1080.                         if not GG.rechargeList[u] then
  1081.                             local target=Spring.GetUnitNearestEnemy(u,1500)
  1082.                             if target then
  1083.                                 KPAIDebugMessage(t,"Did lisk!")
  1084.                                 local x,y,z = Spring.GetUnitPosition(target)
  1085.                                 Spring.GiveOrderToUnit(u, CMD.ATTACK, {x,y,z}, {})
  1086.                                 break
  1087.                             end
  1088.                         end
  1089.                     end
  1090.                     for _,u in ipairs(Spring.GetTeamUnitsByDefs(t,firewall)) do
  1091.                         if not GG.rechargeList[u] then
  1092.                             if td.lastAllyDamage then
  1093.                                 if td.lastAllyDamage.t > Spring.GetGameSeconds()+6 then
  1094.                                     td.lastAllyDamage=nil
  1095.                                 end
  1096.                             end
  1097.                             if td.lastAllyDamage then
  1098.                                 local x=td.lastAllyDamage.x
  1099.                                 local y=td.lastAllyDamage.y
  1100.                                 local z=td.lastAllyDamage.z
  1101.                                 local alliedUnitsNear=0
  1102.                                 local enemyUnitsNear=0
  1103.                                 for _,uic in ipairs(Spring.GetUnitsInCylinder(x,z,300)) do
  1104.                                     if Spring.GetUnitAllyTeam(uic) == Spring.GetUnitAllyTeam(u) then
  1105.                                         alliedUnitsNear=alliedUnitsNear+1
  1106.                                         if _G.protected[uic] then
  1107.                                             alliedUnitsNear=0
  1108.                                             break
  1109.                                         end
  1110.                                     end
  1111.                                 end
  1112.                                 for _,uic in ipairs(Spring.GetUnitsInCylinder(x,z,500)) do
  1113.                                     if not Spring.AreTeamsAllied(Spring.GetUnitTeam(uic),Spring.GetUnitTeam(u)) then
  1114.                                         enemyUnitsNear=enemyUnitsNear+1
  1115.                                     end
  1116.                                 end
  1117.                                 KPAIDebugMessage(t,"Wanna wall!")
  1118.                                 if enemyUnitsNear>=3 and alliedUnitsNear>=7 then
  1119.                                     KPAIDebugMessage(t,"Did wall!")
  1120.                                     Spring.GiveOrderToUnit(u, CMD_FIREWALL, {x,y,z}, {})
  1121.                                     td.lastAllyDamage=nil
  1122.                                     break
  1123.                                 end
  1124.                             end
  1125.                         end
  1126.                     end
  1127.                     td.lastMove=f
  1128.                 end
  1129.             end
  1130.             for _,u in ipairs(Spring.GetTeamUnitsByDefs(t,cons)) do
  1131.                 local c = Spring.GetUnitCommands(u)
  1132.                 local vx,_,vz=Spring.GetUnitVelocity(u)
  1133.                 -- if ((not c) or #c<2) then
  1134.                 if vx==0 and vz==0 and not Spring.GetUnitIsBuilding(u) then
  1135.                     KPAIDebugMessage(t,"found idle cons["..u.."], dispatching it.")
  1136.                     DispatchCon(t,u,0)
  1137.                 end
  1138.             end
  1139.             for _,u in ipairs(Spring.GetTeamUnitsByDefs(t,packet)) do
  1140.                 local c = Spring.GetUnitCommands(u)
  1141.                 local vx,_,vz=Spring.GetUnitVelocity(u)
  1142.                 if vx==0 and vz==0 and ((not c) or #c<1) then
  1143.                     if Spring.GetUnitNearestEnemy(u,250)==nil then
  1144.                         -- KPAIDebugMessage(t,"found idle packet["..u.."], buffering it.")
  1145.                         -- BufferizePacket(t,u)
  1146.                     end
  1147.                 end
  1148.             end
  1149.             for _,u in ipairs(Spring.GetTeamUnitsByDefs(t,{worm,wormold})) do
  1150.                 local firestate=Spring.GetUnitStates(u).firestate
  1151.                 if(firestate~=2) then
  1152.                     KPAIDebugMessage(t,"found worm["..u.."] in firestate="..firestate)
  1153.                     Spring.GiveOrderToUnit(u,CMD.FIRE_STATE,{2},{})
  1154.                 end
  1155.             end
  1156.             for _,u in ipairs(Spring.GetTeamUnitsByDefs(t,exploit)) do
  1157.                 local target=Spring.GetUnitNearestEnemy(u,1100)
  1158.                 if (not target) or Spring.GetUnitSeparation(u,target)<500 then
  1159.                     KPAIDebugMessage(t,"Undeploy")
  1160.                     Spring.GiveOrderToUnit(u,CMD_UNDEPLOY,{},{})
  1161.                 end
  1162.             end
  1163.             for _,u in ipairs(Spring.GetTeamUnitsByDefs(t,bug)) do
  1164.                 local c = Spring.GetUnitCommands(u)
  1165.                 local x,_,z=Spring.GetUnitPosition(u)
  1166.                 if ((not c) or #c<1) and not IsItOccupied(x,z) then
  1167.                     local target=Spring.GetUnitNearestEnemy(u,1000)
  1168.                     if target and (Spring.GetUnitSeparation(u,target)>600) then
  1169.                         KPAIDebugMessage(t,"bombard!")
  1170.                         td.missions[u]=true
  1171.                         Spring.GiveOrderToUnit(u,CMD_DEPLOY,{},{})
  1172.                     end
  1173.                 end
  1174.             end
  1175.             SuicideIfAlone(t)
  1176.         end
  1177.         PositionsStatesChanged=false
  1178.     end
  1179. end
  1180.  
  1181. else
  1182.  
  1183. --UNSYNCED
  1184.  
  1185. --return false
  1186.  
  1187. function gadget:DrawWorldPreUnit()
  1188.     local team = Spring.GetLocalTeamID()
  1189.     if SYNCED.KPAI_Debug_Mode and SYNCED.KPAI_Debug_Mode>0 and SYNCED.teamData and SYNCED.teamData[team] then
  1190.         --local OwnColor={Spring.GetTeamColor(team)}
  1191.         --local EnemyColor={1-OwnColor[1],1-OwnColor[2],1-OwnColor[3],0.5}
  1192.         local     OwnColor = {0,1,0,0.5}
  1193.         local   EmptyColor = {1,1,0,0.5}
  1194.         local   EnemyColor = {1,0,0,0.5}
  1195.         local  LockedColor = {1,0,1,0.5}
  1196.         local UnknownColor = {0,1,1,0.5}
  1197.         local size=32
  1198.         if Spring.GetModOptions()["ons"] and Spring.GetModOptions()["ons"]~="0" then
  1199.             size=96
  1200.         end
  1201.         for _,p in spairs(SYNCED.teamData[team].positions) do
  1202.             if p.state == STATE_EMPTY then
  1203.                 gl.Color(unpack(EmptyColor))
  1204.             elseif p.state == STATE_OWN then
  1205.                 gl.Color(unpack(OwnColor))
  1206.             elseif p.state == STATE_ENEMY then
  1207.                 gl.Color(unpack(EnemyColor))
  1208.             elseif p.state == STATE_LOCKED then
  1209.                 gl.Color(unpack(LockedColor))
  1210.             else
  1211.                 gl.Color(unpack(UnknownColor))
  1212.             end
  1213.             gl.DrawGroundQuad(p.x - size, p.z - size, p.x + size, p.z + size)
  1214.         end
  1215.     end
  1216.     gl.Color(1,1,1,1)
  1217. end
  1218.  
  1219. end
  1220.  
Advertisement
Add Comment
Please, Sign In to add comment