Starsector API
Loading...
Searching...
No Matches
InterdictionPulseAbilityAI.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.abilities.ai;
2
3import com.fs.starfarer.api.Global;
4import com.fs.starfarer.api.campaign.CampaignFleetAPI;
5import com.fs.starfarer.api.campaign.SectorEntityToken.VisibilityLevel;
6import com.fs.starfarer.api.campaign.ai.FleetAIFlags;
7import com.fs.starfarer.api.campaign.ai.ModularFleetAIAPI;
8import com.fs.starfarer.api.campaign.rules.MemoryAPI;
9import com.fs.starfarer.api.characters.AbilityPlugin;
10import com.fs.starfarer.api.impl.campaign.abilities.InterdictionPulseAbility;
11import com.fs.starfarer.api.impl.campaign.ids.Abilities;
12import com.fs.starfarer.api.util.IntervalUtil;
13import com.fs.starfarer.api.util.Misc;
15
16 public static final float AI_FREQUENCY_MULT = 1f;
17
18 private IntervalUtil interval = new IntervalUtil(0.05f, 0.15f);
19
20
21 public void advance(float days) {
22 interval.advance(days * InterdictionPulseAbilityAI.AI_FREQUENCY_MULT);
23 if (!interval.intervalElapsed()) return;
24
25 if (fleet.getAI() instanceof ModularFleetAIAPI) {
26 ModularFleetAIAPI ai = (ModularFleetAIAPI) fleet.getAI();
27 if (ai.getTacticalModule().isMaintainingContact()) {
28 return;
29 }
30 }
31
32 MemoryAPI mem = fleet.getMemoryWithoutUpdate();
33 if (ability.isActiveOrInProgress()) {
34 mem.set(FleetAIFlags.HAS_SPEED_PENALTY, true, 0.2f);
35 mem.set(FleetAIFlags.USED_INTERDICTION_PULSE, true, 0.5f);
36 return;
37 }
38
39 if (!ability.isUsable()) return;
40
41 CampaignFleetAPI pursueTarget = mem.getFleet(FleetAIFlags.PURSUIT_TARGET);
42 CampaignFleetAPI fleeingFrom = mem.getFleet(FleetAIFlags.NEAREST_FLEEING_FROM);
43
44
45 float activationTime = ability.getSpec().getActivationDays() * Global.getSector().getClock().getSecondsPerDay();
46 if (fleeingFrom != null) {
47
49 float dist = Misc.getDistance(fleet.getLocation(), fleeingFrom.getLocation());
50 if (dist > range + 200) return;
51
52 VisibilityLevel level = fleeingFrom.getVisibilityLevelTo(fleet);
53 if (level == VisibilityLevel.NONE) return;
54
55 if (fleet.getAI() != null) {
56 if (!fleet.getAI().isHostileTo(fleeingFrom)) return;
57 }
58
59 //float speed = Math.max(1f, fleeingFrom.getTravelSpeed());
60 float speed = Math.max(1f, fleeingFrom.getVelocity().length());
61 float time = dist / speed;
62
63 boolean usingHasBenefit = false;
64
65 float interdictDur = InterdictionPulseAbility.getInterdictSeconds(fleet, fleeingFrom);
66
67 if (interdictDur > 0 && fleeingFrom.getVelocity().length() > fleet.getVelocity().length()) {
68 for (AbilityPlugin ability : fleeingFrom.getAbilities().values()) {
69 if (!ability.getSpec().hasTag(Abilities.TAG_BURN + "+")) continue;
70 if (ability.isActiveOrInProgress()) {
71 usingHasBenefit = true;
72 break;
73 }
74 }
75
76 AbilityPlugin eb = fleet.getAbility(Abilities.EMERGENCY_BURN);
77 if (eb != null && eb.getCooldownLeft() < activationTime + 1f) usingHasBenefit = true;
78 }
79
80 if (time > activationTime + 2f && time < activationTime + 7f && usingHasBenefit) {
81 if (shouldSkipUsing()) return;
82 ability.activate();
83 }
84 return;
85 }
86
87 if (pursueTarget != null) {
89 float dist = Misc.getDistance(fleet.getLocation(), pursueTarget.getLocation());
90 if (dist > range + 200) return;
91
92 VisibilityLevel level = pursueTarget.getVisibilityLevelTo(fleet);
93 if (level == VisibilityLevel.NONE) return;
94
95 if (fleet.getAI() != null) {
96 if (!fleet.getAI().isHostileTo(pursueTarget)) return;
97 }
98
99
100 //float speed = Math.max(1f, pursueTarget.getTravelSpeed());
101 float speed = Math.max(1f, pursueTarget.getVelocity().length());
102 float closingSpeed = Misc.getClosingSpeed(fleet.getLocation(), pursueTarget.getLocation(),
103 fleet.getVelocity(), pursueTarget.getVelocity());
104 speed = Math.max(1f, (speed - closingSpeed) / 2f);
105 float time = Math.max(200, (range - dist)) / speed;
106 float timeToReach = dist / fleet.getVelocity().length();
107
108 boolean usingHasBenefit = false;
109 float interdictDur = InterdictionPulseAbility.getInterdictSeconds(fleet, pursueTarget);
110
111 if (interdictDur > 0 && pursueTarget.getVelocity().length() > fleet.getVelocity().length()) {
112 for (AbilityPlugin ability : pursueTarget.getAbilities().values()) {
113 if (!ability.getSpec().hasTag(Abilities.TAG_BURN + "+")) continue;
114 if (ability.isActiveOrInProgress()) {
115 usingHasBenefit = true;
116 break;
117 }
118 }
119
120// eb = fleet.getAbility(Abilities.EMERGENCY_BURN);
121// if (eb != null && eb.getCooldownLeft() < activationTime + 1f) usingHasBenefit = true;
122 }
123
124 AbilityPlugin tj = pursueTarget.getAbility(Abilities.TRANSVERSE_JUMP);
125 if (tj != null && tj.isActiveOrInProgress() && timeToReach > activationTime &&
126 dist < range) {
127 usingHasBenefit = true;
128 }
129
130 AbilityPlugin sb = pursueTarget.getAbility(Abilities.SUSTAINED_BURN);
131 if (sb != null && sb.isActiveOrInProgress() &&
132 sb.getProgressFraction() > 0.25f &&
133 sb.getProgressFraction() <= 0.5f) {
134 usingHasBenefit = true;
135 }
136
137 if (usingHasBenefit && time > activationTime + 0.5f) {
138 if (shouldSkipUsing()) return;
139 ability.activate();
140 }
141
142 return;
143 }
144
145 }
146
147 public boolean shouldSkipUsing() {
148 for (CampaignFleetAPI other : fleet.getContainingLocation().getFleets()) {
149 if (fleet == other) continue;
150 if (other.getMemoryWithoutUpdate().contains(FleetAIFlags.USED_INTERDICTION_PULSE)) {
151 return true;
152 }
153 AbilityPlugin ip = other.getAbility(Abilities.INTERDICTION_PULSE);
154 if (ip != null && ip.isActiveOrInProgress()) return true;
155 }
156 return false;
157 }
158}
159
160
161
162
163
164
static SectorAPI getSector()
Definition Global.java:59
static float getInterdictSeconds(CampaignFleetAPI fleet, CampaignFleetAPI other)