001package com.fs.starfarer.api.impl.campaign.abilities;
002
003import java.util.ArrayList;
004import java.util.List;
005
006import java.awt.Color;
007
008import com.fs.starfarer.api.Global;
009import com.fs.starfarer.api.Script;
010import com.fs.starfarer.api.campaign.CampaignFleetAPI;
011import com.fs.starfarer.api.campaign.FactionAPI;
012import com.fs.starfarer.api.campaign.rules.MemoryAPI;
013import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActions;
014import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
015import com.fs.starfarer.api.ui.LabelAPI;
016import com.fs.starfarer.api.ui.TooltipMakerAPI;
017import com.fs.starfarer.api.util.Misc;
018
019public class TransponderAbility extends BaseToggleAbility {
020
021        public static final float DETECTABILITY_MULT = 1f;
022        public static final float DETECTABILITY_FLAT = 1000f;
023        
024//      public String getSpriteName() {
025//              return Global.getSettings().getSpriteName("abilities", Abilities.TRANSPONDER);
026//      }
027        
028        
029        @Override
030        protected String getActivationText() {
031                return "Transponder on";
032        }
033
034
035
036        @Override
037        protected String getDeactivationText() {
038                //return "Transponder off";
039                // currently, doesn't work well - if something like "go dark" cancels transponder,
040                // then you get multiple overlapping messages, "Going dark" + "Transponder off"
041                return null;
042        }
043
044
045        @Override
046        protected void activateImpl() {
047                if (entity.isPlayerFleet()) {
048                        List<FactionAPI> factions = getFactionsThatWouldBecomeHostile();
049                        if (!factions.isEmpty()) {
050                                Global.getSector().getCampaignUI().addMessage("Your identity is revealed and linked to your recent hostile actions!");
051                                for (FactionAPI faction : factions) {
052                                        Global.getSector().adjustPlayerReputation(RepActions.COMBAT_NORMAL, faction.getId());
053                                }
054                        }
055                }
056                
057                entity.setTransponderOn(true);
058                entity.getMemoryWithoutUpdate().set(MemFlags.JUST_TOGGLED_TRANSPONDER, true, 0.1f);
059                
060//              AbilityPlugin goDark = entity.getAbility(Abilities.GO_DARK);
061//              if (goDark != null && goDark.isActive()) {
062//                      goDark.deactivate();
063//              }
064        }
065
066        @Override
067        protected void applyEffect(float amount, float level) {
068                CampaignFleetAPI fleet = getFleet();
069                if (fleet == null) return;
070                
071                if (level > 0) level = 1;
072                fleet.getStats().getDetectedRangeMod().modifyMult(getModId(), 1f + (DETECTABILITY_MULT - 1f) * level, "Transponder on");
073                fleet.getStats().getDetectedRangeMod().modifyFlat(getModId(), DETECTABILITY_FLAT * level, "Transponder on");
074                
075                if (level <= 0) {
076                        cleanupImpl();
077                }
078        }
079        
080        
081        @Override
082        public void deactivate() {
083                super.deactivate();
084                if (entity.isTransponderOn()) {
085                        entity.setTransponderOn(false); // failsafe in case deactivation failed to actually deactivate transponder
086                        entity.getMemoryWithoutUpdate().set(MemFlags.JUST_TOGGLED_TRANSPONDER, true, 0.1f);
087                }
088        }
089
090
091
092        @Override
093        protected void deactivateImpl() {
094                entity.setTransponderOn(false);
095                entity.getMemoryWithoutUpdate().set(MemFlags.JUST_TOGGLED_TRANSPONDER, true, 0.1f);
096                //cleanupImpl();
097        }
098        
099
100//      @Override
101//      public float getActivationDays() {
102//              return 0.0f;
103//      }
104//
105//      @Override
106//      public float getDeactivationDays() {
107//              return 0.1f;
108//      }
109
110        @Override
111        protected void cleanupImpl() {
112                CampaignFleetAPI fleet = getFleet();
113                if (fleet == null) return;
114                
115                fleet.getStats().getDetectedRangeMod().unmodify(getModId());
116        }
117        
118        @Override
119        public void createTooltip(TooltipMakerAPI tooltip, boolean expanded) {
120                Color gray = Misc.getGrayColor();
121                Color highlight = Misc.getHighlightColor();
122                Color red = Misc.getNegativeHighlightColor();
123                
124                String status = " (off)";
125                if (entity.isTransponderOn()) {
126                        status = " (on)";
127                }
128                
129                if (!Global.CODEX_TOOLTIP_MODE) {
130                        LabelAPI title = tooltip.addTitle(spec.getName() + status);
131                        title.highlightLast(status);
132                        title.setHighlightColor(gray);
133                } else {
134                        tooltip.addSpacer(-10f);
135                }
136
137                float pad = 10f;
138                tooltip.addPara("Transponders transmit identifying information to all fleets within range.", pad);
139                
140                if (!Global.CODEX_TOOLTIP_MODE) {
141                        List<FactionAPI> factions = getFactionsThatWouldBecomeHostile();
142                        if (!factions.isEmpty()) {
143                                String text = "Turning the transponder on now would reveal your hostile actions to";
144                                boolean first = true;
145                                boolean last = false;
146                                for (FactionAPI faction : factions) {
147                                        last = factions.indexOf(faction) == factions.size() - 1;
148                                        if (first || !last) {
149                                                text += " " + faction.getDisplayNameWithArticle() + ",";
150                                        } else {
151                                                text += " and " + faction.getDisplayNameWithArticle() + ",";
152                                        }
153                                }
154                                text = text.substring(0, text.length() - 1) + ".";
155                                tooltip.addPara(text, red, pad);
156                        }
157                }
158                
159                tooltip.addPara("When the transponder is on, your fleet can be detected at longer range and " +
160                                "full information on its composition is available at maximum range.", pad);
161                tooltip.addPara("Transponder status also affects the reputation changes from combat and trade. " +
162                                "With it turned off, you might be able to trade with otherwise inhospitable factions.", pad);
163                tooltip.addPara("In most places, running with the transponder off will attract the attention of nearby patrols, " +
164                                "although several factions and certain free ports allow it. " +
165                                "Having the transponder off does not grant perfect anonymity.", pad);
166                
167                
168                //tooltip.addPara("Disables \"Go Dark\" when activated.", pad);
169                addIncompatibleToTooltip(tooltip, expanded);
170        }
171        
172        public String getFactionList(List<FactionAPI> factions) {
173                String text = "";
174                boolean first = true;
175                boolean last = false;
176                for (FactionAPI faction : factions) {
177                        last = factions.indexOf(faction) == factions.size() - 1;
178                        if (first || !last) {
179                                text += " " + faction.getDisplayNameLongWithArticle() + ",";
180                        } else {
181                                text += " and " + faction.getDisplayNameLongWithArticle() + ",";
182                        }
183                }
184                text = text.substring(0, text.length() - 1) + "";
185                return text.trim();
186        }
187        
188
189        public boolean hasTooltip() {
190                return true;
191        }
192        
193        
194        public List<FactionAPI> getFactionsThatWouldBecomeHostile() {
195                return getFactionsThatWouldBecomeHostile(getFleet());
196        }
197        public static List<FactionAPI> getFactionsThatWouldBecomeHostile(CampaignFleetAPI fleet) {
198                List<FactionAPI> result = new ArrayList<FactionAPI>();
199                //CampaignFleetAPI fleet = getFleet();
200                if (fleet == null) return result;
201                if (fleet.getContainingLocation() == null) return result;
202                if (fleet.isTransponderOn()) return result;
203                
204                List<CampaignFleetAPI> fleets = fleet.getContainingLocation().getFleets();
205                for (CampaignFleetAPI other : fleets) {
206                        if (other.getFleetData().getNumMembers() <= 0) continue;
207                        
208//                      VisibilityLevel level = fleet.getVisibilityLevelTo(other);
209//                      if (level == VisibilityLevel.NONE) continue;
210
211                        float dist = Misc.getDistance(fleet.getLocation(), other.getLocation());
212                        fleet.setTransponderOn(true);
213                        float detectRange = (other.getMaxSensorRangeToDetect(fleet) + DETECTABILITY_FLAT) * DETECTABILITY_MULT * 1.25f;
214                        fleet.setTransponderOn(false);
215                        
216                        if (dist > detectRange) continue;
217                        
218                        MemoryAPI mem = other.getMemoryWithoutUpdate();
219                        
220                        if (mem.getBoolean(MemFlags.MEMORY_KEY_LOW_REP_IMPACT)) continue;
221                        
222                        if (!result.contains(other.getFaction()) && 
223                                        mem.getBoolean(MemFlags.MEMORY_KEY_MAKE_HOSTILE_WHILE_TOFF) &&
224                                        !other.getFaction().isHostileTo(fleet.getFaction())) {
225                                result.add(other.getFaction());
226                        }
227                }
228                return result;
229        }
230
231        private transient boolean showAlarm = false;
232        @Override
233        public void advance(float amount) {
234                if (!Global.getSector().isPaused()) {
235                        super.advance(amount);
236                }
237                
238                CampaignFleetAPI fleet = getFleet();
239                if (fleet == null || !fleet.isPlayerFleet()) return;
240                sinceWarning += amount;
241                
242                List<FactionAPI> factions = getFactionsThatWouldBecomeHostile();
243                if (factions.isEmpty()) {
244                        showAlarm = false;
245                } else {
246                        showAlarm = true;
247                }
248        }
249        
250        @Override
251        public boolean runWhilePaused() {
252                return getFleet() != null && getFleet().isPlayerFleet();
253        }
254
255
256        @Override
257        public boolean showProgressIndicator() {
258                return showAlarm;
259        }
260
261        @Override
262        public float getProgressFraction() {
263                return 1f;
264        }
265
266
267        @Override
268        public Color getProgressColor() {
269                Color color = Misc.getNegativeHighlightColor();
270                return Misc.scaleAlpha(color, Global.getSector().getCampaignUI().getSharedFader().getBrightness());
271        }
272
273        
274        public static final float CONFIRM_DURATION = 5f;
275
276
277        @Override
278        protected Object readResolve() {
279                super.readResolve();
280                sinceWarning = 1000f;
281                return this;
282        }
283        
284        transient float sinceWarning = 1000f;
285        
286        @Override
287        public void pressButton() {
288                if (getFleet().isPlayerFleet()) {
289                        if (sinceWarning < CONFIRM_DURATION) {
290                                if (entity.isPlayerFleet()) {
291                                        List<FactionAPI> factions = getFactionsThatWouldBecomeHostile();
292                                        if (!factions.isEmpty()) {
293                                                String list = getFactionList(factions);
294                                                String text = "Turning the transponder on will reveal your identity and make " + list + " hostile.\n\n" +
295                                                                "Are you sure you want to do this?";
296                                                Global.getSector().getCampaignUI().showConfirmDialog(text, "Confirm", "Cancel", 
297                                                                new Script() {
298                                                                        public void run() {
299                                                                                TransponderAbility.super.pressButton();
300                                                                                Global.getSector().getCampaignUI().getMessageDisplay().removeMessage(getDeactivationMessage());
301                                                                                Global.getSector().getCampaignUI().getMessageDisplay().removeMessage(getActivationMessage());
302                                                                                sinceWarning = 1000f;
303                                                                        }
304                                                                }, null);
305                                        } else {
306                                                super.pressButton();
307                                                Global.getSector().getCampaignUI().getMessageDisplay().removeMessage(getDeactivationMessage());
308                                                Global.getSector().getCampaignUI().getMessageDisplay().removeMessage(getActivationMessage());
309                                                sinceWarning = 1000f;
310                                        }
311                                } else {
312                                        super.pressButton();
313                                        Global.getSector().getCampaignUI().getMessageDisplay().removeMessage(getDeactivationMessage());
314                                        Global.getSector().getCampaignUI().getMessageDisplay().removeMessage(getActivationMessage());
315                                        sinceWarning = 1000f;
316                                }
317                        } else {
318                                sinceWarning = 0f;
319                                if (isActive()) {
320                                        //Global.getSector().getCampaignUI().getMessageDisplay().addMessage("Use again to confirm transponder deactivation");
321                                        Global.getSector().getCampaignUI().getMessageDisplay().addMessage(getDeactivationMessage());
322                                } else {
323                                        //Global.getSector().getCampaignUI().getMessageDisplay().addMessage("Use again to confirm transponder activation");
324                                        if (showAlarm) {
325                                                Global.getSector().getCampaignUI().getMessageDisplay().addMessage(getActivationMessage(), Misc.getNegativeHighlightColor());
326                                        } else {
327                                                Global.getSector().getCampaignUI().getMessageDisplay().addMessage(getActivationMessage());
328                                        }
329                                }
330                        }
331                } else {
332                        super.pressButton();
333                }
334        }
335        
336        protected String getDeactivationMessage() {
337                return "Transponder shutdown initiated - use again to deactivate";
338        }
339        protected String getActivationMessage() {
340                if (showAlarm) {
341                        return "Activating the transponder will reveal your identity - use again to confirm";
342                }
343                return "Transponder primed - use again to activate";
344        }
345
346
347        @Override
348        public float getCooldownFraction() {
349                if (sinceWarning < CONFIRM_DURATION) {
350                        return 0f;
351                }
352                return super.getCooldownFraction();
353        }
354
355
356        @Override
357        public boolean isOnCooldown() {
358                return false;
359        }
360
361
362        @Override
363        public Color getCooldownColor() {
364                if (sinceWarning < CONFIRM_DURATION) {
365                        Color color = Misc.getNegativeHighlightColor();
366                        //Color color = Color.red;
367                        if (!showAlarm) {
368                                color = Misc.getHighlightColor();
369                                //color = Color.yellow;
370                        }
371                        float b = 1f;
372                        float t = 0.25f;
373                        if (sinceWarning < t) {
374                                b = sinceWarning / t;
375                        }
376                        if (sinceWarning > CONFIRM_DURATION - t) {
377                                b = 1f - (sinceWarning - (CONFIRM_DURATION - t)) / t;
378                        }
379                        return Misc.scaleAlpha(color, Global.getSector().getCampaignUI().getSharedFader().getBrightness() * 0.75f * b);
380                }
381                return super.getCooldownColor();
382        }
383
384
385        @Override
386        public boolean isCooldownRenderingAdditive() {
387                return true;
388        }
389        
390        
391        
392}
393
394
395
396
397