001package com.fs.starfarer.api.impl.campaign.procgen.themes; 002 003import java.util.List; 004 005import org.lwjgl.util.vector.Vector2f; 006 007import com.fs.starfarer.api.Global; 008import com.fs.starfarer.api.Script; 009import com.fs.starfarer.api.campaign.CampaignFleetAPI; 010import com.fs.starfarer.api.campaign.FleetAssignment; 011import com.fs.starfarer.api.campaign.LocationAPI; 012import com.fs.starfarer.api.campaign.SectorEntityToken; 013import com.fs.starfarer.api.campaign.StarSystemAPI; 014import com.fs.starfarer.api.impl.campaign.fleets.RouteLocationCalculator; 015import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData; 016import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment; 017import com.fs.starfarer.api.util.Misc; 018 019public class RouteFleetAssignmentAI extends BaseAssignmentAI { 020 021 public static enum TravelState { 022 IN_SYSTEM, 023 LEAVING_SYSTEM, 024 IN_HYPER_TRANSIT, 025 ENTERING_SYSTEM, 026 } 027 028 protected RouteData route; 029 protected Boolean gaveReturnAssignments = null; 030 031 032 public RouteFleetAssignmentAI(CampaignFleetAPI fleet, RouteData route, FleetActionDelegate delegate) { 033 super(); 034 this.fleet = fleet; 035 this.route = route; 036 this.delegate = delegate; 037 giveInitialAssignments(); 038 } 039 public RouteFleetAssignmentAI(CampaignFleetAPI fleet, RouteData route) { 040 super(); 041 this.fleet = fleet; 042 this.route = route; 043 giveInitialAssignments(); 044 } 045 046 protected TravelState getTravelState(RouteSegment segment) { 047 if (segment.isInSystem()) { 048 return TravelState.IN_SYSTEM; 049 } 050 051 if (segment.hasLeaveSystemPhase() && segment.getLeaveProgress() < 1f) { 052 return TravelState.LEAVING_SYSTEM; 053 } 054 if (segment.hasEnterSystemPhase() && segment.getEnterProgress() > 0f) { 055 return TravelState.ENTERING_SYSTEM; 056 } 057 058 return TravelState.IN_HYPER_TRANSIT; 059 } 060 061 protected LocationAPI getLocationForState(RouteSegment segment, TravelState state) { 062 switch (state) { 063 case ENTERING_SYSTEM: { 064 if (segment.to != null) { 065 return segment.to.getContainingLocation(); 066 } 067 return segment.from.getContainingLocation(); 068 } 069 case IN_HYPER_TRANSIT: return Global.getSector().getHyperspace(); 070 case IN_SYSTEM: return segment.from.getContainingLocation(); 071 case LEAVING_SYSTEM: return segment.from.getContainingLocation(); 072 } 073 return null; 074 } 075 076 protected void giveInitialAssignments() { 077 TravelState state = getTravelState(route.getCurrent()); 078 LocationAPI conLoc = getLocationForState(route.getCurrent(), state); 079 080 if (fleet.getContainingLocation() != null) { 081 fleet.getContainingLocation().removeEntity(fleet); 082 } 083 conLoc.addEntity(fleet); 084 085// Vector2f loc = route.getInterpolatedLocation(); 086// fleet.setLocation(loc.x, loc.y); 087 fleet.setFacing((float) Math.random() * 360f); 088 089 pickNext(true); 090 } 091 092 @Override 093 public void advance(float amount) { 094 advance(amount, true); 095 } 096 097 protected void advance(float amount, boolean withReturnAssignments) { 098 if (withReturnAssignments && route.isExpired() && gaveReturnAssignments == null) { 099 RouteSegment current = route.getCurrent(); 100 if (current != null && current.from != null && 101 Misc.getDistance(fleet.getLocation(), current.from.getLocation()) < 1000f) { 102 fleet.clearAssignments(); 103 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION_AND_DESPAWN, current.from, 1000f, 104 "returning to " + current.from.getName()); 105 } else { 106 Misc.giveStandardReturnToSourceAssignments(fleet); 107 } 108 gaveReturnAssignments = true; 109 return; 110 } 111 super.advance(amount); 112 } 113 114 protected String getTravelActionText(RouteSegment segment) { 115 return "traveling"; 116 } 117 118 protected String getInSystemActionText(RouteSegment segment) { 119 return "patrolling"; 120 } 121 122 protected String getStartingActionText(RouteSegment segment) { 123 if (segment.from == route.getMarket().getPrimaryEntity()) { 124 return "orbiting " + route.getMarket().getName(); 125 } 126 return "patrolling"; 127 } 128 129 protected String getEndingActionText(RouteSegment segment) { 130 SectorEntityToken to = segment.to; 131 if (to == null) to = segment.from; 132 if (to == null) to = route.getMarket().getPrimaryEntity(); 133 return "returning to " + to.getName(); 134 //return "returning to " + route.getMarket().getName()); 135 //return "orbiting " + route.getMarket().getName(); 136 } 137 138 protected void pickNext() { 139 pickNext(false); 140 } 141 142 protected void pickNext(boolean justSpawned) { 143 RouteSegment current = route.getCurrent(); 144 if (current == null) return; 145 146 List<RouteSegment> segments = route.getSegments(); 147 int index = route.getSegments().indexOf(route.getCurrent()); 148 149 150 if (index == 0 && route.getMarket() != null && !current.isTravel()) { 151 if (current.getFrom() != null && (current.getFrom().isSystemCenter() || current.getFrom().getMarket() != route.getMarket())) { 152 addLocalAssignment(current, justSpawned); 153 } else { 154 addStartingAssignment(current, justSpawned); 155 } 156 return; 157 } 158 159 if (index == segments.size() - 1 && route.getMarket() != null && !current.isTravel() 160 && (current.elapsed >= current.daysMax || current.getFrom() == route.getMarket().getPrimaryEntity())) { 161 addEndingAssignment(current, justSpawned); 162 return; 163 } 164 165 // transiting from current to next; may or may not be in the same star system 166 if (current.isTravel()) { 167 if (index == segments.size() - 1 && 168 fleet.getContainingLocation() == current.to.getContainingLocation() && 169 current.elapsed >= current.daysMax) { 170 addEndingAssignment(current, justSpawned); 171 } else { 172 addTravelAssignment(current, justSpawned); 173 } 174 return; 175 } 176 177 // in a system or in a hyperspace location for some time 178 if (!current.isTravel()) { 179 addLocalAssignment(current, justSpawned); 180 } 181 } 182 183 protected void addStartingAssignment(final RouteSegment current, boolean justSpawned) { 184 SectorEntityToken from = current.getFrom(); 185 if (from == null) from = route.getMarket().getPrimaryEntity(); 186 187 if (justSpawned) { 188 float progress = current.getProgress(); 189 RouteLocationCalculator.setLocation(fleet, progress, from, from); 190 } 191 fleet.addAssignment(FleetAssignment.ORBIT_PASSIVE, from, 192 current.daysMax - current.elapsed, getStartingActionText(current), 193 goNextScript(current)); 194 } 195 196 protected Script goNextScript(final RouteSegment current) { 197 return new Script() { 198 public void run() { 199 route.goToAtLeastNext(current); 200 } 201 }; 202 } 203 204 protected void addEndingAssignment(final RouteSegment current, boolean justSpawned) { 205 if (justSpawned) { 206 float progress = current.getProgress(); 207 RouteLocationCalculator.setLocation(fleet, progress, 208 current.getDestination(), current.getDestination()); 209 } 210// if (justSpawned) { 211// //Vector2f loc = route.getMarket().getPrimaryEntity().getLocation(); 212// Vector2f loc = current.getDestination().getLocation(); 213// loc = Misc.getPointWithinRadius(loc, 214// current.getDestination().getRadius() + 100 + (float) Math.random() * 100f); 215// fleet.setLocation(loc.x, loc.y); 216// } 217 218 SectorEntityToken to = current.to; 219 if (to == null) to = current.from; 220 if (to == null) to = route.getMarket().getPrimaryEntity(); 221 222 if (to == null || !to.isAlive()) { 223 Vector2f loc = Misc.getPointAtRadius(fleet.getLocationInHyperspace(), 5000); 224 SectorEntityToken token = Global.getSector().getHyperspace().createToken(loc); 225 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION_AND_DESPAWN, token, 1000f); 226 return; 227 } 228 229 230 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION, to, 1000f, 231 "returning to " + to.getName()); 232 if (current.daysMax > current.elapsed) { 233 fleet.addAssignment(FleetAssignment.ORBIT_PASSIVE, to, 234 //current.daysMax - current.elapsed, "orbiting " + to.getName()); 235 current.daysMax - current.elapsed, getEndingActionText(current)); 236 } 237 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION_AND_DESPAWN, to, 238 1000f, getEndingActionText(current), 239 goNextScript(current)); 240 } 241 242 protected void addLocalAssignment(final RouteSegment current, boolean justSpawned) { 243 if (justSpawned) { 244 float progress = current.getProgress(); 245 RouteLocationCalculator.setLocation(fleet, progress, 246 current.from, current.getDestination()); 247 } 248 if (current.from != null && current.to == null && !current.isFromSystemCenter()) { 249// if (justSpawned) { 250// Vector2f loc = Misc.getPointWithinRadius(current.from.getLocation(), 500); 251// fleet.setLocation(loc.x, loc.y); 252// } 253 fleet.addAssignment(FleetAssignment.ORBIT_AGGRESSIVE, current.from, 254 current.daysMax - current.elapsed, getInSystemActionText(current), 255 goNextScript(current)); 256 return; 257 } 258 259// if (justSpawned) { 260// Vector2f loc = Misc.getPointAtRadius(new Vector2f(), 8000); 261// fleet.setLocation(loc.x, loc.y); 262// } 263 264 SectorEntityToken target = null; 265 if (current.from.getContainingLocation() instanceof StarSystemAPI) { 266 target = ((StarSystemAPI)current.from.getContainingLocation()).getCenter(); 267 } else { 268 target = Global.getSector().getHyperspace().createToken(current.from.getLocation().x, current.from.getLocation().y); 269 } 270 271 fleet.addAssignment(FleetAssignment.PATROL_SYSTEM, target, 272 current.daysMax - current.elapsed, getInSystemActionText(current)); 273 } 274 275 protected void addTravelAssignment(final RouteSegment current, boolean justSpawned) { 276 if (justSpawned) { 277 TravelState state = getTravelState(current); 278 if (state == TravelState.LEAVING_SYSTEM) { 279 float p = current.getLeaveProgress(); 280 SectorEntityToken jp = RouteLocationCalculator.findJumpPointToUse(fleet, current.from); 281 if (jp == null) jp = current.from; 282 RouteLocationCalculator.setLocation(fleet, p, 283 current.from, jp); 284 285// JumpPointAPI jp = Misc.findNearestJumpPointTo(current.from); 286// if (jp != null) { 287// Vector2f loc = Misc.interpolateVector(current.from.getLocation(), 288// jp.getLocation(), 289// p); 290// fleet.setLocation(loc.x, loc.y); 291// } else { 292// fleet.setLocation(current.from.getLocation().x, current.from.getLocation().y); 293// } 294// randomizeFleetLocation(p); 295 } 296 else if (state == TravelState.ENTERING_SYSTEM) { 297 float p = current.getEnterProgress(); 298 SectorEntityToken jp = RouteLocationCalculator.findJumpPointToUse(fleet, current.to); 299 if (jp == null) jp = current.to; 300 RouteLocationCalculator.setLocation(fleet, p, 301 jp, current.to); 302 303// JumpPointAPI jp = Misc.findNearestJumpPointTo(current.to); 304// if (jp != null) { 305// Vector2f loc = Misc.interpolateVector(jp.getLocation(), 306// current.to.getLocation(), 307// p); 308// fleet.setLocation(loc.x, loc.y); 309// } else { 310// fleet.setLocation(current.to.getLocation().x, current.to.getLocation().y); 311// } 312// randomizeFleetLocation(p); 313 } 314 else if (state == TravelState.IN_SYSTEM) { 315 float p = current.getTransitProgress(); 316 RouteLocationCalculator.setLocation(fleet, p, 317 current.from, current.to); 318// Vector2f loc = Misc.interpolateVector(current.from.getLocation(), 319// current.to.getLocation(), 320// p); 321// fleet.setLocation(loc.x, loc.y); 322// randomizeFleetLocation(p); 323 } 324 else if (state == TravelState.IN_HYPER_TRANSIT) { 325 float p = current.getTransitProgress(); 326 SectorEntityToken t1 = Global.getSector().getHyperspace().createToken( 327 current.from.getLocationInHyperspace().x, 328 current.from.getLocationInHyperspace().y); 329 SectorEntityToken t2 = Global.getSector().getHyperspace().createToken( 330 current.to.getLocationInHyperspace().x, 331 current.to.getLocationInHyperspace().y); 332 RouteLocationCalculator.setLocation(fleet, p, t1, t2); 333 334// Vector2f loc = Misc.interpolateVector(current.getContainingLocationFrom().getLocation(), 335// current.getContainingLocationTo().getLocation(), 336// p); 337// fleet.setLocation(loc.x, loc.y); 338// randomizeFleetLocation(p); 339 } 340 341// 342// Vector2f loc = route.getInterpolatedLocation(); 343// Random random = new Random(); 344// if (route.getSeed() != null) { 345// random = Misc.getRandom(route.getSeed(), 1); 346// } 347// loc = Misc.getPointWithinRadius(loc, 2000f, random); 348// fleet.setLocation(loc.x, loc.y); 349 } 350 351 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION, current.to, 10000f, getTravelActionText(current), 352 goNextScript(current)); 353 354// if (current.isInSystem()) { 355// fleet.addAssignment(FleetAssignment.GO_TO_LOCATION, current.to, 10000f, getTravelActionText(current), 356// goNextScript(current)); 357// } else { 358// SectorEntityToken target = current.to; 359//// if (current.to.getContainingLocation() instanceof StarSystemAPI) { 360//// target = ((StarSystemAPI)current.to.getContainingLocation()).getCenter(); 361//// } 362// fleet.addAssignment(FleetAssignment.GO_TO_LOCATION, target, 10000f, getTravelActionText(current), 363// goNextScript(current)); 364// } 365 } 366 367 368 369} 370 371 372 373 374 375 376 377 378 379