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