Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Fighter AI v2.1
- -- IF YOU USE AN AI CARD SET MIN ALTITUDE LOW ENOUGH TO ALLOW ATTACK RUNS
- minAlt = 50 -- match at least this with the AI card
- maxAlt = 400
- controllingMainframe = 0 --the mainframe with the target prioritization card
- restrictSlot = 0 --ai will only control these weapons, and will orient the craft along those
- onlyBomberRun = 0 -- set to 1 for only doing target/break sequences.
- maneuverDistanceFactor = 3 -- increase this if your plane needs more distance between attack run
- minimumThrust = 0.05 -- used when behind the enemy to slow down and keep it in target longer
- spaceWhenIdle = 0 --set to 1 if you don't have a AI Plane card
- dampening = 10 -- derivative term - reduce wobbling
- multiplyer = 1 -- proportional term - stronger control response
- corrective = 0.1 -- integrative term - helps craft that fly with an offset
- falloff = 1.2 -- tune sustained control response falloff
- neutralPitch = 0.01 -- fixed control offset to nose up
- pYaw = 0
- pPitch = 0
- pRoll = 0
- iYaw = 0
- iPitch = 0
- iRoll = 0
- function flyAlong(I, direction, normal, seed, thrust)
- I:RequestThrustControl(0, thrust)
- I:RequestControl(2,8,thrust)
- logstr = ""
- --I:RequestControl(mode,type,drive)
- eYaw = Vector3.Dot(
- Vector3.ProjectOnPlane(direction, I:GetConstructUpVector() ).normalized,
- I:GetConstructRightVector()
- )
- ePitch = Vector3.Dot(
- Vector3.ProjectOnPlane(direction, I:GetConstructRightVector() ).normalized,
- I:GetConstructUpVector()
- )
- eRoll = Vector3.Dot(
- Vector3.ProjectOnPlane(normal, I:GetConstructForwardVector() ).normalized,
- I:GetConstructRightVector()
- )
- dPitch = ePitch - pPitch
- dYaw = eYaw - pYaw
- dRoll = eRoll - pRoll
- pYaw = eYaw
- pPitch = ePitch
- pRoll = eRoll
- iYaw = (iYaw / (falloff) + eYaw)
- iPitch = (iPitch / (falloff) + ePitch)
- iRoll = (iRoll / (falloff) + eRoll)
- mul = multiplyer
- damp = dampening
- CYaw = mul * pYaw + dYaw * damp + iYaw * corrective
- CPitch = mul * pPitch + dPitch * damp + iPitch * corrective + neutralPitch
- CRoll = mul * pRoll + dRoll * damp + iRoll * corrective
- if ( CYaw < 0 ) then
- --turn left
- I:RequestControl(2,0,-CYaw)
- I:RequestControl(2,1,0)
- logstr = logstr .. " left " .. -CYaw
- else
- --turn right
- I:RequestControl(2,1,CYaw)
- I:RequestControl(2,0,0)
- logstr = logstr .. " right " ..CYaw
- end
- if ( CPitch < 0 ) then
- --pitch down
- I:RequestControl(2,5,-CPitch)
- I:RequestControl(2,4,0)
- logstr = logstr .. " down " .. -CPitch
- else
- --pitch up
- I:RequestControl(2,4,CPitch)
- I:RequestControl(2,5,0)
- logstr = logstr .. " up " .. CPitch
- end
- if ( CRoll < 0 ) then
- --0. roll left
- logstr = logstr .. " rccw " .. -CRoll
- I:RequestControl(2,2,-CRoll)
- I:RequestControl(2,3,0)
- else
- -- roll right
- I:RequestControl(2,3,CRoll)
- I:RequestControl(2,2,0)
- logstr = logstr .. " rcw " .. CRoll
- end
- --I:LogToHud(logstr)
- end
- function killThatThing(I, weaponInfo, targetInfo, weaponIndex, turretSpinnerIndex)
- P = targetInfo.AimPointPosition
- V = targetInfo.Velocity
- WS = weaponInfo.Speed
- G = I:GetGravityForAltitude(P.y).magnitude
- if (WS > 100000) then
- AD = P - weaponInfo.GlobalPosition
- if(turretSpinnerIndex < 0) then
- I:AimWeaponInDirection(weaponIndex, AD.x, AD.y, AD.z, weaponInfo.WeaponSlot)
- I:FireWeapon(weaponIndex, weaponInfo.WeaponSlot)
- else
- I:AimWeaponInDirectionOnTurretOrSpinner(
- turretSpinnerIndex,weaponIndex, AD.x, AD.y, AD.z, weaponInfo.WeaponSlot)
- if (attackState == TARGET) then
- I:FireWeaponOnTurretOrSpinner(
- turretSpinnerIndex,weaponIndex,weaponInfo.WeaponSlot)
- end
- end
- return AD
- end
- T = (P - weaponInfo.GlobalPosition).magnitude / (WS*0.85) -- FIRST ESTIMATE OF FUTURE TARGET POSITION
- FP = P + V*T - I:GetVelocityVector()*T
- -- position the target will be
- AD = FP - weaponInfo.GlobalPosition
- -- direction direct to the target
- PJ = Mathf.Sqrt(AD.x*AD.x + AD.z*AD.z)
- -- horizontal distance to the target
- S2 = WS*WS
- -- speed^2
- S4 = S2*WS*WS
- -- speed^4 (need these many times)
- DELTA = S4 - G*(G*PJ*PJ + 2*AD.y * S2)
- -- is there a solution to the parable?
- if ( DELTA > 0 ) then
- --ok we can reach it and now we have a better estimate
- AG = Mathf.Atan2(S2 - Mathf.Sqrt(DELTA),G*PJ)
- --calculate angle
- --now we can calculate a better time to target using the horizontal speed
- --as obtained from the firing angle
- T = (P - weaponInfo.GlobalPosition).magnitude / (WS * Mathf.Cos(AG))
- FP = P + V*T - I:GetVelocityVector()*T
- --position target will be
- AD = FP - weaponInfo.GlobalPosition
- -- line direct to the target position
- PJ = Mathf.Sqrt(AD.x*AD.x + AD.z*AD.z)
- -- horizontal distance to the target
- DELTA = S4 - G*(G*PJ*PJ + 2*AD.y * S2)
- -- check the parable solution
- if ( DELTA > 0 ) then
- --ok we can reach it and now we have a better estimate
- PY = (S2 - Mathf.Sqrt(DELTA))/(G)
- -- no need to calculate angle or tangent, just the elev
- AD.y = PY --assign new elevation to the firing direction
- if(turretSpinnerIndex < 0) then
- I:AimWeaponInDirection(weaponIndex, AD.x, AD.y, AD.z, weaponInfo.WeaponSlot)
- I:FireWeapon(weaponIndex, weaponInfo.WeaponSlot)
- else
- I:AimWeaponInDirectionOnTurretOrSpinner(
- turretSpinnerIndex,weaponIndex, AD.x, AD.y, AD.z, weaponInfo.WeaponSlot)
- if (attackState == TARGET) then
- I:FireWeaponOnTurretOrSpinner(
- turretSpinnerIndex,weaponIndex,weaponInfo.WeaponSlot)
- end
- end
- end
- end
- return AD
- end
- function idleAround(I)
- idlePosition = I:GetConstructCenterOfMass()
- com = I:GetConstructCenterOfMass()
- fcom = I:GetConstructCenterOfMass() + I:GetVelocityVector()
- if (I:GetFriendlyCount() > 0) then
- idlePosition = idlePosition / I:GetFriendlyCount()
- for friendlyIndex=0, I:GetFriendlyCount() do
- friendlyInfo = I:GetFriendlyInfo(friendlyIndex)
- idlePosition = friendlyInfo.ReferencePosition / I:GetFriendlyCount()
- end
- end
- flyDirection = I:GetConstructCenterOfMass()-I:GetVelocityVector()-idlePosition
- if (com.y < I:GetTerrainAltitudeForLocalPosition(com.x,0,com.z) + minAlt or
- fcom.y < I:GetTerrainAltitudeForLocalPosition(fcom.x,0,fcom.z) + minAlt or
- com.y < minAlt) then
- flyDirection = Vector3(0,1,0)
- I:Component_SetBoolLogicAll(0, true)
- else
- I:Component_SetBoolLogicAll(0, false)
- end
- flyAlong(I, flyDirection, -I:GetGravityForAltitude(I:GetConstructCenterOfMass().y), 0 , thrust)
- end
- BREAK = 0 -- close in to target at max altitude
- SPLIT = 1 -- match target direction rolling down/up according to start alt
- ROLL = 2 -- if enemy vector are parallel, roll into tail
- TARGET = 3 -- aim to a shoot solution
- RUN = 4 -- too close and enemy not fast enough
- LOOP = 5 --enemy is faster loop on it's tail
- YOYO = 6
- EVADE = 9
- TURNFIGHT = 8
- EC = 7
- attackState = TARGET
- function performManeuver(I,targetInfo,attackState, situation)
- --some random defaults
- flyDirection = -I:GetGravityForAltitude(situation.com.y)
- flyNormal = -I:GetGravityForAltitude(situation.com.y)
- thrust = 1
- if (attackState == EC) then
- flyDirection = I:GetConstructForwardVector().normalized
- flyDirection.y = 0.5
- flyNormal = -I:GetGravityForAltitude(situation.com.y)
- I:Component_SetBoolLogicAll(0, true)
- else
- I:Component_SetBoolLogicAll(0, false)
- end
- if (attackState == TARGET) then
- flyNormal = (situation.attackDirection + Vector3(0,2,0)).normalized
- flyNormal.y = 0.5
- if(situation.forwardiness < -0.3) then
- flyDirection = Vector3.Cross(situation.targetDirection, I:GetGravityForAltitude(situation.com.y)).normalized
- flyDirection.y = 0.0
- flyNormal = - situation.targetDirection
- if (situation.operationAltitude > 0.5) then
- flyDirection.y = -situation.operationAltitude
- end
- if (situation.operationAltitude< -0.5) then
- flyDirection.y = situation.operationAltitude
- end
- else
- flyDirection = situation.attackDirection
- end
- if (situation.accordingness > 0 and situation.forwardiness > 0 and situation.separationFactor < 8) then
- if (situation.speedFactor > 1 and I:GetHealthFraction() == 1) then
- thrust = minimumThrust
- end
- end
- end
- if (attackState == BREAK or attackState == EVADE) then
- if(situation.forwardiness > 0.1) then
- flyDirection = Vector3.Cross(situation.targetDirection, I:GetGravityForAltitude(situation.com.y)).normalized
- flyDirection.y = 0.0
- flyNormal = - situation.targetDirection
- if (situation.operationAltitude > 0.5) then
- flyDirection.y = situation.operationAltitude
- end
- if (situation.operationAltitude< -0.5) then
- flyDirection.y = -situation.operationAltitude
- end
- else
- flyDirection = -situation.targetDirection
- flyDirection.y = -Mathf.Sign(situation.operationAltitude)
- if (situation.operationAltitude > 0.5) then
- flyDirection.y = situation.operationAltitude
- end
- if (situation.operationAltitude< -0.5) then
- flyDirection.y = -situation.operationAltitude
- end
- flyNormal = Vector3(0,1,0)
- end
- end
- if (attackState == YOYO) then
- flyDirection = Vector3(0,-situation.operationAltitude,0)
- flyNormal = situation.targetDirection
- end
- if (attackState == ROLL) then
- flyDirection = situation.targetDirection + Vector3(0,-situation.operationAltitude,0) + I:GetConstructRightVector() * situation.rightness
- flyNormal = situation.targetDirection
- end
- if (attackState == TURNFIGHT) then
- flyDirection = Vector3.Cross(situation.targetDirection.normalized, -I:GetGravityForAltitude(situation.com.y))
- flyNormal = situation.targetDirection
- end
- if (attackState == LOOP) then
- flyDirection = -situation.targetVelocity + Vector3(0, -situation.operationAltitude,0)
- flyNormal = situation.targetDirection
- end
- flyNormal = flyNormal.normalized
- if (onlyBomberRun > 0 and flyNormal.y >0.1) then flyNormal.y = 0.1 end
- if (onlyBomberRun > 0 and flyNormal.y <-0.1) then flyNormal.y = -0.1 end
- if (situation.futurecom.y < minAlt) then flyNormal.y = 0.4 end
- if (situation.futurecom.y > maxAlt) then flyNormal.y = -0.4 end
- flyAlong(I, flyDirection, flyNormal, situation.decisionSeed, thrust)
- end
- limit = 0
- function attackEnemy(I, AD, targetInfo)
- situation = {}
- situation.com = I:GetConstructCenterOfMass()
- situation.futurecom = situation.com + I:GetVelocityVector()
- situation.attackDirection = AD
- situation.targetPosition = targetInfo.AimPointPosition
- situation.targetVelocity = targetInfo.Velocity
- situation.targetDirection = situation.targetPosition - I:GetConstructCenterOfMass()
- situation.forwardiness = Vector3.Dot(situation.targetDirection.normalized, I:GetConstructForwardVector())
- situation.uppiness = Vector3.Dot(situation.targetDirection.normalized, I:GetConstructUpVector())
- situation.rightness = Vector3.Dot(situation.targetDirection.normalized, I:GetConstructRightVector())
- situation.accordingness = Vector3.Dot(situation.targetVelocity.normalized, I:GetVelocityVector().normalized)
- situation.distance = situation.targetDirection.magnitude
- situation.separation = (situation.targetDirection + situation.targetVelocity - I:GetVelocityVector()).magnitude
- situation.operationAltitude = 2*(situation.com.y - minAlt)/(maxAlt-minAlt) - 1 -- -1 .. 1
- situation.targetAltitude = 2*(situation.targetPosition.y - minAlt)/(maxAlt-minAlt) - 1 -- -1 .. 1
- situation.speedFactor = I:GetVelocityVector().magnitude / (situation.targetVelocity.magnitude+0.01)
- situation.decisionSeed = ((I:GetConstructForwardVector().x + I:GetConstructForwardVector().y + I:GetConstructForwardVector().z)*534534545353.0)%100
- situation.distanceFactor = maneuverDistanceFactor * situation.distance / I:GetVelocityVector().magnitude
- situation.separationFactor = maneuverDistanceFactor * situation.distance / I:GetVelocityVector().magnitude
- -- break to recover after an emergency climb
- if (attackState == EC and situation.operationAltitude > 0 ) then
- attackState = BREAK
- end
- -- target enemy if we're far enough
- if (situation.distanceFactor > 10 ) then
- attackState = TARGET
- end
- if (situation.accordingness > 0 and situation.separationFactor > 6 ) then
- attackState = TARGET
- end
- if (attackState == TARGET and situation.separationFactor < 4 ) then
- if (onlyBomberRun == 1) then
- attackState = BREAK
- else
- if (situation.decisionSeed < 33) then
- attackState = YOYO
- end
- if (situation.decisionSeed > 32 and situation.decisionSeed < 66) then
- attackState = ROLL
- end
- if (situation.decisionSeed > 65) then
- attackState = LOOP
- end
- end
- end
- --emergency upcode
- if (situation.com.y < I:GetTerrainAltitudeForLocalPosition(situation.com.x,0,situation.com.z) + minAlt or
- situation.futurecom.y < I:GetTerrainAltitudeForLocalPosition(situation.futurecom.x,0,situation.futurecom.z) or
- situation.com.y < minAlt) then
- attackState = EC
- end
- --emergency evade
- if (situation.separationFactor < 2 or situation.distanceFactor < 1) then
- attackState = EVADE
- end
- performManeuver(I,targetInfo,attackState, situation)
- end
- function Update(I)
- targetInfo = I:GetTargetInfo(controllingMainframe, 0)
- AttackDirection = nil
- otherInfo = targetInfo
- --check all other targets and break from any too close to comfort irregardless of priority
- for targetIndex=0,I:GetNumberOfTargets(controllingMainframe) do
- otherInfo = I:GetTargetInfo(controllingMainframe, targetIndex)
- situation = {}
- situation.com = I:GetConstructCenterOfMass()
- situation.targetPosition = otherInfo.AimPointPosition
- situation.targetVelocity = otherInfo.Velocity
- situation.targetDirection = situation.targetPosition - situation.com
- situation.separation = (situation.targetDirection + situation.targetVelocity - I:GetVelocityVector()).magnitude
- if (situation.separation < I:GetVelocityVector().magnitude) then
- targetInfo = otherInfo
- end
- end
- if(targetInfo.Valid) then
- for weaponIndex=0,I:GetWeaponCount() do
- weaponInfo = I:GetWeaponInfo(weaponIndex)
- if ((weaponInfo.WeaponType == 4 or weaponInfo.WeaponType == 0 or weaponInfo.WeaponType == 2)
- and weaponInfo.Valid and weaponInfo.PlayerCurrentlyControllingIt == false
- and weaponInfo.WeaponSlot == restrictSlot) then
- AttackDirection = killThatThing(I, weaponInfo, targetInfo, weaponIndex, -1)
- end
- end
- for turretSpinnerIndex=0,I:GetTurretSpinnerCount() do
- for weaponIndex=0,I:GetWeaponCountOnTurretOrSpinner(turretSpinnerIndex) do
- weaponInfo = I:GetWeaponInfoOnTurretOrSpinner(turretSpinnerIndex, weaponIndex)
- if ((weaponInfo.WeaponType == 4 or weaponInfo.WeaponType == 0 or weaponInfo.WeaponType == 2)
- and weaponInfo.Valid and weaponInfo.PlayerCurrentlyControllingIt == false
- and weaponInfo.WeaponSlot == restrictSlot ) then
- AttackDirection = killThatThing(I, weaponInfo, targetInfo, weaponIndex, turretSpinnerIndex)
- end
- end
- end
- if (AttackDirection == nil) then
- P = targetInfo.AimPointPosition
- V = targetInfo.Velocity
- FP = P + V
- I:LogToHud("No weapon configured!!")
- AttackDirection = FP - I:GetConstructCenterOfMass()
- end
- attackEnemy(I, AttackDirection, targetInfo)
- I:TellAiThatWeAreTakingControl()
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement