Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- v0.8
- controllingMainframe = 0 --the mainframe with the target prioritization card
- restrictSlot = 1 --ai will only control these weapons, and will orient the craft along those
- attackFromDistance = 750 -- distance at which do the attack run
- abortAttackDistance = 100 -- distance at which we disengage
- abortRunDistance = 300 -- distance at which we reengage
- Kp = 10 --amount of control proportional to deviation
- Ki = 0.001 --amount of accumulation to contrast deviation (keep small!)
- Kd = 1 --amount of dampening proportional to oscillation
- minAlt = 100
- maxAlt = 300
- function killThatThing(I, weaponInfo, targetInfo, weaponIndex, turretSpinnerIndex)
- P = targetInfo.AimPointPosition
- V = targetInfo.Velocity
- WS = weaponInfo.Speed
- G = I:GetGravityForAltitude(P.y).magnitude
- 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)
- I:FireWeaponOnTurretOrSpinner(
- turretSpinnerIndex,weaponIndex,weaponInfo.WeaponSlot)
- end
- end
- end
- return AD
- end
- lastRoll = 0
- lastPitch = 0
- lastYaw = 0
- IRoll = 0
- IPitch = 0
- IYaw = 0
- DRoll = 0
- DPitch = 0
- DYaw = 0
- ePitch = 0
- eRoll = 0
- eYaw = 0
- function flyAlong(I, direction, normal)
- I:RequestThrustControl(0, 1)
- logstr = ""
- dt = 1
- lastYaw = eYaw
- lastPitch = ePitch
- lastRoll = eRoll
- --I:RequestControl(mode,type,drive)
- eYaw = Vector3.Dot(
- Vector3.ProjectOnPlane(direction, I:GetConstructUpVector() ),
- I:GetConstructRightVector()
- )
- ePitch = Vector3.Dot(
- Vector3.ProjectOnPlane(direction, I:GetConstructRightVector() ),
- I:GetConstructUpVector()
- )
- eRoll = Vector3.Dot(
- Vector3.ProjectOnPlane(normal, I:GetConstructForwardVector() ),
- I:GetConstructRightVector()
- )
- IYaw = IYaw + eYaw * dt
- DYaw = (eYaw - lastYaw)/dt
- CYaw = Kp*eYaw + Ki*IYaw + Kd*DYaw
- IPitch = IPitch + ePitch * dt
- DPitch = (ePitch - lastPitch)/dt
- CPitch = Kp*ePitch + Ki*IPitch + Kd*DPitch
- IRoll = IRoll + eRoll * dt
- DRoll = (eRoll - lastRoll)/dt
- CRoll = Kp*eRoll + Ki*IRoll + Kd*DRoll
- CYaw = 0.63661977*Mathf.Atan(CYaw)
- CPitch = 0.63661977*Mathf.Atan(CPitch)
- CRoll = 0.63661977*Mathf.Atan(CRoll)
- if ( CYaw < 0 ) then
- --turn left
- I:RequestControl(2,0,-CYaw)
- logstr = logstr .. "left "
- else
- --turn right
- I:RequestControl(2,1,CYaw)
- logstr = logstr .. "right "
- end
- if ( CPitch < 0 ) then
- --pitch down
- I:RequestControl(2,5,-CPitch)
- logstr = logstr .. "down "
- else
- --pitch up
- I:RequestControl(2,4,CPitch)
- logstr = logstr .. "up "
- end
- if ( CRoll < 0 ) then
- -- roll left
- logstr = logstr .. "rccw "
- I:RequestControl(2,2,-CRoll)
- else
- -- roll right
- I:RequestControl(2,3,CRoll)
- logstr = logstr .. "rcw "
- end
- end
- function idleAround(I)
- idlePosition = I:GetConstructCenterOfMass()
- 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
- flyAlong(I, flyDirection, -I:GetGravityForAltitude(I:GetConstructCenterOfMass().y) )
- end
- GAIN = 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
- attackState = GAIN
- function performManeuver(I,AD,targetInfo,attackState)
- normal = -I:GetGravityForAltitude(I:GetConstructCenterOfMass().y)
- if(attackState == GAIN) then
- I:LogToHud("GAINING")
- y = I:GetConstructCenterOfMass().y
- if ( y < maxAlt - 50 ) then
- AD = AD.normalized
- AD.y = 1
- else
- AD.y = 0
- end
- end
- if(attackState == RUN) then
- V = targetInfo.Velocity
- I:LogToHud("RUNNING")
- AD = V * -1
- y = I:GetConstructCenterOfMass().y
- if ( y < maxAlt - 50 ) then
- AD = AD.normalized
- AD.y = 4
- else
- if ( y > (maxAlt - minAlt / 2) ) then
- AD = AD.normalized
- AD.y = -4
- else
- AD.y=0
- end
- end
- end
- if(attackState == TARGET) then
- I:LogToHud("TARGETING")
- normal = AD
- normal = normal + Vector3(0,1,0)
- end
- if(attackState == LOOP) then
- I:LogToHud("LOOP")
- AD = V * -1
- normal = AD
- end
- flyAlong(I, AD, normal)
- end
- function attackEnemy(I, AD, targetInfo)
- P = targetInfo.AimPointPosition
- V = targetInfo.Velocity
- FP = P + V
- TD = FP - I:GetConstructCenterOfMass()
- distance = TD.magnitude
- if (distance > attackFromDistance) then
- attackState = GAIN
- else
- if (distance < abortAttackDistance) then
- attackState = RUN
- else
- if (attackState == GAIN or distance > abortRunDistance) then
- attackState = TARGET
- end
- if (attackState == RUN and distance < abortRunDistance and Vector3.Dot(V,I:GetConstructForwardVector() )> 0.7) then
- attackState = LOOP
- end
- if (attackState == LOOP and distance > abortAttackDistance and Vector3.Dot(V,I:GetConstructForwardVector() ) < 0) then
- attackState = TARGET
- end
- if (attackState == LOOP and distance < abortAttackDistance and Vector3.Dot(V,I:GetConstructForwardVector() ) < 0) then
- attackState = RUN
- end
- end
- end
- performManeuver(I,AD,targetInfo,attackState)
- end
- function Update(I)
- targetInfo = I:GetTargetInfo(controllingMainframe, 0)
- AttackDirection = nil
- if(targetInfo.Valid) then
- for weaponIndex=0,I:GetWeaponCount() do
- weaponInfo = I:GetWeaponInfo(weaponIndex)
- if ((weaponInfo.WeaponType == 4 or weaponInfo.WeaponType == 0 )
- 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 )
- 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)
- else
- I:LogToHud("IDLING")
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement