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}