Advertisement
RA2lover

Medic Drone AI WIP

Oct 26th, 2015
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.24 KB | None | 0 0
  1. ---Player Skill Constants affecting flight model-----
  2. SKY_CAPTAIN_LEVEL=0
  3. SPACE_CAPTAIN_LEVEL=0
  4.  
  5. ---------TARGET PRIORITIZATION---------
  6. function CalculateFriendlyValue(FriendlyInfo, SelfInfo)
  7.  
  8.  --[[returns the friendly unit's value for friendly prioritization purposes.
  9.      you may want to change this to change which units to prioritize,
  10.      for example, by increasing the priority of a specific blueprint.
  11.      Think of this as a more advanced target prioritization AI card.
  12.      This is also the reason this function is on the beginning of the script.
  13.      I probably did an awful job at setting proper prioritization here.
  14.  
  15.      NO. SERIOUSLY. IF YOU SEE DERPY BEHAVIOR, BLAME THIS FUNCTION.]]
  16.  
  17.  --we only want valid targets.
  18.  if not FriendlyInfo.IsValid then return -999999999 end --9 zeros here, shouldn't be looked at all
  19.  if (FriendlyInfo.CenterOfMass-SelfInfo.CenterOfMass).magnitude<3 then return -99999999 end --8 here
  20.  -----ALGORITHM CONSTANTS-----
  21.  
  22.  --value to add per m of distance to the target(calculated by center of mass)
  23.  local DistanceValue=-2
  24.  *(FriendlyInfo.CenterOfMass-SelfInfo.CenterOfMass).Magnitude
  25.  
  26.  --value to add for damage
  27.  --this function prioritizes larger vessels assuming they need more repairs. maybe too much.
  28.  local HealthValue=(FriendlyInfo.PositiveSize+FriendlyInfo.NegativeSize).sqrMagnitude
  29.  *(1.02-FriendlyInfo.HealthFraction) --the .02 helps it stick close to flagships
  30.  
  31.  --value per m/s of velocity in world coordinates
  32.  local WorldVelocityValue = -2
  33.  *FriendlyInfo.Velocity.magnitude
  34.  
  35.  --value per m/s of velocity in coordinates relative to the repair drone.
  36.  --should be somewhat high to avoid unnecessary target switching.
  37.  --closure rate formula help by /u/Alkalannar on /r/homeworkhelp. Thanks Reddit!
  38.  local RelativeVelocityValue = 30
  39.  *(Vector3.Scale(FriendlyInfo.Position-SelfInfo.Position,FriendlyInfo.Velocity-SelfInfo.Velocity)
  40.  /(FriendlyInfo.Position-SelfInfo.Position).magnitude).magnitude
  41.  
  42.  
  43.  --value per meter of altitude the target has from sea level.
  44.  --intentionally low to discourage healing unreachable targets in space.
  45.  --Also low for underwater targets to reduce likelyness of moving underwater.
  46.  local AltitudeValue=0
  47.  local TargetAltitude = FriendlyInfo.CenterOfMass.y
  48.  if     TargetAltitude<-50 then AltitudeValue=TargetAltitude * 30+500
  49.  elseif TargetAltitude<300 then AltitudeValue=TargetAltitude *-10
  50.  elseif TargetAltitude<600 then AltitudeValue=TargetAltitude *-50+3000
  51.  else                           AltitudeValue=TargetAltitude *-250
  52.  end
  53.  
  54.  
  55.  return DistanceValue+HealthValue+VelocityValue+AltitudeValue
  56. end
  57.  
  58.  
  59. --------------------ACTUAL MAIN FUNCTION--------------------
  60. function Update(I)
  61.  -- put your code here
  62. end
  63. --------END MAIN FUNCTION, HELPER FUNCTIONS GO HERE---------
  64.  
  65. function GetSelfInfo(I)
  66.  --attempts to assemble a FriendlyInfo-like object based on self-awareness info
  67.  local Info={}
  68.  --this may look ugly, but i'm not using _G.
  69.  Info.Rotation = nil --screw quaternions.
  70.  Info.ReferencePosition=I:GetConstructPosition()
  71.  Info.PositiveSize = I:GetConstructMaxDimensions()
  72.  Info.NegativeSize=I:GetConstructMinDimensions()
  73.  Info.CenterOfMass=I:GetConstructCenterOfMass()
  74.  Info.UpVector=I:GetConstructUpVector()
  75.  Info.ForwardVector=I:GetConstructForwardVector()
  76.  Info.RightVector=I:GetConstructRightVector()
  77.  Info.HealthFraction=I:GetHealthFraction()
  78.  Info.SparesFraction=I:GetSparesFraction()
  79.  Info.AmmoFraction=I:GetAmmoFraction()
  80.  Info.FuelFraction=I:GetFuelFraction()
  81.  --too lazy to calculate AABBs
  82.  Info.AxisAlignedBoundingBoxMinimum=nil
  83.  Info.AxisAlignedBoundingBoxMaximum=nil
  84.  Info.IsValid=-1 --it's neither valid or invalid. That's the most fitting thing i can think of!
  85.  return Info
  86. end
  87.  
  88. function GetRotationMatrix(...)
  89.  --returns a rotation matrix with the right-up-forward vectors of a FriendlyInfo object.
  90.  --alternatively, can be overloaded with 3 vectors.
  91.  --if so, it's already expecting them to be unit vectors and won't try to normalize them.
  92.  
  93.  --late feature: also accepts quaternion input(passed to another function)
  94.  local M={}
  95.  local args={...}
  96.  if #args==1 and args[1].w==nil then
  97.   M.x=Info.RightVector
  98.   M.y=Info.UpVector
  99.   M.z=Info.ForwardVector
  100.   return M
  101.  elseif args[1].w then return QuaternionToRotationMatrix(...)
  102.  else
  103.   M.x=args[1]
  104.   M.y=args[2]
  105.   M.z=args[3]
  106.   return M
  107.  end
  108. end
  109.  
  110. function ThrustGlobally(I,Force) --Vector3
  111.  --Attempts to apply a specific force(kN) on the global reference frame using the dediblades.
  112.  --Doesn't account for damage affecting force output.
  113.  --Also doesn't try to use vertical force components.
  114.  --Behavior if the system can't achieve the inserted power is undefined.
  115.  
  116.  -- this function could be made much smaller, but i'm too lazy for it right now.
  117.  
  118.  --still writing it. may be reaching critical mass
  119.  
  120.  -- lists spinner IDs for a side
  121.  local RightSpinners, LeftSpinners, UpSpinners, DownSpinners, ForwardSpinners, BackSpinners={}
  122.  local UndefinedSpinners={} -- i'm probably going to trigger this at some point.
  123.  
  124.  local SpinnerCount=I:GetSpinnerCount()
  125.   for n=0, SpinnerCount-1 do
  126.    SpinnerInfo=I:GetSpinnerInfo(n)
  127.    local SpinnerLocalUpVector=GetRotationMatrix(SpinnerInfo.LocalRotation).y
  128.  
  129.    --WHY DONT WE HAVE SWITCH-CASE DAMNIT!? <-totally not an interrobang
  130.     if SpinnerLocalUpVector==Vector3.up then table.insert(UpSpinners, n)
  131.     elseif SpinnerLocalUpVector==Vector3.down then table.insert(DownSpinners,n)
  132.     elseif SpinnerLocalUpVector==Vector3.left then table.insert(LeftSpinners,n)
  133.     elseif SpinnerLocalUpVector==Vector3.right then table.insert(RightSpinners,n)
  134.     elseif SpinnerLocalUpVector==Vector3.forward then table.insert(ForwardSpinners,n)
  135.     elseif SpinnerLocalUpVector==Vector3.back then table.insert(BackSpinners,n)
  136.     else table.insert(UndefinedSpinners,n)
  137.     end
  138.   end
  139.  
  140.  local RotorMass=0.09 --dediblade motor+4 blades
  141.  local AtmosphericDensity=GetAtmosphericDensity()
  142.  local MotorDrive=0 --no engine
  143.  --kN thrust per rad/s of a dediblade, see fromthedepths.gamepedia.com/Air#Dedicated_heliblades
  144.  HelibladeForce=10*RotorMass*AtmosphericDensity*(1+MotorDrive)*(1+(0.02*SKY_CAPTAIN_LEVEL))
  145.  
  146.  local SpinnerCount=Vector3(#LeftSpinners+#RightSpinners,
  147.  #UpSpinners+#DownSpinners,#ForwardSpinners+#BackSpinners)
  148.  
  149.  local ForceProducedPerRad=SpinnerCount*HelibladeForce --output of all of a side's blades/rad/s
  150.  
  151.  Local RadsNeeded=Vector3InvScale(SpinnerCount, ForceNeededPerRad)--RPM for force if orthogonal
  152.  
  153.  for k,v in pairs(RightSpinners) do
  154.   local SpinnerAngle=GetRotationMatrix(I:GetSpinnerInfo[v].Rotation).y
  155.   I:SetSpinnerContinousSpeed(v,TaxicabMagnitude(Vector3.Scale() --UPLOADED WHILE WRITING THIS PART
  156.  end
  157.  
  158. end
  159.  
  160.  
  161. function GetAtmosphericDensity(Input)
  162.  --why don't we have this ingame already?
  163.  --this is a kludge. don't say i didn't warn you. Also, it only works for Neterlike planets
  164.  if Input==nil then return GetAtmosphericDensity(SelfInfo.CenterOfMass.y or 0)
  165.  elseif type(Input)=="number" then
  166.   if Input<300 then return 1
  167.   elseif Input<500+(10*SPACE_CAPTAIN_LEVEL) then
  168.    local dx= 1/(200+(10*SPACE_CAPTAIN_LEVEL)) --% atmos density lost per m of altitude
  169.    return 1-(dx*(Input-300))
  170.   else return 0
  171.   end
  172.  else return GetAtmosphericDensity(Input.CenterOfMass.y or Input.Position.y
  173.              or Input.ReferencePosition.y)
  174.  end
  175.  
  176.  
  177.  
  178. end
  179.  
  180. function QuaternionToRotationMatrix(Q)
  181.  --returns the right/up/forward rotation matrix from a quaternion
  182.  local M={}
  183.  
  184.  local XSquared=Q.x*Q.x
  185.  local YSquared=Q.y*Q.y
  186.  local ZSquared=Q.z*Q.z
  187.  --local WSquared=Q.w*Q.w
  188.  
  189.  local XY=Q.x*Q.y
  190.  local XZ=Q.x*Q.z
  191.  local XW=Q.x*Q.w
  192.  local YZ=Q.y*Q.z
  193.  local YW=Q.y*Q.w
  194.  local ZW=Q.z*Q.w
  195.  
  196.  --I have absolutely no idea how any of this works. If the AI fails to move properly, this is why.
  197.  --Evil4Zerggin linked me to a formula on wikipedia i tried to optimize.
  198.  --I'm probably doing a mistake.
  199.  
  200.  M.x = (Vector3(-YSquared-ZSquared, XY-ZW, XZ+YW)*2)+Vector3.right
  201.  M.y = (Vector3(XY+ZW, -XSquared-ZSquared, YZ-XW)*2)+Vector3.up
  202.  M.z = (Vector3(XZ-YW, YZ+XW, -XSquared-YSquared)*2)+Vector3.forward
  203.  return M
  204. end
  205.  
  206.  
  207. function Vector3InvScale(A,B)
  208. return Vector3.Scale(A,Vector3(1/B.x, 1/B.y, 1/B.z))
  209. end
  210.  
  211. function TaxicabMagnitude(Vec3)
  212. --returns the taxicab magnitude of a Vector3
  213. return math.abs(Vec3.x)+math.abs(Vec3.y)+math.abs(Vec3.z)
  214. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement