001package com.fs.starfarer.api.campaign.impl.items;
002
003import java.util.ArrayList;
004import java.util.Collections;
005import java.util.Comparator;
006import java.util.Iterator;
007import java.util.LinkedHashSet;
008import java.util.List;
009import java.util.Set;
010
011import java.awt.Color;
012
013import com.fs.starfarer.api.Global;
014import com.fs.starfarer.api.campaign.CargoStackAPI;
015import com.fs.starfarer.api.campaign.CargoTransferHandlerAPI;
016import com.fs.starfarer.api.campaign.FactionAPI;
017import com.fs.starfarer.api.campaign.econ.MarketAPI;
018import com.fs.starfarer.api.campaign.econ.SubmarketAPI;
019import com.fs.starfarer.api.combat.ShipHullSpecAPI;
020import com.fs.starfarer.api.graphics.SpriteAPI;
021import com.fs.starfarer.api.loading.FighterWingSpecAPI;
022import com.fs.starfarer.api.loading.WeaponSpecAPI;
023import com.fs.starfarer.api.ui.TooltipMakerAPI;
024import com.fs.starfarer.api.util.Misc;
025
026public class MultiBlueprintItemPlugin extends BaseSpecialItemPlugin implements BlueprintProviderItem {
027
028        
029        protected Set<String> tags = new LinkedHashSet<String>();
030        @Override
031        public void init(CargoStackAPI stack) {
032                super.init(stack);
033                
034                String param = spec.getParams();
035                if (!param.isEmpty()) {
036                        for (String tag : param.split(",")) {
037                                tag = tag.trim();
038                                if (tag.isEmpty()) continue;
039                                tags.add(tag);
040                        }
041                }
042        }
043        
044        transient protected List<String> cachedFighters = null;
045        transient protected List<String> cachedShips = null;
046        transient protected List<String> cachedWeapons= null;
047        
048        public List<String> getProvidedFighters() {
049                if (cachedFighters == null) {
050                        cachedFighters = getWingIds(tags);
051                }
052                return cachedFighters;
053        }
054
055        public List<String> getProvidedShips() {
056                if (cachedShips == null) {
057                        cachedShips = getShipIds(tags);
058                }
059                return cachedShips;
060        }
061
062        public List<String> getProvidedWeapons() {
063                if (cachedWeapons == null) {
064                        cachedWeapons = getWeaponIds(tags);
065                }
066                return cachedWeapons;
067        }
068        public List<String> getProvidedIndustries() {
069                return null;
070        }
071        
072        @Override
073        public void render(float x, float y, float w, float h, float alphaMult,
074                                           float glowMult, SpecialItemRendererAPI renderer) {
075                
076                SpriteAPI sprite = Global.getSettings().getSprite("blueprint_packages", getId(), true);
077                if (sprite.getTextureId() == 0) return; // no texture for a "holo", so no custom rendering
078                
079                
080                float cx = x + w/2f;
081                float cy = y + h/2f;
082                
083                w = 40;
084                h = 40;
085                
086                float p = 1;
087                float blX = cx - 12f - p;
088                float blY = cy - 22f - p;
089                float tlX = cx - 26f - p;
090                float tlY = cy + 19f + p;
091                float trX = cx + 20f + p;
092                float trY = cy + 24f + p;
093                float brX = cx + 34f + p;
094                float brY = cy - 9f - p;
095                
096                List<String> ships = getProvidedShips();
097                List<String> weapons = getProvidedWeapons();
098                List<String> fighters = getProvidedFighters();
099                boolean known = areAllKnown(ships, weapons, fighters);
100                
101                float mult = 1f;
102                
103                sprite.setAlphaMult(alphaMult * mult);
104                sprite.setNormalBlend();
105                sprite.renderWithCorners(blX, blY, tlX, tlY, trX, trY, brX, brY);
106                
107                if (glowMult > 0) {
108                        sprite.setAlphaMult(alphaMult * glowMult * 0.5f * mult);
109                        sprite.setAdditiveBlend();
110                        sprite.renderWithCorners(blX, blY, tlX, tlY, trX, trY, brX, brY);
111                }
112                
113                if (known) {
114                        renderer.renderBGWithCorners(Color.black, blX, blY, tlX, tlY, trX, trY, brX, brY, 
115                                         alphaMult * 0.5f, 0f, false);
116                }
117                
118                renderer.renderScanlinesWithCorners(blX, blY, tlX, tlY, trX, trY, brX, brY, alphaMult, false);
119        }
120
121        @Override
122        public int getPrice(MarketAPI market, SubmarketAPI submarket) {
123                return super.getPrice(market, submarket);
124        }
125        
126        @Override
127        public String getName() {
128                return super.getName();
129        }
130
131        @Override
132        public String getDesignType() {
133                return null;
134        }
135        
136        @Override
137        public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, CargoTransferHandlerAPI transferHandler, Object stackSource) {
138                super.createTooltip(tooltip, expanded, transferHandler, stackSource);
139                
140                float pad = 3f;
141                float opad = 10f;
142                float small = 5f;
143                Color h = Misc.getHighlightColor();
144                Color g = Misc.getGrayColor();
145                Color b = Misc.getButtonTextColor();
146                b = Misc.getPositiveHighlightColor();
147                
148                List<String> ships = getProvidedShips();
149                List<String> weapons = getProvidedWeapons();
150                List<String> fighters = getProvidedFighters();
151                
152                float maxTotal = 21;
153                int minPer = 3;
154                
155                float shipWeight = 0f;
156                float weaponWeight = 0f;
157                float fighterWeight = 0f;
158                
159                FactionAPI pf = Global.getSector().getPlayerFaction();
160                
161                float knownWeight = 0.25f;
162                for (String id : ships) {
163                        if (pf.knowsShip(id)) {
164                                shipWeight += knownWeight;
165                        } else {
166                                shipWeight += 1f;
167                        }
168                }
169                for (String id : weapons) {
170                        if (pf.knowsWeapon(id)) {
171                                weaponWeight += knownWeight;
172                        } else {
173                                weaponWeight += 1f;
174                        }
175                }
176                for (String id : fighters) {
177                        if (pf.knowsFighter(id)) {
178                                fighterWeight += knownWeight;
179                        } else {
180                                fighterWeight += 1f;
181                        }
182                }
183                
184                float totalWeight = shipWeight + weaponWeight + fighterWeight;
185                if (totalWeight < knownWeight) totalWeight = knownWeight;
186                
187                int maxShips = (int) Math.max(minPer, (shipWeight / totalWeight) * maxTotal);
188                int maxWeapons = (int) Math.max(minPer, (weaponWeight / totalWeight) * maxTotal);
189                int maxFighters = (int) Math.max(minPer, (fighterWeight / totalWeight) * maxTotal);
190                
191                
192                if (!ships.isEmpty()) {
193                        addShipList(tooltip, "Ship hulls:", ships, maxShips, opad);
194                }
195                if (!weapons.isEmpty()) {
196                        addWeaponList(tooltip, "Weapons:", weapons, maxWeapons, opad);
197                }
198                if (!fighters.isEmpty()) {
199                        addFighterList(tooltip, "Fighters:", fighters, maxFighters, opad);
200                }
201                
202                
203
204                addCostLabel(tooltip, opad, transferHandler, stackSource);
205                
206                if (!Global.CODEX_TOOLTIP_MODE) {
207                        boolean known = areAllKnown(ships, weapons, fighters);
208                        if (known) {
209                                tooltip.addPara("All blueprints in package already known", g, opad);
210                        } else {
211                                tooltip.addPara("Right-click to learn", b, opad);
212                        }
213                }
214        }
215        
216        protected boolean areAllKnown(List<String> ships, List<String> weapons, List<String> fighters) {
217                
218                for (String hullId : ships) {
219                        if (!Global.getSector().getPlayerFaction().knowsShip(hullId)) {
220                                return false;
221                        }
222                }
223                for (String weaponId : weapons) {
224                        if (!Global.getSector().getPlayerFaction().knowsWeapon(weaponId)) {
225                                return false;
226                        }
227                }
228                for (String wingId : fighters) {
229                        if (!Global.getSector().getPlayerFaction().knowsFighter(wingId)) {
230                                return false;
231                        }
232                }
233                return true;
234        }
235
236        @Override
237        public float getTooltipWidth() {
238                return super.getTooltipWidth();
239        }
240        
241        @Override
242        public boolean isTooltipExpandable() {
243                return false;
244        }
245        
246        @Override
247        public boolean hasRightClickAction() {
248                return true;
249        }
250
251        @Override
252        public boolean shouldRemoveOnRightClickAction() {
253                List<String> ships = getProvidedShips();
254                List<String> weapons = getProvidedWeapons();
255                List<String> fighters = getProvidedFighters();
256                return !areAllKnown(ships, weapons, fighters);
257        }
258
259        @Override
260        public void performRightClickAction() {
261                List<String> ships = getProvidedShips();
262                List<String> weapons = getProvidedWeapons();
263                List<String> fighters = getProvidedFighters();
264                
265                if (areAllKnown(ships, weapons, fighters)) {
266                        Global.getSector().getCampaignUI().getMessageDisplay().addMessage(
267                                        "All blueprints in package already known");//,
268                } else {
269                        Global.getSoundPlayer().playUISound("ui_acquired_blueprint", 1, 1);
270                        FactionAPI pf = Global.getSector().getPlayerFaction();
271                        int sCount = 0;
272                        int wCount = 0;
273                        int fCount = 0;
274                        for (String id : ships) {
275                                if (!pf.knowsShip(id)) sCount++;
276                                pf.addKnownShip(id, true);
277                        }
278                        for (String id : weapons) {
279                                if (!pf.knowsWeapon(id)) wCount++;
280                                pf.addKnownWeapon(id, true);
281                        }
282                        for (String id : fighters) {
283                                if (!pf.knowsFighter(id)) fCount++;
284                                pf.addKnownFighter(id, true);
285                        }
286                        
287                        if (sCount > 0) {
288                                Global.getSector().getCampaignUI().getMessageDisplay().addMessage(
289                                                "Acquired " + sCount + " ship blueprints", Misc.getTooltipTitleAndLightHighlightColor(),
290                                                "" + sCount, Misc.getHighlightColor());
291                        }
292                        if (wCount > 0) {
293                                Global.getSector().getCampaignUI().getMessageDisplay().addMessage(
294                                                "Acquired " + wCount + " weapon blueprints", Misc.getTooltipTitleAndLightHighlightColor(),
295                                                "" + wCount, Misc.getHighlightColor());
296                        }
297                        if (fCount > 0) {
298                                Global.getSector().getCampaignUI().getMessageDisplay().addMessage(
299                                                "Acquired " + fCount + " fighter blueprints", Misc.getTooltipTitleAndLightHighlightColor(),
300                                                "" + fCount, Misc.getHighlightColor());
301                        }
302
303                }
304        }
305
306        public static List<String> getWeaponIds(Set<String> tags) {
307                List<WeaponSpecAPI> specs = Global.getSettings().getAllWeaponSpecs();
308                
309                Iterator<WeaponSpecAPI> iter = specs.iterator();
310//              while (iter.hasNext()) {
311//                      WeaponSpecAPI curr = iter.next();
312//                      if (curr.getAIHints().contains(AIHints.SYSTEM)) {
313//                              iter.remove();
314//                      }
315//              }
316                
317                if (!tags.isEmpty()) {
318                        iter = specs.iterator();
319                        while (iter.hasNext()) {
320                                WeaponSpecAPI curr = iter.next();
321                                for (String tag : tags) {
322                                        boolean not = tag.startsWith("!");
323                                        tag = not ? tag.substring(1) : tag;
324                                        boolean has = curr.hasTag(tag);
325                                        if (not == has) {
326                                                iter.remove();
327                                                break;
328                                        }
329                                }
330                        }
331                }
332                
333                Collections.sort(specs, new Comparator<WeaponSpecAPI>() {
334                        public int compare(WeaponSpecAPI o1, WeaponSpecAPI o2) {
335                                return o2.getSize().ordinal() - o1.getSize().ordinal();
336                        }
337                });
338                
339                List<String> result = new ArrayList<String>();
340                for (WeaponSpecAPI spec : specs) {
341                        result.add(spec.getWeaponId());
342                }
343                return result;
344        }
345
346        
347        public static List<String> getShipIds(Set<String> tags) {
348                List<ShipHullSpecAPI> specs = Global.getSettings().getAllShipHullSpecs();
349                
350                Iterator<ShipHullSpecAPI> iter = specs.iterator();
351                
352                if (!tags.isEmpty()) {
353                        iter = specs.iterator();
354                        while (iter.hasNext()) {
355                                ShipHullSpecAPI curr = iter.next();
356//                              if (tags.contains("pirate_bp") && curr.getHullId().equals("mule_d_pirates")) {
357//                                      System.out.println(curr.getHullId());
358//                              }
359//                              if (!curr.isBaseHull()) {
360//                                      iter.remove();
361//                                      continue;
362//                              }
363                                
364//                              if (curr.hasTag("rare_bp")) {
365//                                      System.out.println("\"" + curr.getHullId() + "\",");
366//                              }
367                                
368                                for (String tag : tags) {
369                                        boolean not = tag.startsWith("!");
370                                        tag = not ? tag.substring(1) : tag;
371                                        boolean has = curr.hasTag(tag);
372                                        if (not == has) {
373                                                iter.remove();
374                                                break;
375                                        }
376                                }
377                        }
378                } else {
379                        specs.clear();
380                }
381                
382                Collections.sort(specs, new Comparator<ShipHullSpecAPI>() {
383                        public int compare(ShipHullSpecAPI o1, ShipHullSpecAPI o2) {
384                                return o2.getHullSize().ordinal() - o1.getHullSize().ordinal();
385                        }
386                });
387                
388                List<String> result = new ArrayList<String>();
389                for (ShipHullSpecAPI spec : specs) {
390                        result.add(spec.getHullId());
391                }
392                return result;
393        }
394        
395        
396        public static List<String> getWingIds(Set<String> tags) {
397                List<FighterWingSpecAPI> specs = Global.getSettings().getAllFighterWingSpecs();
398                
399                Iterator<FighterWingSpecAPI> iter = specs.iterator();
400                
401                if (!tags.isEmpty()) {
402                        iter = specs.iterator();
403                        while (iter.hasNext()) {
404                                FighterWingSpecAPI curr = iter.next();
405                                for (String tag : tags) {
406                                        boolean not = tag.startsWith("!");
407                                        tag = not ? tag.substring(1) : tag;
408                                        boolean has = curr.hasTag(tag);
409                                        if (not == has) {
410                                                iter.remove();
411                                                break;
412                                        }
413                                }
414                        }
415                }
416                
417                List<String> result = new ArrayList<String>();
418                for (FighterWingSpecAPI spec : specs) {
419                        result.add(spec.getId());
420                }
421                return result;
422        }
423
424}
425
426
427
428
429