001package com.fs.starfarer.api.impl.campaign.abilities.ai; 002 003import org.lwjgl.util.vector.Vector2f; 004 005import com.fs.starfarer.api.Global; 006import com.fs.starfarer.api.campaign.CampaignFleetAPI; 007import com.fs.starfarer.api.campaign.FleetAssignment; 008import com.fs.starfarer.api.campaign.SectorEntityToken; 009import com.fs.starfarer.api.campaign.ai.FleetAIFlags; 010import com.fs.starfarer.api.campaign.ai.ModularFleetAIAPI; 011import com.fs.starfarer.api.campaign.rules.MemoryAPI; 012import com.fs.starfarer.api.impl.campaign.ids.MemFlags; 013import com.fs.starfarer.api.util.IntervalUtil; 014import com.fs.starfarer.api.util.Misc; 015 016public class SustainedBurnAbilityAI extends BaseAbilityAI { 017 018 public static final float AI_FREQUENCY_MULT = 1f; 019 020 private IntervalUtil interval = new IntervalUtil(0.05f, 0.15f); 021 022// public EmergencyBurnAbilityAI(AbilityPlugin ability, ModularFleetAIAPI ai) { 023// super(ability, ai); 024// } 025 026 public void advance(float days) { 027 interval.advance(days * SustainedBurnAbilityAI.AI_FREQUENCY_MULT); 028 if (!interval.intervalElapsed()) return; 029 030 MemoryAPI mem = fleet.getMemoryWithoutUpdate(); 031 if (ability.isActiveOrInProgress()) { 032 mem.set(FleetAIFlags.HAS_SPEED_BONUS, true, 0.2f); 033 mem.set(FleetAIFlags.HAS_HIGHER_DETECTABILITY, true, 0.2f); 034 } 035 036 boolean smuggler = mem.getBoolean(MemFlags.MEMORY_KEY_SMUGGLER); 037 if (smuggler) { 038 if (ability.isActive()) ability.deactivate(); 039 return; 040 } 041 042 043 if (fleet.getAI() instanceof ModularFleetAIAPI) { 044 ModularFleetAIAPI ai = (ModularFleetAIAPI) fleet.getAI(); 045 if (ai.getTacticalModule().isMaintainingContact()) { 046 if (ability.isActive()) ability.deactivate(); 047 return; 048 } 049 } 050 051 if (mem.getBoolean(FleetAIFlags.HAS_LOWER_DETECTABILITY) && !ability.isActive()) { 052 return; 053 } 054 055// if (true) { 056// if (!ability.isActive()) { 057// ability.activate(); 058// } else { 059// ability.deactivate(); 060// } 061// return; 062// } 063// if (fleet.getAI() != null && fleet.getAI().getCurrentAssignmentType() == FleetAssignment.STANDING_DOWN) { 064// return; 065// } 066 067 CampaignFleetAPI pursueTarget = mem.getFleet(FleetAIFlags.PURSUIT_TARGET); 068 CampaignFleetAPI fleeingFrom = mem.getFleet(FleetAIFlags.NEAREST_FLEEING_FROM); 069 070// float moveDir = Misc.getDesiredMoveDir(fleet); 071 072 float burn = Misc.getBurnLevelForSpeed(fleet.getVelocity().length()); 073// if (ability.isActive() && burn >= 5f) { 074// float diff = Misc.getAngleDiff(moveDir, Misc.getAngleInDegrees(fleet.getVelocity())); 075// if (diff > 90f) { 076// ability.deactivate(); 077// return; 078// } 079// } 080 081 082 float activationTime = ability.getSpec().getActivationDays() * Global.getSector().getClock().getSecondsPerDay(); 083 if (fleeingFrom != null) { 084 float dist = Misc.getDistance(fleet.getLocation(), fleeingFrom.getLocation()); 085 float speed = Math.max(1f, fleeingFrom.getTravelSpeed()); 086 float time = dist / speed; 087 if (!ability.isActive()) { // far enough to wind up and get away 088 if (time >= activationTime + 5f) { 089 ability.activate(); 090 } 091 } else { // too close to wind up, better chance of getting away by turning SB off 092 if (burn <= 3 && time < 5f) { 093 ability.deactivate(); 094 } 095 } 096 return; 097 } 098 099 if (pursueTarget != null) { 100// if (pursueTarget.isPlayerFleet()) { 101// System.out.println("fwefewwe"); 102// } 103 if (ability.isActive()) { 104 float toTarget = Misc.getAngleInDegrees(fleet.getLocation(), pursueTarget.getLocation()); 105 float velDir = Misc.getAngleInDegrees(fleet.getVelocity()); 106 float diff = Misc.getAngleDiff(toTarget, velDir); 107 if (diff > 60f) { 108 ability.deactivate(); 109 } 110 } 111 return; 112 } 113 114 115 if (fleet.getAI() != null && fleet.getAI().getCurrentAssignment() != null) { 116 FleetAssignment curr = fleet.getAI().getCurrentAssignmentType(); 117 SectorEntityToken target = fleet.getAI().getCurrentAssignment().getTarget(); 118 boolean inSameLocation = target != null && target.getContainingLocation() == fleet.getContainingLocation(); 119 float distToTarget = 100000f; 120 if (inSameLocation) { 121 distToTarget = Misc.getDistance(target.getLocation(), fleet.getLocation()); 122 } 123 boolean close = distToTarget < 2000; 124 125 if (close && 126 (curr == FleetAssignment.ORBIT_PASSIVE || 127 curr == FleetAssignment.ORBIT_AGGRESSIVE || 128 curr == FleetAssignment.DELIVER_CREW || 129 curr == FleetAssignment.DELIVER_FUEL || 130 curr == FleetAssignment.DELIVER_MARINES || 131 curr == FleetAssignment.DELIVER_PERSONNEL || 132 curr == FleetAssignment.DELIVER_RESOURCES || 133 curr == FleetAssignment.DELIVER_SUPPLIES || 134 curr == FleetAssignment.RESUPPLY || 135 curr == FleetAssignment.GO_TO_LOCATION || 136 curr == FleetAssignment.GO_TO_LOCATION_AND_DESPAWN) 137 ) { 138 if (ability.isActive()) ability.deactivate(); 139 return; 140 } 141 if (inSameLocation && ( 142 curr == FleetAssignment.RAID_SYSTEM || 143 curr == FleetAssignment.PATROL_SYSTEM)) { 144 if (ability.isActive()) ability.deactivate(); 145 return; 146 } 147 } 148 149 150 Vector2f travelDest = mem.getVector2f(FleetAIFlags.TRAVEL_DEST); 151 if (travelDest != null) { 152 float dist = Misc.getDistance(fleet.getLocation(), travelDest); 153 float speed = Math.max(1f, fleet.getTravelSpeed()); 154 float time = dist / speed; 155 if (!ability.isActive()) { 156 if (time > activationTime * 2f) { 157 ability.activate(); 158 } 159 } 160 return; 161 } 162 163 164 165 } 166 167 168} 169 170 171 172 173 174