001package com.fs.starfarer.api.impl.campaign.abilities;
002
003import java.awt.Color;
004import java.util.ArrayList;
005import java.util.Collections;
006import java.util.Comparator;
007import java.util.EnumSet;
008import java.util.List;
009
010import com.fs.starfarer.api.EveryFrameScript;
011import com.fs.starfarer.api.Global;
012import com.fs.starfarer.api.campaign.BattleAPI;
013import com.fs.starfarer.api.campaign.CampaignEngineLayers;
014import com.fs.starfarer.api.campaign.CampaignFleetAPI;
015import com.fs.starfarer.api.campaign.SectorEntityToken;
016import com.fs.starfarer.api.campaign.econ.MarketAPI;
017import com.fs.starfarer.api.characters.AbilityPlugin;
018import com.fs.starfarer.api.combat.ViewportAPI;
019import com.fs.starfarer.api.loading.AbilitySpecAPI;
020import com.fs.starfarer.api.ui.TooltipMakerAPI;
021import com.fs.starfarer.api.util.Misc;
022
023public abstract class BaseAbilityPlugin implements AbilityPlugin, EveryFrameScript{
024        
025        public static boolean PLAY_UI_SOUNDS_IN_WORLD_SOURCES = true;
026        
027        protected SectorEntityToken entity;
028        protected String id;
029        
030        protected int disableFrames = 0;
031        
032        protected transient AbilitySpecAPI spec = null;
033        
034        public void init(String id, SectorEntityToken entity) {
035                this.id = id;
036                this.entity = entity;
037                readResolve();
038        }
039        
040        protected Object readResolve() {
041                spec = Global.getSettings().getAbilitySpec(id);
042                return this;
043        }
044        Object writeReplace() {
045                return this;
046        }
047        
048        public String getOnSoundUI() { return spec.getUIOn(); }
049        public String getOnSoundWorld() { return spec.getWorldOn(); }
050        public String getOffSoundUI() { return spec.getUIOff(); }
051        public String getOffSoundWorld() { return spec.getWorldOff(); }
052
053        // no support for UI loops currently; just playing a stereo sound is a workaround
054        // but doesn't use the dedicated UI sound sources
055        public String getLoopSoundUI() { return spec.getUILoop(); }
056        public float getLoopSoundUIVolume() { return 1f; }
057        public float getLoopSoundUIPitch() { return 1f; }
058        
059        public String getLoopSoundWorld() { return spec.getWorldLoop(); }
060        public float getLoopSoundWorldVolume() { return 1f; }
061        public float getLoopSoundWorldPitch() { return 1f; }
062        
063
064        protected void interruptIncompatible() {
065                CampaignFleetAPI fleet = getFleet();
066                if (fleet == null) return;
067                
068                for (AbilityPlugin curr : fleet.getAbilities().values()) {
069                        if (curr == this) continue;
070                        if (!isCompatible(curr) && curr.isActive()) {
071                                curr.deactivate();
072                        }
073                }
074        }
075        
076        protected void disableIncompatible() {
077                CampaignFleetAPI fleet = getFleet();
078                if (fleet == null) return;
079                
080                for (AbilityPlugin curr : fleet.getAbilities().values()) {
081                        if (curr == this) continue;
082                        if (!isCompatible(curr)) {
083                                curr.forceDisable();
084                        }
085                }
086        }
087        
088        public boolean isCompatible(AbilityPlugin other) {
089                for (String tag : spec.getTags()) {
090                        if (!spec.isPositiveTag(tag) && !spec.isNegativeTag(tag)) continue;
091                        if (spec.isPositiveTag(tag) && other.getSpec().hasTag(tag)) return false;
092                        if (other.getSpec().hasOppositeTag(tag)) return false;
093                }
094                return true;
095        }
096        
097        protected void addIncompatibleToTooltip(TooltipMakerAPI tooltip, String desc, String descShort, boolean expanded) {
098                List<AbilityPlugin> list = getInterruptedList();
099                if (list.isEmpty()) return;
100                
101                if (expanded) {
102                        String pre = desc;
103                        tooltip.addPara(pre, 10f);
104                        
105                        String str = "";
106                        for (AbilityPlugin curr : list) {
107                                str += "    " + curr.getSpec().getName() + "\n";
108                        }
109                        str = str.substring(0, str.length() - 1);
110                        Color c = Misc.getTooltipTitleAndLightHighlightColor();
111                        //c = Misc.interpolateColor(c, Color.black, 0.2f);
112                        //c = Misc.getGrayColor();
113                        tooltip.addPara(str, c, 3f);
114                } else {
115                        Color c = Misc.getGrayColor();                  
116                        tooltip.addPara(descShort, c, 10f);
117                }
118        }
119        
120        public List<AbilityPlugin> getInterruptedList() {
121                List<AbilityPlugin> result = new ArrayList<AbilityPlugin>(); 
122                CampaignFleetAPI fleet = getFleet();
123                if (fleet == null) return result;
124                
125                for (AbilityPlugin curr : fleet.getAbilities().values()) {
126                        if (curr == this) continue;
127                        
128                        if (this instanceof BaseToggleAbility && curr instanceof BaseDurationAbility) {
129                                continue;
130                        }
131                        if (!isCompatible(curr)) {
132                                result.add(curr);
133                        }
134                }
135                Collections.sort(result, new Comparator<AbilityPlugin>() {
136                        public int compare(AbilityPlugin o1, AbilityPlugin o2) {
137                                return o1.getSpec().getSortOrder() - o2.getSpec().getSortOrder();
138                        }
139                });
140                return result;
141        }
142        
143        
144        public String getModId() {
145                return id + "_ability_mod";
146        }
147        
148        public CampaignFleetAPI getFleet() {
149                if (entity instanceof CampaignFleetAPI) {
150                        return (CampaignFleetAPI) entity;
151                }
152                return null;
153        }
154        
155        public SectorEntityToken getEntity() {
156                return entity;
157        }
158        
159        public String getId() {
160                return id;
161        }
162        
163        public void advance(float amount) {
164                disableFrames--;
165                if (disableFrames < 0) disableFrames = 0;
166        }
167
168        public boolean isDone() {
169                return false;
170        }
171
172        public boolean runWhilePaused() {
173                return false;
174        }
175        
176        public boolean showActiveIndicator() {
177                return isActive();
178        }
179        
180        public boolean isUsable() {
181                return !isOnCooldown() && disableFrames <= 0;
182        }
183        
184        public void forceDisable() {
185                disableFrames = 2;
186        }
187        
188        public float getCooldownFraction() {
189                return 1f;
190        }
191        
192        public boolean hasCustomButtonPressSounds() {
193                return false;
194        }
195        
196        public boolean hasTooltip() {
197                return true;
198        }
199        
200        public void createTooltip(TooltipMakerAPI tooltip, boolean expanded) {
201        }
202        
203        public boolean isTooltipExpandable() {
204                return true;
205        }
206        
207        public float getTooltipWidth() {
208                return 350f;
209        }
210
211
212        public void pressButton() {
213                
214        }
215
216        public String getSpriteName() {
217                return spec.getIconName();
218//              if (spec.getIconName() != null) return spec.getIconName();
219//              return Global.getSettings().getSpriteName("abilities", "empty_slot");
220        }
221
222        public void activate() {
223                CampaignFleetAPI fleet = getFleet();
224                if (fleet == null || !fleet.isPlayerFleet()) return;
225                Global.getSector().reportPlayerActivatedAbility(this, null);
226                //interruptIncompatible();
227        }
228
229        public void deactivate() {
230                CampaignFleetAPI fleet = getFleet();
231                if (fleet == null || !fleet.isPlayerFleet()) return;
232                Global.getSector().reportPlayerDeactivatedAbility(this, null);
233        }
234
235
236        private static Color defaultCooldownColor = new Color(0,0,0,171);
237        public Color getCooldownColor() {
238                return defaultCooldownColor;
239        }
240
241        public Color getProgressColor() {
242                return entity.getFaction().getBrightUIColor();
243        }
244        
245        public Color getActiveColor() {
246                return entity.getFaction().getBrightUIColor();
247        }
248
249        public float getProgressFraction() {
250                return 0;
251        }
252
253        public boolean isActive() {
254                return false;
255        }
256
257        public boolean isActiveOrInProgress() {
258                return isActive() || isInProgress();
259        }
260
261        public boolean isInProgress() {
262                return getProgressFraction() > 0;
263        }
264
265        public boolean showCooldownIndicator() {
266                return getCooldownFraction() < 1;
267        }
268
269        public boolean showProgressIndicator() {
270                return getProgressFraction() > 0;
271        }
272        
273        
274        public boolean isOnCooldown() {
275                return getCooldownFraction() < 1f;
276        }
277
278        public void cleanup() {
279                
280        }
281
282        public boolean isCooldownRenderingAdditive() {
283                return false;
284        }
285        
286        public abstract void setCooldownLeft(float days);
287        public abstract float getCooldownLeft();
288        
289        protected String getActivationText() {
290                return Misc.ucFirst(spec.getName().toLowerCase());
291                //return null;
292        }
293        
294        protected String getDeactivationText() {
295                return null;
296        }
297
298        public void fleetJoinedBattle(BattleAPI battle) {
299        }
300
301        public void fleetLeftBattle(BattleAPI battle, boolean engagedInHostilities) {
302        }
303
304        public void fleetOpenedMarket(MarketAPI market) {
305        }
306
307        public AbilitySpecAPI getSpec() {
308                return spec;
309        }
310
311        public EnumSet<CampaignEngineLayers> getActiveLayers() {
312                return null;
313        }
314
315        public void render(CampaignEngineLayers layer, ViewportAPI viewport) {
316        }
317
318        public float getLevel() {
319                return 0;
320        }
321
322        
323}