Advertisement
Guest User

Untitled

a guest
Jan 20th, 2018
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.01 KB | None | 0 0
  1. -- Fighter AI v2.1
  2.  
  3. -- IF YOU USE AN AI CARD SET MIN ALTITUDE LOW ENOUGH TO ALLOW ATTACK RUNS
  4.  
  5. minAlt = 50   -- match at least this with the AI card
  6. maxAlt = 400
  7.  
  8. controllingMainframe = 0     --the mainframe with the target prioritization card
  9. restrictSlot = 0             --ai will only control these weapons, and will orient the craft along those
  10.  
  11. onlyBomberRun = 0            -- set to 1 for only doing target/break sequences.
  12. maneuverDistanceFactor = 3   -- increase this if your plane needs more distance between attack run
  13. minimumThrust = 0.05         -- used when behind the enemy to slow down and keep it in target longer
  14.  
  15. spaceWhenIdle = 0            --set to 1 if you don't have a AI Plane card
  16.  
  17. dampening = 10                -- derivative term - reduce wobbling
  18. multiplyer = 1               -- proportional term - stronger control response
  19. corrective = 0.1             -- integrative term - helps craft that fly with an offset
  20. falloff = 1.2                 -- tune sustained control response falloff
  21. neutralPitch = 0.01               -- fixed control offset to nose up
  22.  
  23. pYaw = 0
  24. pPitch = 0
  25. pRoll = 0
  26.  
  27. iYaw = 0
  28. iPitch = 0
  29. iRoll = 0
  30.  
  31.  
  32.  
  33. function flyAlong(I, direction, normal, seed, thrust)
  34.     I:RequestThrustControl(0, thrust)
  35.    
  36.     I:RequestControl(2,8,thrust)
  37.     logstr = ""
  38.    
  39.     --I:RequestControl(mode,type,drive)
  40.     eYaw =  Vector3.Dot(
  41.             Vector3.ProjectOnPlane(direction, I:GetConstructUpVector() ).normalized,
  42.             I:GetConstructRightVector()
  43.             )
  44.     ePitch = Vector3.Dot(
  45.             Vector3.ProjectOnPlane(direction, I:GetConstructRightVector() ).normalized,
  46.             I:GetConstructUpVector()
  47.             )
  48.     eRoll = Vector3.Dot(
  49.             Vector3.ProjectOnPlane(normal, I:GetConstructForwardVector() ).normalized,
  50.             I:GetConstructRightVector()
  51.             )
  52.    
  53.     dPitch = ePitch - pPitch
  54.     dYaw = eYaw - pYaw
  55.     dRoll = eRoll - pRoll
  56.    
  57.     pYaw   = eYaw
  58.     pPitch = ePitch
  59.     pRoll  = eRoll
  60.  
  61.     iYaw   = (iYaw / (falloff) + eYaw)
  62.     iPitch  = (iPitch / (falloff) + ePitch)
  63.     iRoll  = (iRoll / (falloff) + eRoll)
  64.  
  65.     mul = multiplyer
  66.     damp = dampening
  67.    
  68.     CYaw   = mul * pYaw    + dYaw * damp + iYaw * corrective
  69.     CPitch = mul * pPitch  + dPitch * damp + iPitch * corrective + neutralPitch
  70.     CRoll  = mul * pRoll   + dRoll * damp + iRoll * corrective
  71.  
  72.     if ( CYaw < 0 ) then
  73.             --turn left
  74.             I:RequestControl(2,0,-CYaw)
  75.             I:RequestControl(2,1,0)
  76.             logstr = logstr .. " left " .. -CYaw
  77.     else
  78.             --turn right
  79.             I:RequestControl(2,1,CYaw)
  80.             I:RequestControl(2,0,0)
  81.             logstr = logstr .. " right " ..CYaw
  82.     end
  83.     if ( CPitch < 0 ) then
  84.             --pitch down
  85.             I:RequestControl(2,5,-CPitch)
  86.             I:RequestControl(2,4,0)
  87.             logstr = logstr .. " down " .. -CPitch
  88.     else
  89.             --pitch up
  90.             I:RequestControl(2,4,CPitch)
  91.             I:RequestControl(2,5,0)
  92.             logstr = logstr .. " up " .. CPitch
  93.     end    
  94.            
  95.     if ( CRoll < 0 ) then
  96.             --0. roll left
  97.             logstr = logstr .. " rccw " .. -CRoll
  98.             I:RequestControl(2,2,-CRoll)
  99.             I:RequestControl(2,3,0)
  100.     else
  101.             -- roll right  
  102.             I:RequestControl(2,3,CRoll)
  103.             I:RequestControl(2,2,0)
  104.             logstr = logstr .. " rcw " .. CRoll
  105.  
  106.     end
  107.     --I:LogToHud(logstr)
  108. end
  109.  
  110.  
  111.  
  112.  
  113. function killThatThing(I, weaponInfo, targetInfo, weaponIndex, turretSpinnerIndex)
  114.  
  115.     P = targetInfo.AimPointPosition
  116.     V = targetInfo.Velocity
  117.     WS = weaponInfo.Speed
  118.     G = I:GetGravityForAltitude(P.y).magnitude
  119.    
  120.     if (WS > 100000) then
  121.     AD =  P - weaponInfo.GlobalPosition
  122.     if(turretSpinnerIndex < 0) then
  123.            I:AimWeaponInDirection(weaponIndex, AD.x, AD.y, AD.z, weaponInfo.WeaponSlot)
  124.            I:FireWeapon(weaponIndex, weaponInfo.WeaponSlot)
  125.         else
  126.            I:AimWeaponInDirectionOnTurretOrSpinner(
  127.                  turretSpinnerIndex,weaponIndex, AD.x, AD.y, AD.z, weaponInfo.WeaponSlot)
  128.  
  129.          if (attackState == TARGET) then
  130.            I:FireWeaponOnTurretOrSpinner(
  131.                  turretSpinnerIndex,weaponIndex,weaponInfo.WeaponSlot)
  132.          end
  133.  
  134.         end
  135.         return AD
  136.     end
  137.  
  138.     T = (P - weaponInfo.GlobalPosition).magnitude / (WS*0.85) -- FIRST ESTIMATE OF FUTURE TARGET POSITION
  139.  
  140.  
  141.     FP = P + V*T  - I:GetVelocityVector()*T
  142.  -- position the target will be
  143.  
  144.     AD = FP - weaponInfo.GlobalPosition
  145.   -- direction direct to the target
  146.  
  147.  
  148.  
  149.     PJ = Mathf.Sqrt(AD.x*AD.x + AD.z*AD.z)
  150.  -- horizontal distance to the target
  151.  
  152.    
  153.     S2 = WS*WS
  154.   -- speed^2
  155.     S4 = S2*WS*WS
  156.   -- speed^4 (need these many times)
  157.     DELTA = S4 - G*(G*PJ*PJ + 2*AD.y * S2)
  158.  -- is there a solution to the parable?
  159.      
  160.  
  161.     if ( DELTA > 0 ) then
  162.         --ok we can reach it and now we have a better estimate
  163.        
  164.         AG = Mathf.Atan2(S2 - Mathf.Sqrt(DELTA),G*PJ)
  165.  --calculate angle
  166.        
  167.         --now we can calculate a better time to target using the horizontal speed
  168.         --as obtained from the firing angle
  169.        
  170. T = (P - weaponInfo.GlobalPosition).magnitude / (WS * Mathf.Cos(AG))
  171.        
  172.  
  173.         FP = P + V*T - I:GetVelocityVector()*T
  174.   --position target will be
  175.  
  176.         AD = FP - weaponInfo.GlobalPosition
  177.  -- line direct to the target position
  178.  
  179.  
  180.  
  181.         PJ = Mathf.Sqrt(AD.x*AD.x + AD.z*AD.z)
  182.   -- horizontal distance to the target
  183.  
  184.    
  185.      
  186.         DELTA = S4 - G*(G*PJ*PJ + 2*AD.y * S2)
  187.  -- check the parable solution
  188.  
  189.  
  190.         if ( DELTA > 0 ) then
  191.         --ok we can reach it and now we have a better estimate
  192.         PY = (S2 - Mathf.Sqrt(DELTA))/(G)
  193.  -- no need to calculate angle or tangent, just the elev
  194.  
  195.  
  196.  
  197.         AD.y = PY --assign new elevation to the firing direction
  198.  
  199.  
  200.         if(turretSpinnerIndex < 0) then
  201.            I:AimWeaponInDirection(weaponIndex, AD.x, AD.y, AD.z, weaponInfo.WeaponSlot)
  202.            I:FireWeapon(weaponIndex, weaponInfo.WeaponSlot)
  203.         else
  204.            I:AimWeaponInDirectionOnTurretOrSpinner(
  205.                  turretSpinnerIndex,weaponIndex, AD.x, AD.y, AD.z, weaponInfo.WeaponSlot)
  206.  
  207.          if (attackState == TARGET) then
  208.            I:FireWeaponOnTurretOrSpinner(
  209.                  turretSpinnerIndex,weaponIndex,weaponInfo.WeaponSlot)
  210.          end
  211.  
  212.         end
  213.  
  214.       end
  215.          
  216.     end
  217.    return AD
  218. end
  219.  
  220. function idleAround(I)
  221.     idlePosition = I:GetConstructCenterOfMass()
  222.     com = I:GetConstructCenterOfMass()
  223.     fcom = I:GetConstructCenterOfMass() + I:GetVelocityVector()
  224.     if (I:GetFriendlyCount() > 0) then
  225.         idlePosition = idlePosition / I:GetFriendlyCount()
  226.         for friendlyIndex=0, I:GetFriendlyCount() do
  227.             friendlyInfo = I:GetFriendlyInfo(friendlyIndex)
  228.             idlePosition = friendlyInfo.ReferencePosition / I:GetFriendlyCount()
  229.         end
  230.     end
  231.    
  232.     flyDirection = I:GetConstructCenterOfMass()-I:GetVelocityVector()-idlePosition
  233.         if (com.y < I:GetTerrainAltitudeForLocalPosition(com.x,0,com.z) + minAlt or
  234.          fcom.y < I:GetTerrainAltitudeForLocalPosition(fcom.x,0,fcom.z) + minAlt or
  235.          com.y < minAlt) then
  236.       flyDirection = Vector3(0,1,0)
  237.        
  238.     I:Component_SetBoolLogicAll(0, true)
  239.     else
  240.     I:Component_SetBoolLogicAll(0, false)
  241.     end
  242.     flyAlong(I, flyDirection, -I:GetGravityForAltitude(I:GetConstructCenterOfMass().y), 0 , thrust)
  243. end
  244.  
  245.  
  246.  
  247. BREAK = 0 -- close in to target at max altitude
  248. SPLIT = 1 -- match target direction rolling down/up according to start alt
  249. ROLL = 2 -- if enemy vector are parallel, roll into tail
  250. TARGET = 3 -- aim to a shoot solution
  251. RUN = 4 -- too close and enemy not fast enough
  252. LOOP = 5 --enemy is faster loop on it's tail
  253. YOYO = 6
  254. EVADE = 9
  255. TURNFIGHT = 8
  256. EC = 7
  257.  
  258. attackState = TARGET
  259.  
  260. function performManeuver(I,targetInfo,attackState, situation)
  261.     --some random defaults
  262.     flyDirection = -I:GetGravityForAltitude(situation.com.y)
  263.     flyNormal = -I:GetGravityForAltitude(situation.com.y)
  264.     thrust = 1
  265.     if (attackState == EC) then
  266.        
  267.         flyDirection = I:GetConstructForwardVector().normalized
  268.         flyDirection.y = 0.5
  269.        
  270.         flyNormal =  -I:GetGravityForAltitude(situation.com.y)
  271.         I:Component_SetBoolLogicAll(0, true)
  272.     else
  273.         I:Component_SetBoolLogicAll(0, false)
  274.     end
  275.  
  276.     if (attackState == TARGET) then
  277.        
  278.         flyNormal = (situation.attackDirection + Vector3(0,2,0)).normalized
  279.         flyNormal.y = 0.5
  280.         if(situation.forwardiness < -0.3) then
  281.             flyDirection = Vector3.Cross(situation.targetDirection, I:GetGravityForAltitude(situation.com.y)).normalized
  282.             flyDirection.y = 0.0
  283.             flyNormal = - situation.targetDirection
  284.             if (situation.operationAltitude > 0.5) then
  285.                 flyDirection.y = -situation.operationAltitude
  286.             end
  287.             if (situation.operationAltitude< -0.5) then
  288.                 flyDirection.y = situation.operationAltitude
  289.             end
  290.         else
  291.             flyDirection = situation.attackDirection
  292.         end
  293.         if (situation.accordingness > 0 and situation.forwardiness > 0 and situation.separationFactor < 8) then
  294.             if (situation.speedFactor > 1 and I:GetHealthFraction() == 1) then
  295.                 thrust = minimumThrust
  296.             end
  297.         end
  298.     end
  299.    
  300.     if (attackState == BREAK or attackState == EVADE) then
  301.        
  302.         if(situation.forwardiness > 0.1) then
  303.             flyDirection = Vector3.Cross(situation.targetDirection, I:GetGravityForAltitude(situation.com.y)).normalized
  304.             flyDirection.y = 0.0
  305.             flyNormal = - situation.targetDirection
  306.             if (situation.operationAltitude > 0.5) then
  307.                 flyDirection.y = situation.operationAltitude
  308.             end
  309.             if (situation.operationAltitude< -0.5) then
  310.                 flyDirection.y = -situation.operationAltitude
  311.             end
  312.         else
  313.             flyDirection = -situation.targetDirection
  314.             flyDirection.y = -Mathf.Sign(situation.operationAltitude)
  315.             if (situation.operationAltitude > 0.5) then
  316.                 flyDirection.y = situation.operationAltitude
  317.             end
  318.             if (situation.operationAltitude< -0.5) then
  319.                 flyDirection.y = -situation.operationAltitude
  320.             end
  321.  
  322.  
  323.             flyNormal = Vector3(0,1,0)
  324.         end
  325.     end
  326.     if (attackState == YOYO) then
  327.        
  328.         flyDirection = Vector3(0,-situation.operationAltitude,0)
  329.         flyNormal = situation.targetDirection
  330.     end
  331.     if (attackState == ROLL) then
  332.        
  333.         flyDirection =  situation.targetDirection + Vector3(0,-situation.operationAltitude,0) +  I:GetConstructRightVector() * situation.rightness
  334.         flyNormal = situation.targetDirection
  335.     end
  336.    
  337.     if (attackState == TURNFIGHT) then
  338.        
  339.         flyDirection =  Vector3.Cross(situation.targetDirection.normalized, -I:GetGravityForAltitude(situation.com.y))
  340.         flyNormal = situation.targetDirection
  341.     end
  342.    
  343.     if (attackState == LOOP) then
  344.        
  345.         flyDirection =  -situation.targetVelocity +  Vector3(0, -situation.operationAltitude,0)
  346.         flyNormal = situation.targetDirection
  347.     end
  348.    
  349.     flyNormal = flyNormal.normalized
  350.     if (onlyBomberRun > 0 and flyNormal.y  >0.1) then flyNormal.y = 0.1 end
  351.     if (onlyBomberRun > 0 and flyNormal.y  <-0.1) then flyNormal.y = -0.1 end
  352.     if (situation.futurecom.y < minAlt) then flyNormal.y = 0.4 end
  353.     if (situation.futurecom.y > maxAlt) then flyNormal.y = -0.4 end
  354.    
  355.     flyAlong(I, flyDirection, flyNormal, situation.decisionSeed, thrust)
  356. end
  357.  
  358.  
  359.  
  360. limit = 0
  361. function attackEnemy(I, AD, targetInfo)
  362.     situation = {}
  363.  
  364.     situation.com = I:GetConstructCenterOfMass()
  365.     situation.futurecom = situation.com + I:GetVelocityVector()
  366.     situation.attackDirection = AD
  367.     situation.targetPosition = targetInfo.AimPointPosition
  368.     situation.targetVelocity = targetInfo.Velocity
  369.     situation.targetDirection = situation.targetPosition - I:GetConstructCenterOfMass()
  370.    
  371.     situation.forwardiness = Vector3.Dot(situation.targetDirection.normalized, I:GetConstructForwardVector())
  372.     situation.uppiness = Vector3.Dot(situation.targetDirection.normalized, I:GetConstructUpVector())
  373.     situation.rightness = Vector3.Dot(situation.targetDirection.normalized, I:GetConstructRightVector())
  374.     situation.accordingness = Vector3.Dot(situation.targetVelocity.normalized, I:GetVelocityVector().normalized)
  375.    
  376.     situation.distance = situation.targetDirection.magnitude
  377.    
  378.     situation.separation = (situation.targetDirection + situation.targetVelocity  - I:GetVelocityVector()).magnitude
  379.    
  380.     situation.operationAltitude = 2*(situation.com.y - minAlt)/(maxAlt-minAlt) - 1   -- -1 .. 1
  381.     situation.targetAltitude = 2*(situation.targetPosition.y - minAlt)/(maxAlt-minAlt) - 1   -- -1 .. 1
  382.    
  383.     situation.speedFactor = I:GetVelocityVector().magnitude / (situation.targetVelocity.magnitude+0.01)
  384.  
  385.     situation.decisionSeed = ((I:GetConstructForwardVector().x + I:GetConstructForwardVector().y + I:GetConstructForwardVector().z)*534534545353.0)%100    
  386.  
  387.     situation.distanceFactor = maneuverDistanceFactor * situation.distance / I:GetVelocityVector().magnitude
  388.     situation.separationFactor = maneuverDistanceFactor * situation.distance /  I:GetVelocityVector().magnitude
  389.  
  390.    
  391.     -- break to recover after an emergency climb
  392.     if (attackState == EC and situation.operationAltitude > 0 ) then
  393.         attackState = BREAK
  394.     end
  395.     -- target enemy if we're far enough
  396.     if (situation.distanceFactor >  10 ) then  
  397.         attackState = TARGET
  398.     end
  399.  
  400.     if (situation.accordingness >  0 and situation.separationFactor > 6 ) then  
  401.         attackState = TARGET
  402.     end
  403.  
  404.    
  405.     if (attackState == TARGET and situation.separationFactor <  4 ) then  
  406.         if (onlyBomberRun == 1) then
  407.             attackState = BREAK
  408.         else
  409.             if (situation.decisionSeed < 33) then
  410.                 attackState = YOYO
  411.             end
  412.             if (situation.decisionSeed > 32 and situation.decisionSeed < 66) then
  413.                 attackState = ROLL
  414.             end
  415.             if (situation.decisionSeed > 65) then
  416.                 attackState = LOOP
  417.             end
  418.         end
  419.    
  420.     end
  421.    
  422.    
  423.     --emergency upcode
  424.     if (situation.com.y < I:GetTerrainAltitudeForLocalPosition(situation.com.x,0,situation.com.z) + minAlt or
  425.             situation.futurecom.y < I:GetTerrainAltitudeForLocalPosition(situation.futurecom.x,0,situation.futurecom.z) or
  426.             situation.com.y < minAlt) then
  427.        attackState = EC
  428.     end
  429.     --emergency evade
  430.     if (situation.separationFactor <  2 or situation.distanceFactor < 1) then  
  431.         attackState = EVADE
  432.     end
  433.  
  434.     performManeuver(I,targetInfo,attackState, situation)
  435.  
  436. end
  437.  
  438.  
  439. function Update(I)
  440.    
  441.     targetInfo = I:GetTargetInfo(controllingMainframe, 0)
  442.     AttackDirection = nil
  443.    
  444.     otherInfo = targetInfo
  445.     --check all other targets and break from any too close to comfort irregardless of priority
  446.     for targetIndex=0,I:GetNumberOfTargets(controllingMainframe) do
  447.         otherInfo = I:GetTargetInfo(controllingMainframe, targetIndex)
  448.         situation = {}
  449.         situation.com = I:GetConstructCenterOfMass()
  450.         situation.targetPosition = otherInfo.AimPointPosition
  451.         situation.targetVelocity = otherInfo.Velocity
  452.         situation.targetDirection = situation.targetPosition - situation.com
  453.        
  454.        
  455.         situation.separation = (situation.targetDirection + situation.targetVelocity  - I:GetVelocityVector()).magnitude
  456.            
  457.        
  458.         if (situation.separation < I:GetVelocityVector().magnitude) then
  459.             targetInfo = otherInfo
  460.         end
  461.     end
  462.    
  463.    
  464.     if(targetInfo.Valid) then
  465.         for weaponIndex=0,I:GetWeaponCount() do
  466.           weaponInfo = I:GetWeaponInfo(weaponIndex)
  467.      
  468.           if ((weaponInfo.WeaponType == 4 or weaponInfo.WeaponType == 0 or weaponInfo.WeaponType == 2)
  469.                and weaponInfo.Valid and weaponInfo.PlayerCurrentlyControllingIt == false
  470.                and weaponInfo.WeaponSlot == restrictSlot) then
  471.                AttackDirection = killThatThing(I, weaponInfo, targetInfo, weaponIndex, -1)
  472.           end
  473.         end
  474.        
  475.         for turretSpinnerIndex=0,I:GetTurretSpinnerCount() do
  476.             for weaponIndex=0,I:GetWeaponCountOnTurretOrSpinner(turretSpinnerIndex) do
  477.               weaponInfo = I:GetWeaponInfoOnTurretOrSpinner(turretSpinnerIndex, weaponIndex)
  478.                 if ((weaponInfo.WeaponType == 4 or weaponInfo.WeaponType == 0 or weaponInfo.WeaponType == 2)
  479.                 and weaponInfo.Valid and weaponInfo.PlayerCurrentlyControllingIt == false
  480.                 and weaponInfo.WeaponSlot == restrictSlot ) then
  481.                 AttackDirection = killThatThing(I, weaponInfo, targetInfo, weaponIndex, turretSpinnerIndex)
  482.                 end
  483.             end
  484.         end
  485.         if (AttackDirection == nil) then
  486.             P = targetInfo.AimPointPosition
  487.             V = targetInfo.Velocity
  488.        
  489.             FP = P + V
  490.        
  491.          
  492.              I:LogToHud("No weapon configured!!")
  493.             AttackDirection = FP - I:GetConstructCenterOfMass()
  494.         end
  495.         attackEnemy(I, AttackDirection, targetInfo)    
  496.         I:TellAiThatWeAreTakingControl()
  497.     end
  498.        
  499. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement