001package com.fs.starfarer.api.impl; 002 003import java.util.HashMap; 004import java.util.Map; 005 006import com.fs.starfarer.api.Global; 007import com.fs.starfarer.api.MusicPlayerPluginWithVolumeControl; 008import com.fs.starfarer.api.campaign.CampaignFleetAPI; 009import com.fs.starfarer.api.campaign.FactionAPI; 010import com.fs.starfarer.api.campaign.RepLevel; 011import com.fs.starfarer.api.campaign.SectorEntityToken; 012import com.fs.starfarer.api.campaign.StarSystemAPI; 013import com.fs.starfarer.api.campaign.ai.ModularFleetAIAPI; 014import com.fs.starfarer.api.campaign.econ.MarketAPI; 015import com.fs.starfarer.api.campaign.rules.MemoryAPI; 016import com.fs.starfarer.api.combat.CombatEngineAPI; 017import com.fs.starfarer.api.impl.campaign.ids.Entities; 018import com.fs.starfarer.api.impl.campaign.ids.Factions; 019import com.fs.starfarer.api.impl.campaign.ids.Tags; 020import com.fs.starfarer.api.impl.campaign.tutorial.TutorialMissionIntel; 021import com.fs.starfarer.api.util.Misc; 022 023public class MusicPlayerPluginImpl implements MusicPlayerPluginWithVolumeControl { 024 025 public static String KEEP_PLAYING_LOCATION_MUSIC_DURING_ENCOUNTER_MEM_KEY = "$playLocationMusicDuringEnc"; 026 public static String COMBAT_MUSIC_SET_MEM_KEY = "$combatMusicSetId"; 027 public static String COMBAT_MUSIC_SET_FACTION_KEY = "music_combat_set"; 028 public static String MUSIC_SET_MEM_KEY = "$musicSetId"; 029 public static String MUSIC_SET_MEM_KEY_MISSION = "$musicSetIdForMission"; 030 031 032 public static String MUSIC_ENCOUNTER_MYSTERIOUS_AGGRO = "music_encounter_mysterious"; 033 public static String MUSIC_ENCOUNTER_MYSTERIOUS_NON_AGGRESSIVE = "music_encounter_mysterious_non_aggressive"; 034 public static String MUSIC_ENCOUNTER_NEUTRAL = "music_encounter_neutral"; 035 public static String MUSIC_GALATIA_ACADEMY = "music_galatia_academy"; 036 037 038 public static Object CAMPAIGN_SYSTEM = new Object(); 039 public static Object CAMPAIGN_HYPERSPACE = new Object(); 040 public static Object NO_MUSIC = new Object(); 041 public static Object COMBAT = new Object(); 042 public static Object TITLE = new Object(); 043 public static Object MARKET = new Object(); 044 public static Object ENCOUNTER = new Object(); 045 public static Object PLANET_SURVEY = new Object(); 046 047 public static Object CUSTOM = new Object(); 048 049 public static Map<String, String> stringTokens = new HashMap<String, String>(); 050 051 /** 052 * Goal here is to return tokens for which an == comparison works. 053 * @param str 054 * @return 055 */ 056 public static Object getToken(String str) { 057 if (!stringTokens.containsKey(str)) { 058 stringTokens.put(str, str); 059 } 060 return stringTokens.get(str); 061 } 062 063 public static String SYSTEM_MUSIC_PREFIX = "core_sys_music_"; 064 065 public Object getStateTokenForCampaignLocation() { 066 CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet(); 067 if (playerFleet.getContainingLocation() instanceof StarSystemAPI) { 068 /* 069 Just returning CAMPAIGN_SYSTEM and letting getMusicSetIdForCampaignStateToken() 070 return the musicSetId misses the case where there's a transition between 071 two star systems with different music, without hyperspace travel in between - 072 since there would be no state transition (due to it being the same CAMPAIGN_SYSTEM state), 073 a restart of the music - and a change to a different music set - would not be triggered. 074 075 Since the state ID includes the music set id, this means that moving between 076 two systems with the same $musicSetId will not trigger a state change and 077 the same music will just keep playing uninterrupted. 078 */ 079 StarSystemAPI system = (StarSystemAPI) playerFleet.getContainingLocation(); 080 String musicSetId = system.getMemoryWithoutUpdate().getString(MUSIC_SET_MEM_KEY_MISSION); 081 if (musicSetId != null) { 082 return getToken(SYSTEM_MUSIC_PREFIX + musicSetId); 083 } 084 musicSetId = system.getMemoryWithoutUpdate().getString(MUSIC_SET_MEM_KEY); 085 if (musicSetId != null) { 086 return getToken(SYSTEM_MUSIC_PREFIX + musicSetId); 087 } 088 return CAMPAIGN_SYSTEM; 089 } 090// float depth = Misc.getAbyssalDepthOfPlayer(); 091// if (depth > 0.5f) { 092// return NO_MUSIC; 093// } 094 return CAMPAIGN_HYPERSPACE; 095 } 096 097 public String getMusicSetIdForCombat(CombatEngineAPI engine) { 098 if (engine.getContext() != null && engine.getContext().getOtherFleet() != null) { 099 CampaignFleetAPI other = engine.getContext().getOtherFleet(); 100 MemoryAPI mem = other.getMemoryWithoutUpdate(); 101 if (mem.contains(COMBAT_MUSIC_SET_MEM_KEY)) { 102 return mem.getString(COMBAT_MUSIC_SET_MEM_KEY); 103 } 104 String factionSet = other.getFaction().getMusicMap().get(COMBAT_MUSIC_SET_FACTION_KEY); 105 if (factionSet != null) return factionSet; 106 } 107 return "music_combat"; 108 } 109 110 public String getMusicSetIdForTitle() { 111 return "music_title"; 112 } 113 114 115 public float getMusicSetVolumeForCampaignStateToken(Object token, Object param) { 116 if (token == CAMPAIGN_HYPERSPACE) { 117 //float depth = Misc.getAbyssalDepthOfPlayer(); 118 // need to check this way so that the hyperspace track doesn't fade back in 119 // right after transitiong to an abyssal system (as the track fades out) 120 CampaignFleetAPI pf = Global.getSector().getPlayerFleet(); 121 float depth = 0f; 122 if (pf != null) depth = Misc.getAbyssalDepth(pf.getLocationInHyperspace()); 123 float vol = 1f - depth; 124 if (vol > 1f) vol = 1f; 125 if (vol < 0f) vol = 0f; 126 return vol; 127 } 128 return 1f; 129 } 130 131 public String getMusicSetIdForCampaignStateToken(Object token, Object param) { 132 if (token == MARKET) { 133 return getMarketMusicSetId(param); 134 } 135 if (token == ENCOUNTER) { 136 return getEncounterMusicSetId(param); 137 } 138 if (token == CAMPAIGN_SYSTEM || 139 (token instanceof String && ((String)token).startsWith(SYSTEM_MUSIC_PREFIX))) { 140 return getStarSystemMusicSetId(); 141 } 142 if (token == CAMPAIGN_HYPERSPACE) { 143 return getHyperspaceMusicSetId(); 144 } 145 if (token == PLANET_SURVEY) { 146 return getPlanetSurveyMusicSetId(param); 147 } 148 if (token == NO_MUSIC) { 149 return null; 150 } 151 return null; 152 } 153 154 /** 155 * @param param is a MarketAPI. 156 * @return 157 */ 158 protected String getPlanetSurveyMusicSetId(Object param) { 159 SectorEntityToken token = null; 160 if (param instanceof SectorEntityToken) { 161 token = (SectorEntityToken) param; 162 } else if (param instanceof MarketAPI) { 163 token = ((MarketAPI)param).getPlanetEntity(); 164 } 165 if (token != null) { 166 String musicSetId = token.getMemoryWithoutUpdate().getString(MUSIC_SET_MEM_KEY_MISSION); 167 if (musicSetId != null) return musicSetId; 168 musicSetId = token.getMemoryWithoutUpdate().getString(MUSIC_SET_MEM_KEY); 169 if (musicSetId != null) return musicSetId; 170 } 171 return "music_survey_and_scavenge"; 172 } 173 174 protected String getHyperspaceMusicSetId() { 175 return "music_campaign_hyperspace"; 176 } 177 178 protected String getStarSystemMusicSetId() { 179 CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet(); 180 if (playerFleet.getContainingLocation() instanceof StarSystemAPI) { 181 StarSystemAPI system = (StarSystemAPI) playerFleet.getContainingLocation(); 182 String musicSetId = system.getMemoryWithoutUpdate().getString(MUSIC_SET_MEM_KEY_MISSION); 183 if (musicSetId != null) return musicSetId; 184 musicSetId = system.getMemoryWithoutUpdate().getString(MUSIC_SET_MEM_KEY); 185 if (musicSetId != null) return musicSetId; 186 187 if (system.hasTag(Tags.SYSTEM_ABYSSAL)) { 188 return "music_campaign_abyssal"; 189 } 190 if (system.hasTag(Tags.THEME_CORE) || 191 !Misc.getMarketsInLocation(system, Factions.PLAYER).isEmpty()) { 192 return "music_campaign"; 193 } 194 } 195 196 return "music_campaign_non_core"; 197 } 198 199 protected String getEncounterMusicSetId(Object param) { 200 if (param instanceof SectorEntityToken) { 201 SectorEntityToken token = (SectorEntityToken) param; 202 203 String musicSetId = token.getMemoryWithoutUpdate().getString(MUSIC_SET_MEM_KEY_MISSION); 204 if (musicSetId != null) return musicSetId; 205 musicSetId = token.getMemoryWithoutUpdate().getString(MUSIC_SET_MEM_KEY); 206 if (musicSetId != null) return musicSetId; 207 208 if (Entities.ABYSSAL_LIGHT.equals(token.getCustomEntityType())) { 209 return MUSIC_ENCOUNTER_NEUTRAL; 210 } 211 if (Entities.CORONAL_TAP.equals(token.getCustomEntityType())) { 212 return MUSIC_ENCOUNTER_MYSTERIOUS_AGGRO; 213 } 214 if (Entities.WRECK.equals(token.getCustomEntityType())) { 215 return MUSIC_ENCOUNTER_NEUTRAL; 216 } 217 if (Entities.DERELICT_GATEHAULER.equals(token.getCustomEntityType())) { 218 return MUSIC_ENCOUNTER_MYSTERIOUS_NON_AGGRESSIVE; 219 } 220 221 if (Entities.DEBRIS_FIELD_SHARED.equals(token.getCustomEntityType())) { 222 return "music_survey_and_scavenge"; 223 } 224 if (token.hasTag(Tags.GATE)) { 225 return MUSIC_ENCOUNTER_NEUTRAL; 226 } 227 if (token.hasTag(Tags.OBJECTIVE)) { 228 return MUSIC_ENCOUNTER_NEUTRAL; 229 } 230 if (token.hasTag(Tags.SALVAGEABLE)) { 231 if (token.getMemoryWithoutUpdate() != null && token.getMemoryWithoutUpdate().getBoolean("$hasDefenders")) { 232 if (token.getMemoryWithoutUpdate().getBoolean("$limboMiningStation")) { 233 return MUSIC_ENCOUNTER_MYSTERIOUS_AGGRO; 234 } 235 if (token.getMemoryWithoutUpdate().getBoolean("$limboWormholeCache")) { 236 return MUSIC_ENCOUNTER_MYSTERIOUS_AGGRO; 237 } 238 return MUSIC_ENCOUNTER_NEUTRAL; 239 } 240 return "music_survey_and_scavenge"; 241 } 242 if (token.hasTag(Tags.SALVAGE_MUSIC)) { 243 return "music_survey_and_scavenge"; 244 } 245 246// MemoryAPI memory = token.getMemoryWithoutUpdate(); 247// if (!memory.getBoolean("$defenderFleetDefeated") && memory.getBoolean("$hasDefenders")) { 248// CampaignFleetAPI defenders = memory.getFleet("$defenderFleet"); 249// if (defenders != null) token = defenders; 250// } 251 252 if (token.getFaction() != null) { 253 FactionAPI faction = (FactionAPI) token.getFaction(); 254 String type = null; 255 //MemoryAPI mem = token.getMemoryWithoutUpdate(); 256 boolean hostile = false; 257 boolean knowsWhoPlayerIs = false; 258 if (token instanceof CampaignFleetAPI) { 259 CampaignFleetAPI fleet = (CampaignFleetAPI) token; 260 if (fleet.getAI() instanceof ModularFleetAIAPI) { 261 hostile = ((ModularFleetAIAPI) fleet.getAI()).isHostileTo(Global.getSector().getPlayerFleet()); 262 } 263 knowsWhoPlayerIs = fleet.knowsWhoPlayerIs(); 264 } 265 266 if (faction.isAtWorst(Factions.PLAYER, RepLevel.FAVORABLE) && knowsWhoPlayerIs && !hostile) { 267 type = "encounter_friendly"; 268 } else if ((faction.isAtBest(Factions.PLAYER, RepLevel.SUSPICIOUS) && knowsWhoPlayerIs) || hostile) { 269 type = "encounter_hostile"; 270 } else { 271 type = "encounter_neutral"; 272 } 273 274 if (type != null) { 275 musicSetId = faction.getMusicMap().get(type); 276 if (musicSetId != null) { 277 return musicSetId; 278 } 279 } 280 281 musicSetId = null; 282 if (faction.isAtWorst(Factions.PLAYER, RepLevel.FAVORABLE)) { 283 musicSetId = "music_default_encounter_friendly"; 284 } else if (faction.isAtBest(Factions.PLAYER, RepLevel.SUSPICIOUS)) { 285 musicSetId = "music_default_encounter_hostile"; 286 } else { 287 musicSetId = "music_default_encounter_neutral"; 288 } 289 return musicSetId; 290 } 291 } 292 return null; 293 } 294 295 296 protected String getMarketMusicSetId(Object param) { 297 if (param instanceof MarketAPI) { 298 MarketAPI market = (MarketAPI) param; 299 300 String musicSetId = market.getMemoryWithoutUpdate().getString(MUSIC_SET_MEM_KEY_MISSION); 301 if (musicSetId != null) return musicSetId; 302 musicSetId = market.getMemoryWithoutUpdate().getString(MUSIC_SET_MEM_KEY); 303 if (musicSetId != null) return musicSetId; 304 305 if (market.getPrimaryEntity() != null && 306 market.getPrimaryEntity().getMemoryWithoutUpdate().getBoolean("$abandonedStation")) { 307 return getPlanetSurveyMusicSetId(param); 308 } 309 310 if (market.getPrimaryEntity() != null && 311 market.getPrimaryEntity().getId().equals("station_galatia_academy")) { 312 if (TutorialMissionIntel.isTutorialInProgress()) { 313 return MUSIC_ENCOUNTER_MYSTERIOUS_AGGRO; 314 } 315 return MUSIC_GALATIA_ACADEMY; 316 } 317 318 FactionAPI faction = market.getFaction(); 319 if (faction != null) { 320 String type = null; 321 if (faction.isAtWorst(Factions.PLAYER, RepLevel.FAVORABLE)) { 322 type = "market_friendly"; 323 } else if (faction.isAtBest(Factions.PLAYER, RepLevel.SUSPICIOUS)) { 324 type = "market_hostile"; 325 } else { 326 type = "market_neutral"; 327 } 328 329 if (type != null) { 330 musicSetId = faction.getMusicMap().get(type); 331 if (musicSetId != null) { 332 return musicSetId; 333 } 334 } 335 336 musicSetId = null; 337 if (faction.isAtWorst(Factions.PLAYER, RepLevel.FAVORABLE)) { 338 musicSetId = "music_default_market_friendly"; 339 } else if (faction.isAtBest(Factions.PLAYER, RepLevel.SUSPICIOUS)) { 340 musicSetId = "music_default_market_hostile"; 341 } else { 342 musicSetId = "music_default_market_neutral"; 343 } 344 return musicSetId; 345 } 346 } 347 return null; 348 } 349} 350 351 352 353 354 355 356 357