Advertisement
Guest User

Untitled

a guest
Jan 20th, 2018
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 15.39 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.05               -- 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.     T = (P - weaponInfo.GlobalPosition).magnitude / (WS*0.85) -- FIRST ESTIMATE OF FUTURE TARGET POSITION
  121.  
  122.  
  123.     FP = P + V*T  - I:GetVelocityVector()*T
  124.  -- position the target will be
  125.  
  126.     AD = FP - weaponInfo.GlobalPosition
  127.   -- direction direct to the target
  128.  
  129.  
  130.  
  131.     PJ = Mathf.Sqrt(AD.x*AD.x + AD.z*AD.z)
  132.  -- horizontal distance to the target
  133.  
  134.    
  135.     S2 = WS*WS
  136.   -- speed^2
  137.     S4 = S2*WS*WS
  138.   -- speed^4 (need these many times)
  139.     DELTA = S4 - G*(G*PJ*PJ + 2*AD.y * S2)
  140.  -- is there a solution to the parable?
  141.      
  142.  
  143.     if ( DELTA > 0 ) then
  144.         --ok we can reach it and now we have a better estimate
  145.        
  146.         AG = Mathf.Atan2(S2 - Mathf.Sqrt(DELTA),G*PJ)
  147.  --calculate angle
  148.        
  149.         --now we can calculate a better time to target using the horizontal speed
  150.         --as obtained from the firing angle
  151.        
  152. T = (P - weaponInfo.GlobalPosition).magnitude / (WS * Mathf.Cos(AG))
  153.        
  154.  
  155.         FP = P + V*T - I:GetVelocityVector()*T
  156.   --position target will be
  157.  
  158.         AD = FP - weaponInfo.GlobalPosition
  159.  -- line direct to the target position
  160.  
  161.  
  162.  
  163.         PJ = Mathf.Sqrt(AD.x*AD.x + AD.z*AD.z)
  164.   -- horizontal distance to the target
  165.  
  166.    
  167.      
  168.         DELTA = S4 - G*(G*PJ*PJ + 2*AD.y * S2)
  169.  -- check the parable solution
  170.  
  171.  
  172.         if ( DELTA > 0 ) then
  173.         --ok we can reach it and now we have a better estimate
  174.         PY = (S2 - Mathf.Sqrt(DELTA))/(G)
  175.  -- no need to calculate angle or tangent, just the elev
  176.  
  177.  
  178.  
  179.         AD.y = PY --assign new elevation to the firing direction
  180.  
  181.  
  182.         if(turretSpinnerIndex < 0) then
  183.            I:AimWeaponInDirection(weaponIndex, AD.x, AD.y, AD.z, weaponInfo.WeaponSlot)
  184.            I:FireWeapon(weaponIndex, weaponInfo.WeaponSlot)
  185.         else
  186.            I:AimWeaponInDirectionOnTurretOrSpinner(
  187.                  turretSpinnerIndex,weaponIndex, AD.x, AD.y, AD.z, weaponInfo.WeaponSlot)
  188.  
  189.          if (attackState == TARGET) then
  190.            I:FireWeaponOnTurretOrSpinner(
  191.                  turretSpinnerIndex,weaponIndex,weaponInfo.WeaponSlot)
  192.          end
  193.  
  194.         end
  195.  
  196.       end
  197.          
  198.     end
  199.    return AD
  200. end
  201.  
  202. function idleAround(I)
  203.     idlePosition = I:GetConstructCenterOfMass()
  204.     com = I:GetConstructCenterOfMass()
  205.     fcom = I:GetConstructCenterOfMass() + I:GetVelocityVector()
  206.     if (I:GetFriendlyCount() > 0) then
  207.         idlePosition = idlePosition / I:GetFriendlyCount()
  208.         for friendlyIndex=0, I:GetFriendlyCount() do
  209.             friendlyInfo = I:GetFriendlyInfo(friendlyIndex)
  210.             idlePosition = friendlyInfo.ReferencePosition / I:GetFriendlyCount()
  211.         end
  212.     end
  213.    
  214.     flyDirection = I:GetConstructCenterOfMass()-I:GetVelocityVector()-idlePosition
  215.         if (com.y < I:GetTerrainAltitudeForLocalPosition(com.x,0,com.z) + minAlt or
  216.          fcom.y < I:GetTerrainAltitudeForLocalPosition(fcom.x,0,fcom.z) + minAlt or
  217.          com.y < minAlt) then
  218.       flyDirection = Vector3(0,1,0)
  219.        
  220.     I:Component_SetBoolLogicAll(0, true)
  221.     else
  222.     I:Component_SetBoolLogicAll(0, false)
  223.     end
  224.     flyAlong(I, flyDirection, -I:GetGravityForAltitude(I:GetConstructCenterOfMass().y), 0 , thrust)
  225. end
  226.  
  227.  
  228.  
  229. BREAK = 0 -- close in to target at max altitude
  230. SPLIT = 1 -- match target direction rolling down/up according to start alt
  231. ROLL = 2 -- if enemy vector are parallel, roll into tail
  232. TARGET = 3 -- aim to a shoot solution
  233. RUN = 4 -- too close and enemy not fast enough
  234. LOOP = 5 --enemy is faster loop on it's tail
  235. YOYO = 6
  236. EVADE = 9
  237. TURNFIGHT = 8
  238. EC = 7
  239.  
  240. attackState = TARGET
  241.  
  242. function performManeuver(I,targetInfo,attackState, situation)
  243.     --some random defaults
  244.     flyDirection = -I:GetGravityForAltitude(situation.com.y)
  245.     flyNormal = -I:GetGravityForAltitude(situation.com.y)
  246.     thrust = 1
  247.     if (attackState == EC) then
  248.        
  249.         flyDirection = I:GetConstructForwardVector().normalized
  250.         flyDirection.y = 0.5
  251.        
  252.         flyNormal =  -I:GetGravityForAltitude(situation.com.y)
  253.         I:Component_SetBoolLogicAll(0, true)
  254.     else
  255.         I:Component_SetBoolLogicAll(0, false)
  256.     end
  257.  
  258.     if (attackState == TARGET) then
  259.        
  260.         flyNormal = (situation.attackDirection + Vector3(0,2,0)).normalized
  261.         flyNormal.y = 0.5
  262.         if(situation.forwardiness < -0.3) then
  263.             flyDirection = Vector3.Cross(situation.targetDirection, I:GetGravityForAltitude(situation.com.y)).normalized
  264.             flyDirection.y = 0.0
  265.             flyNormal = - situation.targetDirection
  266.             if (situation.operationAltitude > 0.5) then
  267.                 flyDirection.y = -situation.operationAltitude
  268.             end
  269.             if (situation.operationAltitude< -0.5) then
  270.                 flyDirection.y = situation.operationAltitude
  271.             end
  272.         else
  273.             flyDirection = situation.attackDirection
  274.         end
  275.         if (situation.accordingness > 0 and situation.forwardiness > 0 and situation.separationFactor < 8) then
  276.             if (situation.speedFactor>1 and I:GetHealthFraction() > 0.99) then
  277.                 thrust = minimumThrust
  278.             end
  279.         end
  280.     end
  281.    
  282.     if (attackState == BREAK or attackState == EVADE) then
  283.        
  284.         if(situation.forwardiness > 0.1) then
  285.             flyDirection = Vector3.Cross(situation.targetDirection, I:GetGravityForAltitude(situation.com.y)).normalized
  286.             flyDirection.y = 0.0
  287.             flyNormal = - situation.targetDirection
  288.             if (situation.operationAltitude > 0.5) then
  289.                 flyDirection.y = situation.operationAltitude
  290.             end
  291.             if (situation.operationAltitude< -0.5) then
  292.                 flyDirection.y = -situation.operationAltitude
  293.             end
  294.         else
  295.             flyDirection = -situation.targetDirection
  296.             flyDirection.y = -Mathf.Sign(situation.operationAltitude)
  297.             if (situation.operationAltitude > 0.5) then
  298.                 flyDirection.y = situation.operationAltitude
  299.             end
  300.             if (situation.operationAltitude< -0.5) then
  301.                 flyDirection.y = -situation.operationAltitude
  302.             end
  303.  
  304.  
  305.             flyNormal = Vector3(0,1,0)
  306.         end
  307.     end
  308.     if (attackState == YOYO) then
  309.        
  310.         flyDirection = Vector3(0,-situation.operationAltitude,0)
  311.         flyNormal = situation.targetDirection
  312.     end
  313.     if (attackState == ROLL) then
  314.        
  315.         flyDirection =  situation.targetDirection + Vector3(0,-situation.operationAltitude,0) +  I:GetConstructRightVector() * situation.rightness
  316.         flyNormal = situation.targetDirection
  317.     end
  318.    
  319.     if (attackState == TURNFIGHT) then
  320.        
  321.         flyDirection =  Vector3.Cross(situation.targetDirection.normalized, -I:GetGravityForAltitude(situation.com.y))
  322.         flyNormal = situation.targetDirection
  323.     end
  324.    
  325.     if (attackState == LOOP) then
  326.        
  327.         flyDirection =  -situation.targetVelocity +  Vector3(0, -situation.operationAltitude,0)
  328.         flyNormal = situation.targetDirection
  329.     end
  330.    
  331.     flyNormal = flyNormal.normalized
  332.     if (onlyBomberRun > 0 and flyNormal.y  >0.1) then flyNormal.y = 0.1 end
  333.     if (onlyBomberRun > 0 and flyNormal.y  <-0.1) then flyNormal.y = -0.1 end
  334.     if (situation.futurecom.y < minAlt) then flyNormal.y = 0.4 end
  335.     if (situation.futurecom.y > maxAlt) then flyNormal.y = -0.4 end
  336.    
  337.     flyAlong(I, flyDirection, flyNormal, situation.decisionSeed, thrust)
  338. end
  339.  
  340.  
  341.  
  342. limit = 0
  343. function attackEnemy(I, AD, targetInfo)
  344.     situation = {}
  345.  
  346.     situation.com = I:GetConstructCenterOfMass()
  347.     situation.futurecom = situation.com + I:GetVelocityVector()
  348.     situation.attackDirection = AD
  349.     situation.targetPosition = targetInfo.AimPointPosition
  350.     situation.targetVelocity = targetInfo.Velocity
  351.     situation.targetDirection = situation.targetPosition - I:GetConstructCenterOfMass()
  352.    
  353.     situation.forwardiness = Vector3.Dot(situation.targetDirection.normalized, I:GetConstructForwardVector())
  354.     situation.uppiness = Vector3.Dot(situation.targetDirection.normalized, I:GetConstructUpVector())
  355.     situation.rightness = Vector3.Dot(situation.targetDirection.normalized, I:GetConstructRightVector())
  356.     situation.accordingness = Vector3.Dot(situation.targetVelocity.normalized, I:GetVelocityVector().normalized)
  357.    
  358.     situation.distance = situation.targetDirection.magnitude
  359.    
  360.     situation.separation = (situation.targetDirection + situation.targetVelocity  - I:GetVelocityVector()).magnitude
  361.    
  362.     situation.operationAltitude = 2*(situation.com.y - minAlt)/(maxAlt-minAlt) - 1   -- -1 .. 1
  363.     situation.targetAltitude = 2*(situation.targetPosition.y - minAlt)/(maxAlt-minAlt) - 1   -- -1 .. 1
  364.    
  365.     situation.speedFactor = I:GetVelocityVector().magnitude / (situation.targetVelocity.magnitude+0.01)
  366.  
  367.     situation.decisionSeed = ((I:GetConstructForwardVector().x + I:GetConstructForwardVector().y + I:GetConstructForwardVector().z)*534534545353.0)%100    
  368.  
  369.     situation.distanceFactor = maneuverDistanceFactor * situation.distance / I:GetVelocityVector().magnitude
  370.     situation.separationFactor = maneuverDistanceFactor * situation.distance /  I:GetVelocityVector().magnitude
  371.  
  372.    
  373.     -- break to recover after an emergency climb
  374.     if (attackState == EC and situation.operationAltitude > 0 ) then
  375.         attackState = BREAK
  376.     end
  377.     -- target enemy if we're far enough
  378.     if (situation.distanceFactor >  10 ) then  
  379.         attackState = TARGET
  380.     end
  381.  
  382.     if (situation.accordingness >  0 and situation.separationFactor > 6 ) then  
  383.         attackState = TARGET
  384.     end
  385.  
  386.    
  387.     if (attackState == TARGET and situation.separationFactor <  4 ) then  
  388.         if (onlyBomberRun == 1) then
  389.             attackState = BREAK
  390.         else
  391.             if (situation.decisionSeed < 33) then
  392.                 attackState = YOYO
  393.             end
  394.             if (situation.decisionSeed > 32 and situation.decisionSeed < 66) then
  395.                 attackState = ROLL
  396.             end
  397.             if (situation.decisionSeed > 65) then
  398.                 attackState = LOOP
  399.             end
  400.         end
  401.    
  402.     end
  403.    
  404.    
  405.     --emergency upcode
  406.     if (situation.com.y < I:GetTerrainAltitudeForLocalPosition(situation.com.x,0,situation.com.z) + minAlt or
  407.             situation.futurecom.y < I:GetTerrainAltitudeForLocalPosition(situation.futurecom.x,0,situation.futurecom.z) or
  408.             situation.com.y < minAlt) then
  409.        attackState = EC
  410.     end
  411.     --emergency evade
  412.     if (situation.separationFactor <  2 ) then  
  413.         attackState = EVADE
  414.     end
  415.  
  416.     performManeuver(I,targetInfo,attackState, situation)
  417.  
  418. end
  419.  
  420.  
  421. function Update(I)
  422.    
  423.     targetInfo = I:GetTargetInfo(controllingMainframe, 0)
  424.     AttackDirection = nil
  425.    
  426.     otherInfo = targetInfo
  427.     --check all other targets and break from any too close to comfort irregardless of priority
  428.     for targetIndex=0,I:GetNumberOfTargets(controllingMainframe) do
  429.         otherInfo = I:GetTargetInfo(controllingMainframe, targetIndex)
  430.         situation = {}
  431.         situation.com = I:GetConstructCenterOfMass()
  432.         situation.targetPosition = otherInfo.AimPointPosition
  433.         situation.targetVelocity = otherInfo.Velocity
  434.         situation.targetDirection = situation.targetPosition - situation.com
  435.        
  436.        
  437.         situation.separation = (situation.targetDirection + situation.targetVelocity  - I:GetVelocityVector()).magnitude
  438.            
  439.        
  440.         if (situation.separation < I:GetVelocityVector().magnitude) then
  441.             targetInfo = otherInfo
  442.         end
  443.     end
  444.    
  445.    
  446.     if(targetInfo.Valid) then
  447.         for weaponIndex=0,I:GetWeaponCount() do
  448.           weaponInfo = I:GetWeaponInfo(weaponIndex)
  449.      
  450.           if ((weaponInfo.WeaponType == 4 or weaponInfo.WeaponType == 0 or weaponInfo.WeaponType == 2)
  451.                and weaponInfo.Valid and weaponInfo.PlayerCurrentlyControllingIt == false
  452.                and weaponInfo.WeaponSlot == restrictSlot) then
  453.                AttackDirection = killThatThing(I, weaponInfo, targetInfo, weaponIndex, -1)
  454.           end
  455.         end
  456.        
  457.         for turretSpinnerIndex=0,I:GetTurretSpinnerCount() do
  458.             for weaponIndex=0,I:GetWeaponCountOnTurretOrSpinner(turretSpinnerIndex) do
  459.               weaponInfo = I:GetWeaponInfoOnTurretOrSpinner(turretSpinnerIndex, weaponIndex)
  460.                 if ((weaponInfo.WeaponType == 4 or weaponInfo.WeaponType == 0 or weaponInfo.WeaponType == 2)
  461.                 and weaponInfo.Valid and weaponInfo.PlayerCurrentlyControllingIt == false
  462.                 and weaponInfo.WeaponSlot == restrictSlot ) then
  463.                 AttackDirection = killThatThing(I, weaponInfo, targetInfo, weaponIndex, turretSpinnerIndex)
  464.                 end
  465.             end
  466.         end
  467.         if (AttackDirection == nil) then
  468.             P = targetInfo.AimPointPosition
  469.             V = targetInfo.Velocity
  470.        
  471.             FP = P + V
  472.        
  473.          
  474.              I:LogToHud("No weapon configured!!")
  475.             AttackDirection = FP - I:GetConstructCenterOfMass()
  476.         end
  477.         attackEnemy(I, AttackDirection, targetInfo)    
  478.         I:TellAiThatWeAreTakingControl()
  479.     end
  480.        
  481. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement