001package com.fs.starfarer.api.impl.campaign.fleets; 002 003import java.util.Random; 004 005import org.lwjgl.util.vector.Vector2f; 006 007import com.fs.starfarer.api.EveryFrameScript; 008import com.fs.starfarer.api.Global; 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.PlanetAPI; 013import com.fs.starfarer.api.campaign.SectorEntityToken; 014import com.fs.starfarer.api.campaign.StarSystemAPI; 015import com.fs.starfarer.api.campaign.econ.MarketAPI; 016import com.fs.starfarer.api.util.Misc; 017import com.fs.starfarer.api.util.WeightedRandomPicker; 018 019public class DisposableAggroAssignmentAI implements EveryFrameScript { 020 021 protected StarSystemAPI system; 022 protected CampaignFleetAPI fleet; 023 protected DisposableFleetManager manager; 024 025 026 public DisposableAggroAssignmentAI(CampaignFleetAPI fleet, StarSystemAPI system, 027 DisposableFleetManager manager, float probStayInHyper) { 028 this.fleet = fleet; 029 this.system = system; 030 this.manager = manager; 031 032 giveInitialAssignments(probStayInHyper); 033 } 034 035 protected void giveInitialAssignments(float probStayInHyper) { 036 boolean playerInSameLocation = fleet.getContainingLocation() == Global.getSector().getCurrentLocation(); 037 038 SectorEntityToken target = null; 039 if (!playerInSameLocation && !fleet.isInHyperspace()) { // in system, player is in hyper 040 target = pickEntityToGuard(new Random(), system, fleet); 041 if (target != null) { 042 Vector2f loc = Misc.getPointAtRadius(target.getLocation(), target.getRadius() + 100f); 043 fleet.setLocation(loc.x, loc.y); 044 } else { 045 Vector2f loc = Misc.getPointAtRadius(new Vector2f(), 5000f); 046 fleet.setLocation(loc.x, loc.y); 047 } 048 } else if (fleet.isInHyperspace()) { // fleet in hyper; don't care about player being there or not 049 SectorEntityToken from = Misc.getSourceEntity(fleet); 050 if (from != null && system != null) { 051 float angle = Misc.getAngleInDegrees(system.getLocation(), from.getLocationInHyperspace()); 052 float arc = 90f; 053 angle = angle - arc / 2f + arc * (float) Math.random(); 054 //float dist = Global.getSettings().getMaxSensorRangeHyper() + 500f + 1000f * (float) Math.random(); 055 float dist = Global.getSettings().getMaxSensorRangeHyper() + 1000f; 056 Vector2f loc = Misc.getUnitVectorAtDegreeAngle(angle); 057 loc.scale(dist); 058 Vector2f.add(loc, system.getLocation(), loc); 059 060 loc = Misc.pickHyperLocationNotNearPlayer(new Vector2f(loc), Global.getSettings().getMaxSensorRangeHyper() + 500f); 061 062 fleet.setLocation(loc.x, loc.y); 063 } else { 064 Vector2f loc = Misc.pickHyperLocationNotNearPlayer(system.getLocation(), Global.getSettings().getMaxSensorRangeHyper() + 500f); 065 fleet.setLocation(loc.x, loc.y); 066 } 067 } else { // player in same location, and in-system 068 target = pickEntityToGuard(new Random(), system, fleet); 069 Vector2f loc = new Vector2f(5000, 0); 070 if (target != null) { 071 Vector2f from = target.getLocation(); 072 loc = Misc.pickLocationNotNearPlayer(system, from, 073 Global.getSettings().getMaxSensorRange() + 500f); 074 } else { // no jump points case; ??? 075 loc = Misc.pickLocationNotNearPlayer(system, 076 Misc.getPointAtRadius(new Vector2f(0, 0), 8000), 077 Global.getSettings().getMaxSensorRange() + 500f); 078 } 079 fleet.setLocation(loc.x, loc.y); 080 } 081 pickNext(target, probStayInHyper); 082 } 083 084 protected void pickNext(SectorEntityToken target, float probStayInHyper) { 085 if (fleet.isInHyperspace()) { 086 Vector2f dest = Misc.getPointAtRadius(system.getLocation(), 1000); 087 LocationAPI hyper = Global.getSector().getHyperspace(); 088 SectorEntityToken token = hyper.createToken(dest.x, dest.y); 089 fleet.addAssignment(FleetAssignment.GO_TO_LOCATION, token, 1000, 090 manager.getTravelText(system, fleet)); 091 } 092 093 if (fleet.isInHyperspace() && (float) Math.random() < probStayInHyper) { 094 fleet.addAssignment(FleetAssignment.RAID_SYSTEM, system.getHyperspaceAnchor(), 10000, 095 manager.getActionOutsideText(system, fleet)); 096 } else { 097 if (target == null) target = pickEntityToGuard(new Random(), system, fleet); 098 if (target != null) { 099 float speed = Misc.getSpeedForBurnLevel(8); 100 float dist = Misc.getDistance(fleet.getLocation(), target.getLocation()); 101 float seconds = dist / speed; 102 float days = seconds / Global.getSector().getClock().getSecondsPerDay(); 103 days += 30f + 10f * (float) Math.random(); 104 fleet.addAssignment(FleetAssignment.PATROL_SYSTEM, target, days, 105 manager.getActionInsideText(system, fleet)); 106 return; 107 } else { 108 float days = 5f + 5f * (float) Math.random(); 109 fleet.addAssignment(FleetAssignment.PATROL_SYSTEM, null, days, 110 manager.getActionInsideText(system, fleet)); 111 } 112 } 113 } 114 115 public void advance(float amount) { 116 if (fleet.getCurrentAssignment() == null) { 117 pickNext(null, 0f); 118 } 119 } 120 121 public boolean isDone() { 122 return false; 123 } 124 125 public boolean runWhilePaused() { 126 return false; 127 } 128 129 public static SectorEntityToken pickEntityToGuard(Random random, StarSystemAPI system, CampaignFleetAPI fleet) { 130 WeightedRandomPicker<SectorEntityToken> picker = new WeightedRandomPicker<SectorEntityToken>(random); 131 132 for (SectorEntityToken entity : system.getJumpPoints()) { 133 float mult = getWeightMultForPatrols(system, fleet, entity); 134 picker.add(entity, 5f * mult); 135 } 136 137 // gas giants are exits from hyperspace, so hang around there too 138 for (PlanetAPI planet : system.getPlanets()) { 139 if (planet.isGasGiant()) { 140 float mult = getWeightMultForPatrols(system, fleet, planet); 141 picker.add(planet, 5f * mult); 142 } 143 } 144 145 for (MarketAPI market : Global.getSector().getEconomy().getMarkets(system)) { 146 if (market.getFaction() != fleet.getFaction()) continue; 147 148 float mult = getWeightMultForPatrols(system, fleet, market.getPrimaryEntity()); 149 picker.add(market.getPrimaryEntity(), 5f * mult); 150 } 151 152 return picker.pick(); 153 } 154 155 public static float getWeightMultForPatrols(StarSystemAPI system, CampaignFleetAPI fleet, SectorEntityToken entity) { 156 float count = countNearbyPatrols(system, fleet, entity); 157 return 1f / (count * 10f + 1f); 158 } 159 160 public static float countNearbyPatrols(StarSystemAPI system, CampaignFleetAPI fleet, SectorEntityToken entity) { 161 float count = 0; 162 for (CampaignFleetAPI other : system.getFleets()) { 163 float dist = Misc.getDistance(other, entity); 164 if (dist > 3000) continue; 165 166 if (!Misc.isPatrol(other)) continue; 167 168 if (fleet.isHostileTo(other)) { 169 count++; 170 } 171 } 172 return count; 173 } 174 175} 176 177 178 179 180 181 182 183 184 185