Advertisement
LJLim

Sustained Burn AI

May 13th, 2017
192
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 10.74 KB | None | 0 0
  1. package data.scripts.campaign.abilities.ai;
  2.  
  3. import com.fs.starfarer.api.Global;
  4. import com.fs.starfarer.api.campaign.CampaignFleetAPI;
  5. import com.fs.starfarer.api.campaign.FleetAssignment;
  6. import com.fs.starfarer.api.campaign.SectorEntityToken;
  7. import com.fs.starfarer.api.campaign.SectorEntityToken.VisibilityLevel;
  8. import com.fs.starfarer.api.campaign.ai.FleetAIFlags;
  9. import com.fs.starfarer.api.campaign.ai.FleetAssignmentDataAPI;
  10. import com.fs.starfarer.api.campaign.ai.ModularFleetAIAPI;
  11. import com.fs.starfarer.api.campaign.rules.MemoryAPI;
  12. import com.fs.starfarer.api.fleet.FleetMemberAPI;
  13. import com.fs.starfarer.api.impl.campaign.abilities.ai.BaseAbilityAI;
  14. import com.fs.starfarer.api.impl.campaign.ids.Abilities;
  15. import com.fs.starfarer.api.util.IntervalUtil;
  16. import com.fs.starfarer.api.util.Misc;
  17. import java.util.Arrays;
  18. import java.util.HashSet;
  19. import java.util.Set;
  20.  
  21. // adapted from Emergency Burn AI
  22. public class SustainedBurnAbilityAI extends BaseAbilityAI {
  23.  
  24.     public static final float AI_FREQUENCY_MULT = 1f;
  25.     public static final float DISTANCE_TO_STOP = 800f;
  26.     public static final float DISTANCE_TO_START = 2000f;
  27.     public static final Set NO_BURN_ASSIGNMENTS = new HashSet(Arrays.asList(new FleetAssignment[]{
  28.         FleetAssignment.DEFEND_LOCATION, FleetAssignment.PATROL_SYSTEM,
  29.         FleetAssignment.RAID_SYSTEM, FleetAssignment.HOLD,
  30.         FleetAssignment.STANDING_DOWN, FleetAssignment.GO_TO_LOCATION_AND_DESPAWN
  31.     }));
  32.    
  33.     protected final IntervalUtil interval = new IntervalUtil(0.2f, 0.25f);
  34.    
  35.     protected boolean isFleetUsingAbility(CampaignFleetAPI target, String ability)
  36.     {
  37.         if (target.getAbility(ability) == null)
  38.             return false;
  39.         return target.getAbility(ability).isActiveOrInProgress();
  40.     }
  41.    
  42.     protected boolean shouldStop()
  43.     {
  44.         MemoryAPI mem = fleet.getMemoryWithoutUpdate();
  45.         CampaignFleetAPI fleeingFrom = mem.getFleet(FleetAIFlags.NEAREST_FLEEING_FROM);
  46.         if (fleeingFrom != null)
  47.         {
  48.             writeDebugMessage(fleet.getName() + " is running for its life, don't stop");
  49.             return false;
  50.         }
  51.            
  52.         if (fleet.getAI() == null)
  53.         {
  54.             writeDebugMessage(fleet.getName() + " has null AI, stop");
  55.             return true;
  56.         }
  57.         FleetAssignmentDataAPI assignmentData = fleet.getAI().getCurrentAssignment();
  58.         if (assignmentData == null)
  59.         {
  60.             writeDebugMessage(fleet.getName() + " has null assignment, stop");
  61.             return true;
  62.         }
  63.        
  64.        
  65.         FleetAssignment assignment = assignmentData.getAssignment();
  66.         if (NO_BURN_ASSIGNMENTS.contains(assignment))
  67.         {
  68.             writeDebugMessage(fleet.getName() + " non-burn assignment, stop");
  69.             return true;
  70.         }
  71.        
  72.         SectorEntityToken target = assignmentData.getTarget();
  73.         if (target instanceof CampaignFleetAPI)
  74.         {
  75.             CampaignFleetAPI targetFleet = (CampaignFleetAPI)target;
  76.             if (target.getContainingLocation() != fleet.getContainingLocation())
  77.             {
  78.                 writeDebugMessage(fleet.getName() + " target in another location, don't stop");
  79.                 return false;
  80.             }
  81.                
  82.             float closingSpeed = Misc.getClosingSpeed(fleet.getLocation(), targetFleet.getLocation(),
  83.                                                       fleet.getVelocity(), targetFleet.getVelocity());
  84.            
  85.             // we're facing the wrong way and already moving, turning to catch them is going to be a huge pain, may as well stop
  86.             //if (closingSpeed < 0 && fleet.getVelocity().x != 0 && fleet.getVelocity().y != 0)
  87.             //  return true;
  88.            
  89.             // target is using S burn, so will we
  90.             if (isFleetUsingAbility(targetFleet, Abilities.SUSTAINED_BURN))
  91.             {
  92.                 writeDebugMessage(fleet.getName() + " target fleet is burning, don't stop");
  93.                 return false;
  94.             }
  95.            
  96.             // following target, don't S burn if we're already close
  97.             if (assignment == FleetAssignment.ORBIT_AGGRESSIVE
  98.                     || assignment == FleetAssignment.ORBIT_PASSIVE)
  99.             {
  100.                 writeDebugMessage(fleet.getName() + " is close enough to escortee?");
  101.                 return Misc.getDistance(fleet.getLocation(), target.getLocation()) <= DISTANCE_TO_STOP;
  102.             }
  103.         }
  104.         else
  105.         {
  106.             // destination in other system, don't turn off S burn
  107.             if (target.getContainingLocation() != fleet.getContainingLocation())
  108.             {
  109.                 writeDebugMessage(fleet.getName() + " wants to go to another location, don't stop");
  110.                 return false;
  111.             }
  112.             else
  113.             {
  114.                 // if close, turn off S burn
  115.                 float dist = Misc.getDistance(fleet.getLocation(), target.getLocation());
  116.                 if (dist <= DISTANCE_TO_STOP)
  117.                 {
  118.                     writeDebugMessage(fleet.getName() + " is near destination, stop");
  119.                     return true;
  120.                 }
  121.             }
  122.         }
  123.         return false;
  124.     }
  125.    
  126.     protected boolean shouldStart()
  127.     {
  128.         MemoryAPI mem = fleet.getMemoryWithoutUpdate();
  129.        
  130.         CampaignFleetAPI pursueTarget = mem.getFleet(FleetAIFlags.PURSUIT_TARGET);
  131.         CampaignFleetAPI fleeingFrom = mem.getFleet(FleetAIFlags.NEAREST_FLEEING_FROM);
  132.        
  133.         // being pursued by a faster enemy that's not too close: turn on
  134.         if (fleeingFrom != null) {
  135.             VisibilityLevel level = fleet.getVisibilityLevelTo(fleeingFrom);
  136.             if (level == VisibilityLevel.NONE)
  137.             {
  138.                 writeDebugMessage(fleet.getName() + " pursuer can't see us, don't burn");
  139.                 return false;
  140.             }
  141.            
  142.             boolean hopelessFight = isGreatlyOutmatchedBy(fleeingFrom);
  143.             float dist = Misc.getDistance(fleet.getLocation(), fleeingFrom.getLocation()) - fleet.getRadius() + fleeingFrom.getRadius();
  144.             float ourSpeed = fleet.getFleetData().getBurnLevel();
  145.             float theirSpeed = fleeingFrom.getFleetData().getBurnLevel();
  146.            
  147.             if (ourSpeed >= theirSpeed) return false;   // no need (yet)
  148.             if (hopelessFight && dist > 400)
  149.             {
  150.                 writeDebugMessage(fleet.getName() + " is running for its life, burn");
  151.                 return true;
  152.             }
  153.         }
  154.        
  155.         // pursuing a faster enemy, and would be faster then them with SB on: turn on
  156.         if (pursueTarget != null) {
  157.             if (fleet.getAI() instanceof ModularFleetAIAPI) {
  158.                 ModularFleetAIAPI ai = (ModularFleetAIAPI) fleet.getAI();
  159.                 if (ai.getTacticalModule().isMaintainingContact()) // do we really want to catch them? meh
  160.                 {
  161.                     writeDebugMessage(fleet.getName() + " maintaining contact with target, don't burn");
  162.                     return false;
  163.                 }
  164.             }
  165.            
  166.             VisibilityLevel level = pursueTarget.getVisibilityLevelTo(fleet);
  167.             if (level == VisibilityLevel.NONE)
  168.             {
  169.                 writeDebugMessage(fleet.getName() + " can't see target, don't burn");
  170.                 return false;
  171.             }
  172.            
  173.             boolean targetInsignificant = otherInsignificant(pursueTarget);
  174.             if (targetInsignificant)
  175.             {
  176.                 writeDebugMessage(fleet.getName() + " is chasing small fry, don't burn");
  177.                 return false;
  178.             }
  179.  
  180.             float dist = Misc.getDistance(fleet.getLocation(), pursueTarget.getLocation()) - fleet.getRadius() - pursueTarget.getRadius();
  181.             if (dist < 0) return false; // already on top of them
  182.            
  183.             float ourSpeed = fleet.getFleetData().getBurnLevel();
  184.             float theirSpeed = pursueTarget.getFleetData().getBurnLevel();
  185.             if (ourSpeed > theirSpeed)
  186.             {
  187.                 writeDebugMessage(fleet.getName() + " is already faster than target, don't burn");  // no need (yet)
  188.                 return false;
  189.             }  
  190.            
  191.             // they're trying to S-burn away, use our own
  192.             if (isFleetUsingAbility(pursueTarget, Abilities.SUSTAINED_BURN))
  193.             {
  194.                 writeDebugMessage(fleet.getName() + " target fleet is burning, burn");
  195.                 return true;
  196.             }
  197.            
  198.             if (pursueTarget.getContainingLocation() != fleet.getContainingLocation())
  199.             {
  200.                 writeDebugMessage(fleet.getName() + " target fleet is in another system, burn");
  201.                 return true;
  202.             }
  203.         }
  204.        
  205.         FleetAssignmentDataAPI assignmentData = fleet.getAI().getCurrentAssignment();
  206.         if (assignmentData != null)
  207.         {
  208.             FleetAssignment assignment = assignmentData.getAssignment();
  209.             if (NO_BURN_ASSIGNMENTS.contains(assignment)) return true;
  210.            
  211.             SectorEntityToken target = assignmentData.getTarget();
  212.             if (target instanceof CampaignFleetAPI)
  213.             {
  214.                 // following target, S burn to get closer?
  215.                 if (assignment == FleetAssignment.ORBIT_AGGRESSIVE || assignment == FleetAssignment.ORBIT_PASSIVE)
  216.                 {
  217.                     if (Misc.getDistance(fleet.getLocation(), target.getLocation()) >= DISTANCE_TO_START)
  218.                     {
  219.                         writeDebugMessage(fleet.getName() + " target fleet is far away, burn");
  220.                         return true;
  221.                     }
  222.                 }
  223.             }
  224.             else
  225.             {
  226.                 // destination in other system, use S burn
  227.                 if (target.getContainingLocation() != fleet.getContainingLocation())
  228.                 {
  229.                     writeDebugMessage(fleet.getName() + " wants to go to another location, burn");
  230.                     return true;
  231.                 }
  232.                 else
  233.                 {
  234.                     float dist = Misc.getDistance(fleet.getLocation(), target.getLocation());
  235.                     if (dist >= DISTANCE_TO_START)
  236.                     {
  237.                         writeDebugMessage(fleet.getName() + " destination is far enough away, burn");
  238.                         return true;
  239.                     }
  240.                 }
  241.             }
  242.         }
  243.         return false;
  244.     }
  245.  
  246.     boolean wasActive = false;
  247.    
  248.     @Override
  249.     public void advance(float days) {
  250.         boolean active = ability.isActiveOrInProgress();
  251.         if (active != wasActive)
  252.         {
  253.             writeDebugMessage(fleet.getName() + " burn state changed, now " + active);
  254.             wasActive = active;
  255.         }
  256.        
  257.         interval.advance(days * AI_FREQUENCY_MULT);
  258.         if (!interval.intervalElapsed()) return;
  259.        
  260.         if (ability.isActiveOrInProgress()) {
  261.             // should we stop?
  262.             if (shouldStop())
  263.             {
  264.                 writeDebugMessage(fleet.getName() + " stopping burn");
  265.                 ability.deactivate();
  266.                 return;
  267.             }
  268.             MemoryAPI mem = fleet.getMemoryWithoutUpdate();
  269.             mem.set(FleetAIFlags.HAS_SPEED_BONUS, true, 0.4f);
  270.             mem.set(FleetAIFlags.HAS_VISION_PENALTY, true, 0.4f);
  271.             //writeDebugMessage(fleet.getName() + " is already burning, do nothing");
  272.             return;
  273.         }
  274.        
  275.         if (fleet.getAI() != null && NO_BURN_ASSIGNMENTS.contains(fleet.getAI().getCurrentAssignmentType())) {
  276.             return;
  277.         }
  278.        
  279.         if (!ability.isUsable()) return;
  280.        
  281.         if (shouldStart())
  282.         {
  283.             writeDebugMessage(fleet.getName() + " starting burn");
  284.             ability.activate();
  285.         }
  286.     }
  287.    
  288.     protected boolean isGreatlyOutmatchedBy(CampaignFleetAPI other) {
  289.         float us = getStrength(fleet);
  290.         float them = getStrength(other);
  291.        
  292.         if (us < 0.1f) us = 0.1f;
  293.         if (them < 0.1f) them = 0.1f;
  294.         return them > us * 3f;
  295.     }
  296.    
  297.     protected boolean otherInsignificant(CampaignFleetAPI other) {
  298.         float us = getStrength(fleet);
  299.         float them = getStrength(other);
  300.        
  301.         if (us < 0.1f) us = 0.1f;
  302.         if (them < 0.1f) them = 0.1f;
  303.         return us > them * 3f;
  304.     }
  305.    
  306.     public static float getStrength(CampaignFleetAPI fleet) {
  307.         float str = 0f;
  308.         for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) {
  309.             if (member.canBeDeployedForCombat()) {
  310.                 float strength = member.getMemberStrength();
  311.                 str += strength;
  312.             }
  313.         }
  314.         return str;
  315.     }
  316.    
  317.     protected void writeDebugMessage(String str)
  318.     {
  319.         CampaignFleetAPI player = Global.getSector().getPlayerFleet();
  320.         if (fleet.getContainingLocation() == player.getContainingLocation()
  321.                     && Misc.getDistance(fleet.getLocation(), player.getLocation()) <= 700)
  322.         {
  323.             Global.getSector().getCampaignUI().addMessage(str);
  324.         }
  325.     }
  326. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement