001package com.fs.starfarer.api.impl.campaign.terrain;
002
003import java.awt.Color;
004import java.util.EnumSet;
005
006import org.lwjgl.opengl.GL11;
007
008import com.fs.starfarer.api.Global;
009import com.fs.starfarer.api.campaign.CampaignEngineLayers;
010import com.fs.starfarer.api.campaign.CampaignFleetAPI;
011import com.fs.starfarer.api.campaign.SectorEntityToken;
012import com.fs.starfarer.api.campaign.TerrainAIFlags;
013import com.fs.starfarer.api.combat.ViewportAPI;
014import com.fs.starfarer.api.impl.combat.BattleCreationPluginImpl.NebulaTextureProvider;
015import com.fs.starfarer.api.loading.Description.Type;
016import com.fs.starfarer.api.ui.Alignment;
017import com.fs.starfarer.api.ui.TooltipMakerAPI;
018import com.fs.starfarer.api.util.Misc;
019
020public class NebulaTerrainPlugin extends BaseTiledTerrain implements NebulaTextureProvider {
021//      public static float MIN_BURN_PENALTY = 0.1f;
022//      public static float BURN_PENALTY_RANGE = 0.4f;
023        
024        
025        public static final float TILE_SIZE = 400;
026        public static final float VISIBLITY_MULT = 0.5f;
027        
028//      public static Map<HullSize, Float> burnPenalty = new HashMap<HullSize, Float>();
029//      static {
030//              burnPenalty.put(HullSize.FIGHTER, 3f);
031//              burnPenalty.put(HullSize.FRIGATE, 3f);
032//              burnPenalty.put(HullSize.DESTROYER, 2f);
033//              burnPenalty.put(HullSize.CRUISER, 1f);
034//              burnPenalty.put(HullSize.CAPITAL_SHIP, 0f);
035//      }
036        
037        
038        public void init(String terrainId, SectorEntityToken entity, Object param) {
039                super.init(terrainId, entity, param);
040                if (name == null || name.equals("Unknown")) name = "Nebula";
041        }
042        
043        public String getNameForTooltip() {
044                return "Nebula";
045        }
046        
047        protected Object readResolve() {
048                super.readResolve();
049                layers = EnumSet.of(CampaignEngineLayers.TERRAIN_2, CampaignEngineLayers.TERRAIN_8);
050                return this;
051        }
052        transient private EnumSet<CampaignEngineLayers> layers = EnumSet.of(CampaignEngineLayers.TERRAIN_2, CampaignEngineLayers.TERRAIN_8);
053        public EnumSet<CampaignEngineLayers> getActiveLayers() {
054                return layers;
055        }
056        
057
058        public String getNebulaMapTex() {
059                return Global.getSettings().getSpriteName(params.cat, params.key + "_map");
060        }
061
062        public String getNebulaTex() {
063                return Global.getSettings().getSpriteName(params.cat, params.key);
064        }
065        
066        public void advance(float amount) {
067                super.advance(amount);
068        }
069                
070
071        private transient CampaignEngineLayers currLayer = null;
072        public void render(CampaignEngineLayers layer, ViewportAPI viewport) {
073                currLayer = layer;
074                super.render(layer, viewport);
075
076                
077//              float x = entity.getLocation().x;
078//              float y = entity.getLocation().y;
079//              float size = getTileSize();
080//              float renderSize = getTileRenderSize();
081//              
082//              float w = tiles.length * size;
083//              float h = tiles[0].length * size;
084//              
085//              x -= w / 2f;
086//              y -= h / 2f;
087//              
088//              GL11.glDisable(GL11.GL_TEXTURE_2D);
089//              GL11.glEnable(GL11.GL_BLEND);
090//              GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
091//
092//              Color color = Color.white;
093//              GL11.glColor4ub((byte)color.getRed(),
094//                                              (byte)color.getGreen(),
095//                                              (byte)color.getBlue(),
096//                                              (byte)((float)color.getAlpha() * 0.25f));
097//              
098//              GL11.glBegin(GL11.GL_QUADS);
099//              {
100//                      GL11.glVertex2f(x, y);
101//                      GL11.glVertex2f(x, y + h);
102//                      GL11.glVertex2f(x + w, y + h);
103//                      GL11.glVertex2f(x + w, y);
104//              }
105//              GL11.glEnd();
106        }
107
108        @Override
109        public float getTileRenderSize() {
110                //return TILE_SIZE + 300f;
111                //return TILE_SIZE + 600f;
112                return TILE_SIZE * 2.5f;
113        }
114        
115        @Override
116        public float getTileContainsSize() {
117                //return TILE_SIZE + 200f;
118                return TILE_SIZE * 1.5f;
119        }
120
121        @Override
122        public float getTileSize() {
123                return TILE_SIZE;
124        }
125        
126        @Override
127        protected void renderSubArea(float startColumn, float endColumn,
128                        float startRow, float endRow, float factor, int samples,
129                        float alphaMult) {
130                
131//              if (currLayer != CampaignEngineLayers.TERRAIN_8) {
132//                      float size = getTileSize();
133//                      float renderSize = getTileRenderSize();
134//                      float x = entity.getLocation().x - renderSize / 2f;
135//                      float y = entity.getLocation().y - renderSize / 2f;
136//                      
137//                      float w = tiles.length * size + renderSize;
138//                      float h = tiles[0].length * size + renderSize;
139//                      
140//
141//                      GL11.glColorMask(false, false, false, true);
142//                      GL11.glBlendFunc(GL11.GL_ONE, GL11.GL_ZERO);
143//                      GL11.glColor4ub((byte)0,
144//                                      (byte)0,
145//                                      (byte)0,
146//                                      (byte)255);
147//                      GL11.glBegin(GL11.GL_QUADS);
148//                      {
149//                              GL11.glVertex2f(x, y);
150//                              GL11.glVertex2f(x, y + h);
151//                              GL11.glVertex2f(x + w, y + h);
152//                              GL11.glVertex2f(x + w, y);
153//                      }
154//                      GL11.glEnd();
155//                      
156//                      GL11.glColorMask(true, true, true, false);
157//                      GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_DST_ALPHA);
158//                      Color color = getRenderColor();
159//                      GL11.glColor4ub((byte)color.getRed(),
160//                                      (byte)color.getGreen(),
161//                                      (byte)color.getBlue(),
162//                                      (byte)((float)color.getAlpha() * alphaMult));
163//              }
164                
165                super.renderSubArea(startColumn, endColumn, startRow, endRow, factor, samples, alphaMult);
166                
167                
168//              if (currLayer != CampaignEngineLayers.TERRAIN_8) {
169//                      float size = getTileSize();
170//                      float renderSize = getTileRenderSize();
171//                      float x = entity.getLocation().x - renderSize / 2f;
172//                      float y = entity.getLocation().y - renderSize / 2f;
173//                      float w = tiles.length * size + renderSize;
174//                      float h = tiles[0].length * size + renderSize;
175//                      
176//                      x -= w/2f;
177//                      y -= h/2f;
178//                      
179//                      
180//                      GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_DST_COLOR);
181//                      GL11.glColor4ub((byte)0,
182//                                      (byte)0,
183//                                      (byte)0,
184//                                      (byte)255);
185//                      GL11.glBegin(GL11.GL_QUADS);
186//                      {
187//                              GL11.glVertex2f(x, y);
188//                              GL11.glVertex2f(x, y + h);
189//                              GL11.glVertex2f(x + w, y + h);
190//                              GL11.glVertex2f(x + w, y);
191//                      }
192//                      GL11.glEnd();
193//                      
194//              }
195        }
196
197        @Override
198        public void preRender(CampaignEngineLayers layer, float alphaMult) {
199                GL11.glEnable(GL11.GL_BLEND);
200                if (entity.isInHyperspace()) {
201//                      if (layer == CampaignEngineLayers.TERRAIN_8) {
202//                              GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
203//                      } else {
204//                              GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
205//                      }
206                        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
207                } else {
208                        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
209                }
210                //GL11.glDisable(GL11.GL_BLEND);
211                
212                if (layer == CampaignEngineLayers.TERRAIN_8) {
213                        alphaMult *= 0.20f;
214                        //alphaMult *= 0.50f;
215                }
216                
217                Color color = getRenderColor();
218                GL11.glColor4ub((byte)color.getRed(),
219                                (byte)color.getGreen(),
220                                (byte)color.getBlue(),
221                                (byte)((float)color.getAlpha() * alphaMult));
222        }
223        
224        @Override
225        public void preMapRender(float alphaMult) {
226                GL11.glEnable(GL11.GL_BLEND);
227                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
228                //GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
229                
230                //Color color = new Color(125,125,200,255);
231                //Color color = new Color(100,100,150,255);
232                Color color = getRenderColor();
233                GL11.glColor4ub((byte)color.getRed(),
234                                (byte)color.getGreen(),
235                                (byte)color.getBlue(),
236                                (byte)((float)color.getAlpha() * alphaMult));
237        }
238
239        @Override
240        public Color getRenderColor() {
241                return Color.white;
242                //return Color.black;
243                //return Misc.interpolateColor(Color.black, Color.white, 0.1f);
244                //return new Color(255,255,255,150);
245        }
246        
247        @Override
248        public void applyEffect(SectorEntityToken entity, float days) {
249                if (entity instanceof CampaignFleetAPI) {
250                        CampaignFleetAPI fleet = (CampaignFleetAPI) entity;
251                        fleet.getStats().addTemporaryModMult(0.1f, getModId() + "_1",
252                                                                "Inside nebula", VISIBLITY_MULT, 
253                                                                fleet.getStats().getDetectedRangeMod());
254                        
255                        float penalty = Misc.getBurnMultForTerrain(fleet);
256                        //float penalty = getBurnPenalty(fleet);
257                        fleet.getStats().addTemporaryModMult(0.1f, getModId() + "_2",
258                                                                "Inside nebula", penalty, 
259                                                                fleet.getStats().getFleetwideMaxBurnMod());
260//                      fleet.getStats().addTemporaryModPercent(0.1f, getModId() + "_2",
261//                                                              "Inside nebula", -100f * penalty, 
262//                                                              fleet.getStats().getFleetwideMaxBurnMod());
263
264                        
265//                      if (fleet.isPlayerFleet()) {
266//                              System.out.println("23gfgwefwef");
267//                      }
268//                      String buffId = getModId();
269//                      float buffDur = 0.1f;
270//                      for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) {
271//                              float penalty = burnPenalty.get(member.getHullSpec().getHullSize());
272//                              
273//                              Buff test = member.getBuffManager().getBuff(buffId);
274//                              if (test instanceof MaxBurnBuff) {
275//                                      MaxBurnBuff buff = (MaxBurnBuff) test;
276//                                      buff.setDur(buffDur);
277//                              } else {
278//                                      member.getBuffManager().addBuff(new MaxBurnBuff(buffId, -penalty, buffDur));
279//                              }
280//                      }
281                }
282        }
283        
284//      public static float getBurnPenalty(CampaignFleetAPI fleet) {
285//              float min = Global.getSettings().getBaseFleetSelectionRadius() + Global.getSettings().getFleetSelectionRadiusPerUnitSize();
286//              float max = Global.getSettings().getMaxFleetSelectionRadius();
287//              float radius = fleet.getRadius();
288//
289//              float penalty = 1f - (radius - min) / (max - min);
290//              if (penalty > 1) penalty = 1;
291//              if (penalty < 0) penalty = 0;
292//              penalty = MIN_BURN_PENALTY + penalty * BURN_PENALTY_RANGE;
293//
294//              float skillMod = fleet.getCommanderStats().getDynamic().getValue(Stats.NAVIGATION_PENALTY_MULT);
295//              penalty *= skillMod;
296//              
297//              return penalty;
298//      }
299
300        public boolean hasTooltip() {
301                return true;
302        }
303        
304        public void createTooltip(TooltipMakerAPI tooltip, boolean expanded) {
305                float pad = 10f;
306                float small = 5f;
307                Color gray = Misc.getGrayColor();
308                Color highlight = Misc.getHighlightColor();
309                Color fuel = Global.getSettings().getColor("progressBarFuelColor");
310                Color bad = Misc.getNegativeHighlightColor();
311                Color text = Misc.getTextColor();
312                
313                tooltip.addTitle("Nebula");
314                tooltip.addPara(Global.getSettings().getDescription(getTerrainId(), Type.TERRAIN).getText1(), pad);
315                float nextPad = pad;
316                if (expanded) {
317                        tooltip.addSectionHeading("Travel", Alignment.MID, pad);
318                        nextPad = small;
319                }
320                tooltip.addPara("Reduces the range at which fleets inside can be detected by %s.", nextPad,
321                                highlight, 
322                                "" + (int) ((1f - VISIBLITY_MULT) * 100) + "%"
323                );
324                
325                tooltip.addPara("Reduces the travel speed of fleets inside by up to %s. Larger fleets are slowed down more.",
326                                pad,
327                                highlight,
328                                "" + (int) ((Misc.BURN_PENALTY_MULT) * 100f) + "%"
329                );
330                
331                float penalty = Misc.getBurnMultForTerrain(Global.getSector().getPlayerFleet());
332                String penaltyStr = Misc.getRoundedValue(1f - penalty);
333                tooltip.addPara("Your fleet's speed is reduced by %s.", pad,
334                                highlight,
335                                "" + (int) Math.round((1f - penalty) * 100) + "%"
336                                //Strings.X + penaltyStr
337                );
338                
339//              tooltip.addPara("Reduces the maximum burn level of ships depending on size. Larger ship classes are able to exploit a higher mass to cross section ratio and suffer a smaller penalty.", pad);
340//              tooltip.beginGrid(150, 1);
341//              tooltip.addToGrid(0, 0, "  Frigates", "" + -burnPenalty.get(HullSize.FRIGATE).intValue());
342//              tooltip.addToGrid(0, 1, "  Destroyers", "" + -burnPenalty.get(HullSize.DESTROYER).intValue());
343//              tooltip.addToGrid(0, 2, "  Cruisers", "" + -burnPenalty.get(HullSize.CRUISER).intValue());
344//              tooltip.addToGrid(0, 3, "  Capital ships", "" + -burnPenalty.get(HullSize.CAPITAL_SHIP).intValue());
345//              tooltip.addGrid(small);
346                
347                if (expanded) { 
348                        tooltip.addSectionHeading("Combat", Alignment.MID, pad);
349                        tooltip.addPara("Numerous patches of nebula present on the battlefield, but the medium is not dense enough to affect ships moving at combat speeds.", small);
350//                      tooltip.addPara("Numerous patches of nebula present on the battlefield, slowing ships down to a percentage of their top speed.", small);
351//                      tooltip.beginGrid(150, 1);
352//      //              nebulaSpeedFighter":1,
353//      //              "nebulaSpeedFrigate":0.7,
354//      //              "nebulaSpeedDestroyer":0.8,
355//      //              "nebulaSpeedCruiser":0.9,
356//      //              "nebulaSpeedCapital":1,
357//                      tooltip.addToGrid(0, 0, "  Frigates", "" + (int)(Global.getSettings().getFloat("nebulaSpeedFrigate") * 100f) + "%");
358//                      tooltip.addToGrid(0, 1, "  Destroyers", "" + (int)(Global.getSettings().getFloat("nebulaSpeedDestroyer") * 100f) + "%");
359//                      tooltip.addToGrid(0, 2, "  Cruisers", "" + (int)(Global.getSettings().getFloat("nebulaSpeedCruiser") * 100f) + "%");
360//                      //tooltip.addToGrid(0, 3, "  Capital ships", "" + (int)(Global.getSettings().getFloat("nebulaSpeedCapital") * 100f) + "%");
361//                      tooltip.addGrid(small);
362//                      
363//                      tooltip.addPara("Capital ships and fighters are not affected.", pad);
364                }
365                
366                //tooltip.addPara("Does not stack with other similar terrain effects.", pad);
367        }
368        
369        public boolean isTooltipExpandable() {
370                return true;
371        }
372        
373        public float getTooltipWidth() {
374                return 350f;
375        }
376        
377        public String getEffectCategory() {
378                return "nebula-like";
379        }
380
381        public boolean hasAIFlag(Object flag) {
382                return flag == TerrainAIFlags.REDUCES_DETECTABILITY || 
383                                flag == TerrainAIFlags.REDUCES_SPEED_LARGE||
384                                flag == TerrainAIFlags.TILE_BASED
385                                ;
386        }
387}
388
389
390