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}