001package com.fs.starfarer.api.impl.campaign.ghosts; 002 003import java.util.List; 004import java.util.Random; 005 006import org.lwjgl.util.vector.Vector2f; 007 008import com.fs.starfarer.api.Global; 009import com.fs.starfarer.api.campaign.CampaignFleetAPI; 010import com.fs.starfarer.api.campaign.CampaignTerrainAPI; 011import com.fs.starfarer.api.campaign.LocationAPI; 012import com.fs.starfarer.api.impl.campaign.terrain.HyperspaceTerrainPlugin; 013import com.fs.starfarer.api.impl.campaign.velfield.SlipstreamTerrainPlugin2; 014import com.fs.starfarer.api.util.Misc; 015import com.fs.starfarer.api.util.WeightedRandomPicker; 016 017public class BaseSensorGhostCreator implements SensorGhostCreator { 018 019 public List<SensorGhost> createGhost(SensorGhostManager manager) { 020 return null; 021 } 022 023 public float getFrequency(SensorGhostManager manager) { 024 return 10f; 025 } 026 027 public String getId() { 028 return getClass().getSimpleName(); 029 } 030 031 public float getTimeoutDaysOnSuccessfulCreate(SensorGhostManager manager) { 032 return 10f + manager.getRandom().nextFloat() * 10f; 033 } 034 035 036 public static Vector2f findClearHyperspaceArea(Vector2f from, float minRange, float maxRange, float radius, Random random) { 037 return findHyperspaceArea(from, minRange, maxRange, radius, random, true, 0f); 038 } 039 public static Vector2f findDeepHyperspaceArea(Vector2f from, float minRange, float maxRange, float radius, Random random) { 040 return findHyperspaceArea(from, minRange, maxRange, radius, random, false, 0f); 041 } 042 public static Vector2f findHyperspaceArea(Vector2f from, float minRange, float maxRange, float radius, Random random, boolean clear, float noSlipstreamRange) { 043 if (random == null) random = Misc.random; 044 045 CampaignTerrainAPI terrain = Misc.getHyperspaceTerrain(); 046 if (terrain == null) return null; 047 048 HyperspaceTerrainPlugin plugin = (HyperspaceTerrainPlugin) terrain.getPlugin(); 049 050 int[][] tiles = plugin.getTiles(); 051 float perTile = plugin.getTileSize(); 052 int areaSize = (int) Math.ceil(radius / perTile); 053 054 055 Vector2f best = null; 056 float bestScore = 0f; 057 058 float total = (areaSize + areaSize + 1) * (areaSize + areaSize + 1); 059 if (total < 1f) total = 1f; 060 for (int k = 0; k < 20; k++) { 061 Vector2f test = Misc.getPointWithinRadiusUniform(from, minRange, maxRange, random); 062 int [] coords = plugin.getTile(test); 063 if (coords == null) continue; 064 065 if (noSlipstreamRange > 0) { 066 if (Misc.isInsideSlipstream(test, noSlipstreamRange)) continue; 067 } 068 069 float count = 0f; 070 for (int i = coords[0] - areaSize; i <= coords[0] + areaSize; i++) { 071 if (i < 0) continue; 072 if (i >= tiles.length) continue; 073 for (int j = coords[1] - areaSize; j < coords[1] + areaSize; j++) { 074 if (j < 0) continue; 075 if (j >= tiles[0].length) continue; 076 077 int texIndex = tiles[i][j]; 078 if (clear) { 079 if (texIndex <= 0) { 080 count++; 081 } 082 } else { 083 if (texIndex > 0) { 084 count++; 085 } 086 } 087 } 088 } 089 float score = count / total; 090 if (score >= 0.75f && score > bestScore) { 091 best = test; 092 bestScore = score; 093 } 094 } 095 096 return best; 097 } 098 099 public static SlipstreamTerrainPlugin2 pickNearbySlipstream(float radius, Random random) { 100 return pickNearbySlipstream(radius, Global.getSector().getHyperspace(), random); 101 } 102 public static SlipstreamTerrainPlugin2 pickNearbySlipstream(float radius, LocationAPI location, Random random) { 103 WeightedRandomPicker<SlipstreamTerrainPlugin2> picker = new WeightedRandomPicker<SlipstreamTerrainPlugin2>(random); 104 CampaignFleetAPI pf = Global.getSector().getPlayerFleet(); 105 Vector2f loc = pf.getLocation(); 106 107 for (CampaignTerrainAPI ter : location.getTerrainCopy()) { 108 if (ter.getPlugin() instanceof SlipstreamTerrainPlugin2) { 109 SlipstreamTerrainPlugin2 plugin = (SlipstreamTerrainPlugin2) ter.getPlugin(); 110 if (plugin.containsPoint(loc, radius)) { 111 float w = 1f; 112 if (plugin.isPreventedFromAffecting(pf)) { 113 w *= 0.25f; // more likely to pick the slipstream the player is in, if there is one 114 } 115 picker.add(plugin, w); 116 } 117 } 118 } 119 return picker.pick(); 120 } 121 122 // moved to Misc 123// public static boolean isInsideSlipstream(Vector2f loc, float radius) { 124// return isInsideSlipstream(loc, radius, Global.getSector().getHyperspace()); 125// } 126// public static boolean isInsideSlipstream(Vector2f loc, float radius, LocationAPI location) { 127// for (CampaignTerrainAPI ter : location.getTerrainCopy()) { 128// if (ter.getPlugin() instanceof SlipstreamTerrainPlugin2) { 129// SlipstreamTerrainPlugin2 plugin = (SlipstreamTerrainPlugin2) ter.getPlugin(); 130// if (plugin.containsPoint(loc, radius)) { 131// return true; 132// } 133// } 134// } 135// return false; 136// } 137 138 public boolean canSpawnWhilePlayerInOrNearSlipstream() { 139 return false; 140 } 141 142 public boolean canSpawnWhilePlayerInAbyss() { 143 return false; 144 } 145 146 public boolean canSpawnWhilePlayerOutsideAbyss() { 147 return true; 148 } 149} 150 151 152 153 154 155