001package com.fs.starfarer.api.impl.hullmods;
002
003import java.awt.Color;
004import java.util.HashMap;
005import java.util.Map;
006
007import com.fs.starfarer.api.GameState;
008import com.fs.starfarer.api.Global;
009import com.fs.starfarer.api.campaign.CampaignFleetAPI;
010import com.fs.starfarer.api.combat.HullModFleetEffect;
011import com.fs.starfarer.api.combat.MutableShipStatsAPI;
012import com.fs.starfarer.api.combat.ShipAPI;
013import com.fs.starfarer.api.combat.ShipAPI.HullSize;
014import com.fs.starfarer.api.fleet.FleetMemberAPI;
015import com.fs.starfarer.api.impl.campaign.ids.Stats;
016import com.fs.starfarer.api.ui.LabelAPI;
017import com.fs.starfarer.api.ui.TooltipMakerAPI;
018import com.fs.starfarer.api.util.Misc;
019
020@SuppressWarnings("unchecked")
021public class HighResSensors extends BaseLogisticsHullMod  implements HullModFleetEffect {
022
023//      public static float BONUS = 60;
024//      public static float CAPITAL_BONUS = 100;
025        
026        public static float MIN_CR = 0.1f;
027        public static String MOD_KEY = "core_HighResSensors";
028        
029        private static Map combatMag = new HashMap();
030        private static Map mag = new HashMap();
031//      static {
032//              mag.put(HullSize.FRIGATE, Global.getSettings().getFloat("baseSensorFrigate"));
033//              mag.put(HullSize.DESTROYER, Global.getSettings().getFloat("baseSensorDestroyer"));
034//              mag.put(HullSize.CRUISER, Global.getSettings().getFloat("baseSensorCruiser"));
035//              mag.put(HullSize.CAPITAL_SHIP, Global.getSettings().getFloat("baseSensorCapital"));
036//      }
037        static {
038                mag.put(HullSize.FRIGATE, 50f);
039                mag.put(HullSize.DESTROYER, 75f);
040                mag.put(HullSize.CRUISER, 100f);
041                mag.put(HullSize.CAPITAL_SHIP, 150f);
042                
043                combatMag.put(HullSize.FRIGATE, 1000f);
044                combatMag.put(HullSize.DESTROYER, 1500f);
045                combatMag.put(HullSize.CRUISER, 2000f);
046                combatMag.put(HullSize.CAPITAL_SHIP, 2500f);
047        }
048        
049        public void applyEffectsBeforeShipCreation(HullSize hullSize, MutableShipStatsAPI stats, String id) {
050                //stats.getSensorStrength().modifyPercent(id, ((Float) mag.get(hullSize)).intValue());
051//              float bonus = BONUS;
052//              if (hullSize == HullSize.CAPITAL_SHIP) bonus = CAPITAL_BONUS;
053//              stats.getSensorStrength().modifyFlat(id, bonus);
054                
055                stats.getDynamic().getMod(Stats.HRS_SENSOR_RANGE_MOD).modifyFlat(id, (Float) mag.get(hullSize));
056                
057                boolean sMod = isSMod(stats);
058                if (sMod) {
059                        float mag = ((Float) combatMag.get(hullSize)).intValue();
060                        stats.getSightRadiusMod().modifyFlat(id, mag);
061                }
062        }
063        
064        public String getSModDescriptionParam(int index, HullSize hullSize) {
065                if (index == 0) return "" + ((Float) combatMag.get(HullSize.FRIGATE)).intValue();
066                if (index == 1) return "" + ((Float) combatMag.get(HullSize.DESTROYER)).intValue();
067                if (index == 2) return "" + ((Float) combatMag.get(HullSize.CRUISER)).intValue();
068                if (index == 3) return "" + ((Float) combatMag.get(HullSize.CAPITAL_SHIP)).intValue();
069                return null;
070        }
071        public String getDescriptionParam(int index, HullSize hullSize) {
072//              if (index == 0) return "" + (int) BONUS;
073//              if (index == 1) return "" + (int) CAPITAL_BONUS;
074//              if (index == 0) return "" + ((Float) mag.get(HullSize.FRIGATE)).intValue();
075//              if (index == 1) return "" + ((Float) mag.get(HullSize.DESTROYER)).intValue();
076//              if (index == 2) return "" + ((Float) mag.get(HullSize.CRUISER)).intValue();
077                //if (index == 3) return "" + ((Float) mag.get(HullSize.CAPITAL_SHIP)).intValue();
078                return null;
079        }
080
081        public void advanceInCampaign(CampaignFleetAPI fleet) {
082        }
083        public boolean withAdvanceInCampaign() {
084                return false;
085        }
086        public boolean withOnFleetSync() {
087                return true;
088        }
089
090        public void onFleetSync(CampaignFleetAPI fleet) {
091                float modifier = getAdjustedHRSModifier(fleet, null, 0f);
092                if (modifier <= 0) {
093                        fleet.getSensorRangeMod().unmodifyFlat(MOD_KEY);
094                } else {
095                        fleet.getSensorRangeMod().modifyFlat(MOD_KEY, modifier, "Ships with high resolution sensors");
096                }
097        }
098        
099        @Override
100        public boolean shouldAddDescriptionToTooltip(HullSize hullSize, ShipAPI ship, boolean isForModSpec) {
101                return false; // no description from the csv
102        }
103
104        @Override
105        public void addPostDescriptionSection(TooltipMakerAPI tooltip, HullSize hullSize, ShipAPI ship, float width, boolean isForModSpec) {
106                float pad = 3f;
107                float opad = 10f;
108                Color h = Misc.getHighlightColor();
109                Color bad = Misc.getNegativeHighlightColor();
110                
111                tooltip.addPara("A ship with high resolution sensors increases the fleet's sensor range by %s/%s/%s/%s," +
112                                " depending on hull size. " +
113                                "Each additional ship with high resolution sensors provides diminishing returns. " +
114                                "The higher the highest sensor range increase from a single ship in the fleet, the later diminishing returns kick in.", 
115                                opad, h,
116                                "" + ((Float) mag.get(HullSize.FRIGATE)).intValue(),
117                                "" + ((Float) mag.get(HullSize.DESTROYER)).intValue(),
118                                "" + ((Float) mag.get(HullSize.CRUISER)).intValue(),
119                                "" + ((Float) mag.get(HullSize.CAPITAL_SHIP)).intValue()
120                                );
121                
122                if (isForModSpec || ship == null) return;
123                if (Global.getSettings().getCurrentState() == GameState.TITLE) return;
124                
125                CampaignFleetAPI fleet = Global.getSector().getPlayerFleet();
126                float fleetMod = getAdjustedHRSModifier(fleet, null, 0f);
127                float currShipMod = (Float) mag.get(hullSize);
128                
129                float fleetModWithOneMore = getAdjustedHRSModifier(fleet, null, currShipMod);
130                float fleetModWithoutThisShip = getAdjustedHRSModifier(fleet, ship.getFleetMemberId(), 0f);
131                
132                tooltip.addPara("The total sensor strength increase for your fleet is %s.", opad, h,
133                                "" + (int)Math.round(fleetMod));
134                
135                float cr = ship.getCurrentCR();
136                for (FleetMemberAPI member : Global.getSector().getPlayerFleet().getFleetData().getMembersListCopy()) {
137                        if (member.getId().equals(ship.getFleetMemberId())) {
138                                cr = member.getRepairTracker().getCR();
139                        }
140                }
141                
142                if (cr < MIN_CR) {
143                        LabelAPI label = tooltip.addPara("This ship's combat readiness is below %s " +
144                                        "and its high resolution sensors can not be utilized. Bringing this ship into readiness " +
145                                        "would increase the fleetwide bonus to %s.",
146                                        opad, h,
147                                        "" + (int) Math.round(MIN_CR * 100f) + "%",
148                                        "" + (int)Math.round(fleetModWithOneMore));
149                        label.setHighlightColors(bad, h);
150                        label.setHighlight("" + (int) Math.round(MIN_CR * 100f) + "%", "" + (int)Math.round(fleetModWithOneMore));
151                } else {
152                        if (fleetMod > currShipMod) {
153                                tooltip.addPara("Removing this ship would decrease it to %s. Adding another ship of the same type " +
154                                                "would increase it to %s.", opad, h,
155                                                "" + (int)Math.round(fleetModWithoutThisShip),
156                                                "" + (int)Math.round(fleetModWithOneMore));
157                        } else {
158                                tooltip.addPara("Adding another ship of the same type " +
159                                                "would increase it to %s.", opad, h,
160                                                "" + (int)Math.round(fleetModWithOneMore));
161                        }
162                }
163        }
164
165        public static float getAdjustedHRSModifier(CampaignFleetAPI fleet, String skipId, float add) {
166                float max = 0f;
167                float total = 0f;
168                for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) {
169                        if (member.isMothballed()) continue;
170                        if (member.getRepairTracker().getCR() < MIN_CR) continue;
171                        
172                        if (member.getId().equals(skipId)) { 
173                                continue;
174                        }
175                        float v = member.getStats().getDynamic().getMod(Stats.HRS_SENSOR_RANGE_MOD).computeEffective(0f);
176                        if (v <= 0) continue;
177                        
178                        if (v > max) max = v;
179                        total += v;
180                }
181                if (add > max) max = add;
182                total += add;
183                
184                if (max <= 0) return 0f;
185                float units = total / max;
186                if (units <= 1) return max;
187                float mult = Misc.logOfBase(2.5f, units) + 1f;
188                float result = total * mult / units;
189                if (result <= 0) {
190                        result = 0;
191                } else {
192                        result = Math.round(result * 100f) / 100f;
193                        result = Math.max(result, 1f);
194                }
195                return result;
196        }
197
198
199}