001package com.fs.starfarer.api.characters; 002 003import java.awt.Color; 004import java.util.ArrayList; 005import java.util.LinkedHashMap; 006import java.util.List; 007import java.util.Map; 008 009import com.fs.starfarer.api.Global; 010import com.fs.starfarer.api.combat.ShipVariantAPI; 011import com.fs.starfarer.api.fleet.FleetMemberAPI; 012import com.fs.starfarer.api.impl.campaign.plog.PlaythroughLog; 013import com.fs.starfarer.api.impl.campaign.plog.SModRecord; 014import com.fs.starfarer.api.loading.HullModSpecAPI; 015import com.fs.starfarer.api.loading.VariantSource; 016import com.fs.starfarer.api.ui.Alignment; 017import com.fs.starfarer.api.ui.ButtonAPI; 018import com.fs.starfarer.api.ui.TooltipMakerAPI; 019import com.fs.starfarer.api.ui.UIComponentAPI; 020import com.fs.starfarer.api.util.Misc; 021 022public class SkillsChangeRemoveSmodsEffect extends BaseSkillsChangeEffect { 023 024 public static class SmodRemovalEffectData { 025 FleetMemberAPI member; 026 List<SModRecord> records = new ArrayList<SModRecord>(); 027 int maxBefore; 028 int maxAfter; 029 int numSmods; 030 int remove; 031 boolean offerChoice = false; 032 List<String> removeList = new ArrayList<String>(); 033 034 List<ButtonAPI> buttons = new ArrayList<ButtonAPI>(); 035 } 036 037 public static class SmodDataMap { 038 Map<FleetMemberAPI, SmodRemovalEffectData> map = new LinkedHashMap<FleetMemberAPI, SmodRemovalEffectData>(); 039 } 040 public void setMap(SmodDataMap map, Map<String, Object> dataMap) { 041 String key = getClass().getSimpleName(); 042 dataMap.put(key, map); 043 } 044 public SmodDataMap getMap(Map<String, Object> dataMap) { 045 String key = getClass().getSimpleName(); 046 SmodDataMap map = (SmodDataMap)dataMap.get(key); 047 if (map == null) { 048 map = new SmodDataMap(); 049 dataMap.put(key, map); 050 } 051 return map; 052 } 053 054 public SmodDataMap getEffects(MutableCharacterStatsAPI from, MutableCharacterStatsAPI to) { 055 SmodDataMap result = new SmodDataMap(); 056 057 058 for (SModRecord record : PlaythroughLog.getInstance().getSModsInstalled()) { 059 FleetMemberAPI member = record.getMember(); 060 if (member == null) continue; 061 if (record.getSMods().isEmpty()) continue; 062 String modId = record.getSMods().get(0); 063 if (!member.getVariant().getSMods().contains(modId)) continue; 064 if (!member.getVariant().getHullMods().contains(modId)) continue; 065 066 SmodRemovalEffectData data = result.map.get(member); 067 if (data == null) { 068 data = new SmodRemovalEffectData(); 069 data.member = member; 070 data.numSmods = member.getVariant().getSMods().size(); 071 data.maxBefore = Misc.getMaxPermanentMods(member, from); 072 data.maxAfter = Misc.getMaxPermanentMods(member, to); 073 result.map.put(member, data); 074 } 075 data.records.add(record); 076 } 077 078 for (FleetMemberAPI member : new ArrayList<FleetMemberAPI>(result.map.keySet())) { 079 SmodRemovalEffectData data = result.map.get(member); 080 if (data.maxBefore <= data.maxAfter || data.records.isEmpty() || 081 data.numSmods <= data.maxAfter) { 082 result.map.remove(member); 083 } else { 084 data.remove = Math.min(data.numSmods - data.maxAfter, data.records.size()); 085 data.offerChoice = data.remove <= 1 && 086 Global.getSector().getPlayerFleet().getFleetData().getMembersListCopy().contains(data.member); 087 if (!data.offerChoice) { 088 List<SModRecord> copy = new ArrayList<SModRecord>(data.records); 089 for (int i = 0; i < data.remove; i++) { 090 int minCost = 10000; 091 SModRecord minCostMod = null; 092 for (SModRecord record : data.records) { 093 HullModSpecAPI mod = Global.getSettings().getHullModSpec(record.getSMods().get(0)); 094 int cost = mod.getCostFor(member.getHullSpec().getHullSize()); 095 if (cost < minCost) { 096 minCostMod = record; 097 minCost = cost; 098 } 099 } 100 if (minCostMod != null) { 101 data.removeList.add(minCostMod.getSMods().get(0)); 102 copy.remove(minCostMod); 103 } 104 } 105 } 106 } 107 } 108 109 return result; 110 } 111 112 113 @Override 114 public boolean hasEffects(MutableCharacterStatsAPI from, MutableCharacterStatsAPI to) { 115 return !getEffects(from, to).map.isEmpty(); 116 } 117 118 @Override 119 public void printEffects(MutableCharacterStatsAPI from, MutableCharacterStatsAPI to, TooltipMakerAPI info, Map<String, Object> dataMap) { 120 super.prepare(); 121 122 SmodDataMap map = getEffects(from, to); 123 setMap(map, dataMap); 124 125 float pad = 3f; 126 float opad = 10f; 127 Color h = Misc.getHighlightColor(); 128 129 float initPad = 15f; 130 info.addSectionHeading("S-mods", base, dark, Alignment.MID, initPad); 131 initPad = opad; 132// for (SmodRemovalEffectData data : map.map.values()) { 133// if (!data.offerChoice) { 134 info.addPara("Ships that you've built s-mods into that now have more than their maximum" 135 + " number of s-mods will have the cheapest s-mods removed.", initPad, 136 Misc.getNegativeHighlightColor(), 137 "cheapest s-mods removed"); 138 initPad = 15f; 139 info.addPara("If only one s-mod is being removed, and the ship is currently in your fleet, " 140 + "you can select which s-mod to remove. S-mods you did not build into a ship will not be removed, even if the ship is over the limit.", opad); 141// break; 142// } 143// } 144 145 for (SmodRemovalEffectData data : map.map.values()) { 146 final FleetMemberAPI member = data.member; 147 148 if (data.offerChoice) { 149 String str = "The " + member.getShipName() + 150 " (" + member.getHullSpec().getHullNameWithDashClass() + "), will lose its built-in..."; 151 info.addPara(str, initPad); 152 153 float bw = 470; 154 float bh = 25; 155 float indent = 40f; 156 UIComponentAPI prev = null; 157 int minCost = 10000; 158 ButtonAPI minCostButton = null; 159 for (SModRecord record : data.records) { 160 HullModSpecAPI mod = Global.getSettings().getHullModSpec(record.getSMods().get(0)); 161 float p = opad; 162 if (prev != null) p = pad; 163 int cost = mod.getCostFor(member.getHullSpec().getHullSize()); 164 ButtonAPI b = info.addAreaCheckbox( 165 mod.getDisplayName() + " (" + cost + " OP)", new Object(), base, dark, bright, bw, bh, p, true); 166 data.buttons.add(b); 167 168 if (prev == null) { 169 b.getPosition().setXAlignOffset(indent); 170 } 171 prev = b; 172 if (cost < minCost) { 173 minCostButton = b; 174 minCost = cost; 175 } 176 } 177 if (minCostButton != null) { 178 minCostButton.setChecked(true); 179 } 180 181 info.addSpacer(0).getPosition().setXAlignOffset(-indent); 182 } 183 } 184 } 185 186 @Override 187 public void infoButtonPressed(ButtonAPI button, Object param, Map<String, Object> dataMap) { 188 SmodDataMap map = getMap(dataMap); 189 190 for (SmodRemovalEffectData data : map.map.values()) { 191 boolean found = false; 192 for (ButtonAPI b : data.buttons) { 193 if (b == button) { 194 found = true; 195 break; 196 } 197 } 198 if (found) { 199 for (ButtonAPI b : data.buttons) { 200 if (b == button) { 201 b.setChecked(true); 202 } else { 203 b.setChecked(false); 204 } 205 } 206 break; 207 } 208 } 209 } 210 211 @Override 212 public void applyEffects(MutableCharacterStatsAPI from, MutableCharacterStatsAPI to, Map<String, Object> dataMap) { 213 SmodDataMap map = getMap(dataMap); 214 215 for (SmodRemovalEffectData data : map.map.values()) { 216 ShipVariantAPI variant = data.member.getVariant(); 217 variant = variant.clone(); 218 variant.setSource(VariantSource.REFIT); 219 220 if (data.offerChoice) { 221 int index = 0; 222 for (ButtonAPI b : data.buttons) { 223 if (b.isChecked()) { 224 SModRecord record = data.records.get(index); 225 data.removeList.add(record.getSMods().get(0)); 226 } 227 index++; 228 } 229 } 230 for (String modId : data.removeList) { 231 variant.removePermaMod(modId); 232 } 233 data.member.setVariant(variant, false, false); 234 } 235 } 236 237} 238 239 240 241 242 243 244