001package com.fs.starfarer.api.impl.campaign.terrain; 002 003import com.fs.starfarer.api.campaign.PlanetAPI; 004import com.fs.starfarer.api.campaign.SectorEntityToken; 005import com.fs.starfarer.api.util.Misc; 006 007public class RangeBlockerUtil { 008 009 private int resolution; 010 private float maxRange; 011// private LocationAPI location; 012// private SectorEntityToken entity; 013// private SectorEntityToken exclude; 014 015 private float degreesPerUnit; 016 private float [] limits; 017 private float [] curr; 018 //private float [] alphas; 019 020 private boolean wasUpdated = false; 021 private boolean isAnythingShortened = false; 022 023 public RangeBlockerUtil(int resolution, float maxRange) { 024 this.resolution = resolution; 025 this.maxRange = maxRange; 026 027 //degreesPerUnit = (float) Math.floor(360f / (float) resolution); 028 degreesPerUnit = 360f / (float) resolution; 029 030 limits = new float [resolution]; 031 curr = new float [resolution]; 032 //alphas = new float [resolution]; 033 } 034 035 036 public boolean wasEverUpdated() { 037 return wasUpdated; 038 } 039 040 041 public void updateAndSync(SectorEntityToken entity, SectorEntityToken exclude, float diffMult) { 042 updateLimits(entity, exclude, diffMult); 043 sync(); 044// for (int i = 0; i < resolution; i++) { 045// alphas[i] = 1f; 046// } 047 } 048 049 public void sync() { 050 for (int i = 0; i < resolution; i++) { 051 curr[i] = limits[i]; 052 } 053 } 054 055 public float getShortenAmountAt(float angle) { 056 return maxRange - getCurrMaxAt(angle); 057 } 058 059 public float getCurrMaxAt(float angle) { 060 angle = Misc.normalizeAngle(angle); 061 062 float index = angle / 360f * resolution; 063 int i1 = (int) Math.floor(index); 064 int i2 = (int) Math.ceil(index); 065 while (i1 >= resolution) i1 -= resolution; 066 while (i2 >= resolution) i2 -= resolution; 067 068 float v1 = curr[i1]; 069 float v2 = curr[i2]; 070 071 return v1 + (v2 - v1) * (index - (int) index); 072 073 //int index = getIndexForAngle(angle); 074 //return curr[index]; 075 } 076 077 public float getAlphaAt(float angle) { 078 return 1f; 079// int index = getIndexForAngle(angle); 080// return alphas[index]; 081 } 082 083 public void advance(float amount, float minApproachSpeed, float diffMult) { 084 for (int i = 0; i < resolution; i++) { 085 curr[i] = Misc.approach(curr[i], limits[i], minApproachSpeed, diffMult, amount); 086// if (curr[i] > limits[i] + 100f) { 087// alphas[i] = Misc.approach(alphas[i], 0f, 1f, 1f, amount); 088// } else { 089// alphas[i] = Misc.approach(alphas[i], 1f, 1f, 1f, amount); 090// } 091 } 092 } 093 094 public void updateLimits(SectorEntityToken entity, SectorEntityToken exclude, float diffMult) { 095 //if (true) return; 096 097 for (int i = 0; i < resolution; i++) { 098 limits[i] = maxRange; 099 } 100 101 isAnythingShortened = false; 102 103 for (PlanetAPI planet : entity.getContainingLocation().getPlanets()) { 104 if (planet == entity || planet == exclude) continue; 105 float dist = Misc.getDistance(entity.getLocation(), planet.getLocation()); 106 if (dist > maxRange) continue; 107 108 float graceRadius = 100f; 109 graceRadius = 0f; 110 graceRadius = planet.getRadius() + 100f; 111 float span = Misc.computeAngleSpan(planet.getRadius() + graceRadius, dist); 112 113 float angle = Misc.getAngleInDegrees(entity.getLocation(), planet.getLocation()); 114 115 float offsetSize = maxRange * 0.2f; 116 117 float spanOffset = span * 0.4f * 1f / diffMult; 118 spanOffset = 0f; 119 for (float f = angle - span/2f - spanOffset; f <= angle + span/2f - spanOffset; f += degreesPerUnit) { 120 float offset = Math.abs(f - angle) / (span / 2f); 121 if (offset > 1) offset = 1; 122 offset = (1f - (float) Math.cos(offset * 3.1416f / 2f)); 123 //offset = (float) Math.sqrt(offset); 124// offset += 1f; 125 offset *= offset; 126// offset *= offset; 127// offset -= 1f; 128 //offset *= planet.getRadius() + graceRadius; 129 offset *= offsetSize; 130 131 132 int index = getIndexForAngle(f); 133 limits[index] = Math.min(dist - (planet.getRadius()) * 0.5f + offset, limits[index]); 134 isAnythingShortened = true; 135 } 136 } 137 138 wasUpdated = true; 139 } 140 141 public void block(float angle, float arc, float limit) { 142 //float radius = Misc.computeAngleRadius(angle, limit); 143 float offsetSize = Math.max(limit, maxRange * 0.1f); 144 145 for (float f = angle - arc/2f; f <= angle + arc/2f; f += degreesPerUnit) { 146 147 float offset = Math.abs(f - angle) / (arc / 2f); 148 if (offset > 1) offset = 1; 149 offset = (1f - (float) Math.cos(offset * 3.1416f / 2f)); 150 offset += 1f; 151 offset *= offset; 152 offset -= 1f; 153 offset *= offsetSize; 154 //offset = 0f; 155 offset = Math.abs(offset); 156 157 int index = getIndexForAngle(f); 158 limits[index] = Math.min(limit + offset, limits[index]); 159 isAnythingShortened = true; 160 } 161 } 162 163 public int getIndexForAngle(float angle) { 164 angle = Misc.normalizeAngle(angle); 165 166 int index = (int)Math.round(angle / 360f * (float) resolution); 167 if (index < 0) index = 0; 168 //if (index > resolution - 1) index = resolution - 1; 169 while (index >= resolution) index -= resolution; 170 171 return index; 172 } 173 174 public boolean isAnythingShortened() { 175 return isAnythingShortened; 176 } 177 178 179 public float getMaxRange() { 180 return maxRange; 181 } 182 183 184} 185 186 187 188 189 190 191 192 193 194 195