001package com.fs.starfarer.api.impl.campaign.intel.punitive; 002 003import java.awt.Color; 004import java.util.Map; 005 006import org.lwjgl.input.Keyboard; 007 008import com.fs.starfarer.api.Global; 009import com.fs.starfarer.api.campaign.CampaignFleetAPI; 010import com.fs.starfarer.api.campaign.FactionAPI; 011import com.fs.starfarer.api.campaign.InteractionDialogAPI; 012import com.fs.starfarer.api.campaign.InteractionDialogPlugin; 013import com.fs.starfarer.api.campaign.OptionPanelAPI; 014import com.fs.starfarer.api.campaign.RepLevel; 015import com.fs.starfarer.api.campaign.TextPanelAPI; 016import com.fs.starfarer.api.campaign.VisualPanelAPI; 017import com.fs.starfarer.api.campaign.ReputationActionResponsePlugin.ReputationAdjustmentResult; 018import com.fs.starfarer.api.campaign.rules.MemoryAPI; 019import com.fs.starfarer.api.combat.EngagementResultAPI; 020import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin; 021import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.CustomRepImpact; 022import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActionEnvelope; 023import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActions; 024import com.fs.starfarer.api.impl.campaign.ids.Factions; 025import com.fs.starfarer.api.impl.campaign.ids.Sounds; 026import com.fs.starfarer.api.impl.campaign.intel.punitive.PunitiveExpeditionIntel.PunExOutcome; 027import com.fs.starfarer.api.impl.campaign.intel.punitive.PunitiveExpeditionManager.PunExData; 028import com.fs.starfarer.api.impl.campaign.rulecmd.AddRemoveCommodity; 029import com.fs.starfarer.api.impl.campaign.rulecmd.SetStoryOption; 030import com.fs.starfarer.api.ui.IntelUIAPI; 031import com.fs.starfarer.api.ui.TooltipMakerAPI; 032import com.fs.starfarer.api.util.Misc; 033 034public class PEAvertInteractionDialogPluginImpl implements InteractionDialogPlugin { 035 036 private static enum OptionId { 037 INIT, 038 USE_CONNECTIONS, 039 BRIBE, 040 LEAVE, 041 042 CONFIRM, 043 CANCEL, 044 } 045 046 //public static float BRIBE_BASE = 0; 047 public static int BRIBE_MULT = 10000; 048 public static int BRIBE_MAX = 100000; 049 050 public static RepLevel MIN_REP = RepLevel.WELCOMING; 051 public static float REP_COST = 0.2f; 052 053 protected InteractionDialogAPI dialog; 054 protected TextPanelAPI textPanel; 055 protected OptionPanelAPI options; 056 protected VisualPanelAPI visual; 057 058 protected CampaignFleetAPI playerFleet; 059 060 protected PunitiveExpeditionIntel intel; 061 protected IntelUIAPI ui; 062 063 public PEAvertInteractionDialogPluginImpl(PunitiveExpeditionIntel intel, IntelUIAPI ui) { 064 this.intel = intel; 065 this.ui = ui; 066 } 067 068 public void init(InteractionDialogAPI dialog) { 069 this.dialog = dialog; 070 textPanel = dialog.getTextPanel(); 071 options = dialog.getOptionPanel(); 072 visual = dialog.getVisualPanel(); 073 074 playerFleet = Global.getSector().getPlayerFleet(); 075 076 visual.setVisualFade(0.25f, 0.25f); 077 //visual.showImagePortion("illustrations", "quartermaster", 640, 400, 0, 0, 480, 300); 078 visual.showPlanetInfo(intel.getTarget().getPrimaryEntity()); 079 080 dialog.setOptionOnEscape("Leave", OptionId.LEAVE); 081 082 optionSelected(null, OptionId.INIT); 083 } 084 085 public Map<String, MemoryAPI> getMemoryMap() { 086 return null; 087 } 088 089 public void backFromEngagement(EngagementResultAPI result) { 090 // no combat here, so this won't get called 091 } 092 093 protected int computeBribeAmount() { 094 PunExData data = PunitiveExpeditionManager.getInstance().getDataFor(intel.getFaction()); 095 int numAttempts = 1; 096 if (data != null) numAttempts = data.numAttempts; 097 098 int bribe = (int) (Math.pow(2, numAttempts) * BRIBE_MULT); 099 if (bribe > BRIBE_MAX) bribe = BRIBE_MAX; 100 return bribe; 101// int bribe = (int) Math.round(BRIBE_BASE + data.threshold * BRIBE_MULT); 102// return bribe; 103 } 104 105 protected void printOptionDesc(OptionId option) { 106 Color tc = Misc.getTextColor(); 107 FactionAPI faction = intel.getFaction(); 108 109 switch (option) { 110 case BRIBE: 111 int bribe = computeBribeAmount(); 112 textPanel.addPara("Sufficient funding allocated to proper official and unofficial actors should " + 113 "ensure that the expedition does not go beyond the planning stages."); 114 115 int credits = (int) playerFleet.getCargo().getCredits().get(); 116 Color costColor = Misc.getHighlightColor(); 117 if (bribe > credits) costColor = Misc.getNegativeHighlightColor(); 118 119 textPanel.addPara("A total of %s should be enough to get the job done, and will also " + 120 "ensure that your standing with " + faction.getDisplayNameWithArticle() + 121 " does not suffer.", 122 costColor, 123 Misc.getDGSCredits(bribe)); 124 125 textPanel.addPara("You have %s available.", Misc.getHighlightColor(), 126 Misc.getDGSCredits(credits)); 127 128 break; 129 case USE_CONNECTIONS: 130 boolean canUseConnections = faction.isAtWorst(Factions.PLAYER, MIN_REP); 131 if (canUseConnections) { 132 textPanel.addPara("You can use your connections to pull a few strings and ensure the operation " + 133 "never gets beyond the planning stages."); 134 } else { 135 textPanel.addPara("You do not have sufficient connections with " + faction.getPersonNamePrefix() + 136 " officials to stall out this kind of an operation."); 137 CoreReputationPlugin.addRequiredStanding(faction, MIN_REP, null, textPanel, null, tc, 0, true); 138 } 139 140 CoreReputationPlugin.addCurrentStanding(faction, null, textPanel, null, tc, 0f); 141 142 if (canUseConnections) { 143 textPanel.addPara("Calling in these favors will reduce your " + 144 "standing with " + faction.getDisplayNameWithArticle() + " by %s points.", 145 Misc.getHighlightColor(), "" + (int) Math.round(REP_COST * 100f)); 146 } 147 148 break; 149 } 150 } 151 152 protected void addChoiceOptions() { 153 options.clearOptions(); 154 155 options.addOption("Allocate sufficient funds for bribes and other means of disrupting the planning", OptionId.BRIBE, null); 156 options.addOption("Use your connections to disrupt the planning", OptionId.USE_CONNECTIONS, null); 157 158 dialog.setOptionColor(OptionId.BRIBE, Misc.getStoryOptionColor()); 159 160 options.addOption("Dismiss", OptionId.LEAVE, null); 161 options.setShortcut(OptionId.LEAVE, Keyboard.KEY_ESCAPE, false, false, false, true); 162 } 163 164 protected void addDismissOption() { 165 options.clearOptions(); 166 options.addOption("Dismiss", OptionId.LEAVE, null); 167 options.setShortcut(OptionId.LEAVE, Keyboard.KEY_ESCAPE, false, false, false, true); 168 } 169 170 protected OptionId beingConfirmed = null; 171 protected void addConfirmOptions() { 172 if (beingConfirmed == null) return; 173 174 options.clearOptions(); 175 176 printOptionDesc(beingConfirmed); 177 178 options.addOption("Take the necessary actions", OptionId.CONFIRM, null); 179 options.addOption("Never mind", OptionId.CANCEL, null); 180 options.setShortcut(OptionId.CANCEL, Keyboard.KEY_ESCAPE, false, false, false, true); 181 182 if (beingConfirmed == OptionId.BRIBE) { 183 184 SetStoryOption.set(dialog, 1, OptionId.CONFIRM, "bribePunitiveExpedition", Sounds.STORY_POINT_SPEND_INDUSTRY, 185 "Issued bribe to avert " + intel.getFaction().getDisplayName() + " punitive expedition"); 186 187 int bribe = computeBribeAmount(); 188 if (bribe > playerFleet.getCargo().getCredits().get()) { 189 options.setEnabled(OptionId.CONFIRM, false); 190 options.setTooltip(OptionId.CONFIRM, "Not enough credits."); 191 } 192 } else if (beingConfirmed == OptionId.USE_CONNECTIONS) { 193 FactionAPI faction = intel.getFaction(); 194 boolean canUseConnections = faction.isAtWorst(Factions.PLAYER, MIN_REP); 195 if (!canUseConnections) { 196 options.setEnabled(OptionId.CONFIRM, false); 197 options.setTooltip(OptionId.CONFIRM, "Standing not high enough."); 198 } 199 } 200 } 201 202 203 public void printInit() { 204 TooltipMakerAPI info = textPanel.beginTooltip(); 205 info.setParaSmallInsignia(); 206 intel.addInitialDescSection(info, 0); 207 textPanel.addTooltip(); 208 209 textPanel.addPara("The operation is still in the planning stages, " + 210 "and you have several options at your disposal to ensure it never gets off the ground."); 211 } 212 213 public void optionSelected(String text, Object optionData) { 214 if (optionData == null) return; 215 216 OptionId option = (OptionId) optionData; 217 218 if (text != null) { 219 //textPanel.addParagraph(text, Global.getSettings().getColor("buttonText")); 220 dialog.addOptionSelectedText(option); 221 } 222 223 switch (option) { 224 case INIT: 225 printInit(); 226 addChoiceOptions(); 227 break; 228 case BRIBE: 229 beingConfirmed = OptionId.BRIBE; 230 addConfirmOptions(); 231 break; 232 case USE_CONNECTIONS: 233 beingConfirmed = OptionId.USE_CONNECTIONS; 234 addConfirmOptions(); 235 break; 236 case CONFIRM: 237 if (beingConfirmed == OptionId.BRIBE) { 238 int bribe = computeBribeAmount(); 239 AddRemoveCommodity.addCreditsLossText(bribe, textPanel); 240 playerFleet.getCargo().getCredits().subtract(bribe); 241 } else if (beingConfirmed == OptionId.USE_CONNECTIONS) { 242 CustomRepImpact impact = new CustomRepImpact(); 243 impact.delta = -REP_COST; 244 ReputationAdjustmentResult repResult = Global.getSector().adjustPlayerReputation( 245 new RepActionEnvelope(RepActions.CUSTOM, 246 impact, null, textPanel, false, true), 247 intel.getFaction().getId()); 248 } 249 intel.getOrganizeStage().abort(); 250 intel.setOutcome(PunExOutcome.AVERTED); 251 intel.forceFail(false); 252 intel.sendUpdate(PunitiveExpeditionIntel.OUTCOME_UPDATE, textPanel); 253 addDismissOption(); 254 break; 255 case CANCEL: 256 addChoiceOptions(); 257 break; 258 case LEAVE: 259 leave(); 260 break; 261 } 262 } 263 264 protected void leave() { 265 dialog.dismiss(); 266 ui.updateUIForItem(intel); 267 } 268 269 public void optionMousedOver(String optionText, Object optionData) { 270 271 } 272 273 public void advance(float amount) { 274 275 } 276 277 public Object getContext() { 278 return null; 279 } 280} 281 282 283