001package com.fs.starfarer.api.impl.campaign; 002 003import java.util.HashMap; 004import java.util.Map; 005 006import java.awt.Color; 007 008import com.fs.starfarer.api.Global; 009import com.fs.starfarer.api.campaign.CampaignFleetAPI; 010import com.fs.starfarer.api.campaign.InteractionDialogAPI; 011import com.fs.starfarer.api.campaign.InteractionDialogPlugin; 012import com.fs.starfarer.api.campaign.OptionPanelAPI; 013import com.fs.starfarer.api.campaign.RuleBasedDialog; 014import com.fs.starfarer.api.campaign.TextPanelAPI; 015import com.fs.starfarer.api.campaign.VisualPanelAPI; 016import com.fs.starfarer.api.campaign.econ.MarketAPI; 017import com.fs.starfarer.api.campaign.events.CampaignEventPlugin; 018import com.fs.starfarer.api.campaign.rules.MemKeys; 019import com.fs.starfarer.api.campaign.rules.MemoryAPI; 020import com.fs.starfarer.api.campaign.rules.RulesAPI; 021import com.fs.starfarer.api.characters.PersonAPI; 022import com.fs.starfarer.api.combat.EngagementResultAPI; 023import com.fs.starfarer.api.impl.campaign.ids.MemFlags; 024import com.fs.starfarer.api.impl.campaign.rulecmd.DismissDialog; 025import com.fs.starfarer.api.impl.campaign.rulecmd.DumpMemory; 026import com.fs.starfarer.api.impl.campaign.rulecmd.FireAll; 027import com.fs.starfarer.api.impl.campaign.rulecmd.FireBest; 028import com.fs.starfarer.api.util.Misc; 029 030/** 031 * @author Alex Mosolov 032 * 033 * Uses the data in data/campaign/rules.csv to drive the dialog interactions. 034 * 035 * Copyright 2014 Fractal Softworks, LLC 036 */ 037public class RuleBasedInteractionDialogPluginImpl implements InteractionDialogPlugin, RuleBasedDialog { 038 039 public static final String FAILSAFE_LEAVE = "rbid_failsafe_leave"; 040 041 private InteractionDialogAPI dialog; 042 private TextPanelAPI textPanel; 043 private OptionPanelAPI options; 044 private VisualPanelAPI visual; 045 046 private RulesAPI rules; 047 private MemoryAPI memory; 048 049 private CampaignFleetAPI playerFleet; 050 051 private Object custom1; 052 private Object custom2; 053 private Object custom3; 054 055 private static final Color HIGHLIGHT_COLOR = Global.getSettings().getColor("buttonShortcut"); 056 057 private boolean embeddedMode = false; 058 public void setEmbeddedMode(boolean embeddedMode) { 059 this.embeddedMode = embeddedMode; 060 } 061 062 private final String initialTrigger; 063 064 public RuleBasedInteractionDialogPluginImpl() { 065 this("OpenInteractionDialog"); 066 } 067 public RuleBasedInteractionDialogPluginImpl(String initialTrigger) { 068 this.initialTrigger = initialTrigger; 069 } 070 071 072 public void reinit(boolean withContinueOnRuleFound) { 073 init(dialog); 074 } 075 076 public void init(InteractionDialogAPI dialog) { 077 this.dialog = dialog; 078 079 textPanel = dialog.getTextPanel(); 080 options = dialog.getOptionPanel(); 081 visual = dialog.getVisualPanel(); 082 083 playerFleet = Global.getSector().getPlayerFleet(); 084 085 if (!embeddedMode) { 086 visual.setVisualFade(0.25f, 0.25f); 087 } 088 089 rules = Global.getSector().getRules(); 090 091 updateMemory(); 092 093 if (!embeddedMode) { 094 fireBest(initialTrigger); 095 if (!options.hasOptions()) { 096 options.clearOptions(); 097 options.addOption("Leave", FAILSAFE_LEAVE); 098 if (Global.getSettings().isDevMode()) { 099 DevMenuOptions.addOptions(dialog); 100 } 101 } 102 } 103 } 104 105 public void updateMemory() { 106 if (memoryMap == null) { 107 memoryMap = new HashMap<String, MemoryAPI>(); 108 } else { 109 memoryMap.clear(); 110 } 111 memory = dialog.getInteractionTarget().getMemory(); 112 113 memoryMap.put(MemKeys.LOCAL, memory); 114 if (dialog.getInteractionTarget().getFaction() != null) { 115 memoryMap.put(MemKeys.FACTION, dialog.getInteractionTarget().getFaction().getMemory()); 116 } else { 117 memoryMap.put(MemKeys.FACTION, Global.getFactory().createMemory()); 118 } 119 memoryMap.put(MemKeys.GLOBAL, Global.getSector().getMemory()); 120 memoryMap.put(MemKeys.PLAYER, Global.getSector().getCharacterData().getMemory()); 121 122 if (dialog.getInteractionTarget().getMarket() != null) { 123 memoryMap.put(MemKeys.MARKET, dialog.getInteractionTarget().getMarket().getMemory()); 124 } 125 126 if (memory.contains(MemFlags.MEMORY_KEY_SOURCE_MARKET)) { 127 String marketId = memory.getString(MemFlags.MEMORY_KEY_SOURCE_MARKET); 128 MarketAPI market = Global.getSector().getEconomy().getMarket(marketId); 129 if (market != null) { 130 memoryMap.put(MemKeys.SOURCE_MARKET, market.getMemory()); 131 } 132 } 133 134 updatePersonMemory(); 135 } 136 137 private void updatePersonMemory() { 138 PersonAPI person = dialog.getInteractionTarget().getActivePerson(); 139// if (person != null) { 140// memoryMap.put(MemKeys.PERSON, person.getMemory()); 141// } else { 142// memoryMap.remove(MemKeys.PERSON); 143// } 144 if (person != null) { 145 memory = person.getMemory(); 146 memoryMap.put(MemKeys.LOCAL, memory); 147 memoryMap.put(MemKeys.PERSON_FACTION, person.getFaction().getMemory()); 148 memoryMap.put(MemKeys.ENTITY, dialog.getInteractionTarget().getMemory()); 149 } else { 150 memory = dialog.getInteractionTarget().getMemory(); 151 memoryMap.put(MemKeys.LOCAL, memory); 152 memoryMap.remove(MemKeys.ENTITY); 153 memoryMap.remove(MemKeys.PERSON_FACTION); 154 155 } 156 } 157 158 159 public void notifyActivePersonChanged() { 160 updatePersonMemory(); 161 } 162 163 public void setActiveMission(CampaignEventPlugin mission) { 164 if (mission == null) { 165 memoryMap.remove(MemKeys.MISSION); 166 } else { 167 MemoryAPI memory = mission.getMemory(); 168 if (memory != null) { 169 memoryMap.put(MemKeys.MISSION, memory); 170 } else { 171 memoryMap.remove(MemKeys.MISSION); 172 } 173 } 174 } 175 176 177 public boolean fireAll(String trigger) { 178 return FireAll.fire(null, dialog, memoryMap, trigger); 179 } 180 181 public boolean fireBest(String trigger) { 182 return FireBest.fire(null, dialog, memoryMap, trigger); 183 } 184 185 public void backFromEngagement(EngagementResultAPI result) { 186 // no combat here, so this won't get called 187 } 188 189 public void optionSelected(String text, Object optionData) { 190 if (optionData == null || !(optionData instanceof String)) return; 191 192 String optionId = (String) optionData; 193 194 if (text != null) { 195 //textPanel.addParagraph(text, Global.getSettings().getColor("buttonText")); 196 dialog.addOptionSelectedText(optionData); 197 } 198 199 if (optionId == FAILSAFE_LEAVE) { 200 new DismissDialog().execute(null, dialog, null, memoryMap); 201 return; 202 } 203 204 if (optionId == DumpMemory.OPTION_ID) { 205 new DumpMemory().execute(null, dialog, null, memoryMap); 206 return; 207 } else if (DevMenuOptions.isDevOption(optionData)) { 208 DevMenuOptions.execute(dialog, (String) optionData); 209 return; 210 } 211 212 memory.set("$option", optionId); 213 memory.expire("$option", 0); 214 215 boolean foundRule = fireBest("DialogOptionSelected"); 216 if (!foundRule && !dialog.isCurrentOptionHadAConfirm()) { 217 textPanel.addPara("ERROR: no rule found for option " + optionId + 218 ", adding a failsafe option to exit dialog.", Misc.getNegativeHighlightColor()); 219 textPanel.addPara("Note: this may break any mission interaction in the current dialog, " 220 + "it's recommended that you reload an earlier save if you use this option."); 221 textPanel.highlightInLastPara(Misc.getNegativeHighlightColor(), "recommended that you reload an earlier save"); 222 options.addOption("Exit dialog", FAILSAFE_LEAVE); 223 } 224 225 } 226 227 228 private String lastOptionMousedOver = null; 229 private Map<String, MemoryAPI> memoryMap; 230 public void optionMousedOver(String optionText, Object optionData) { 231 232 } 233 234 public void advance(float amount) { 235// if (Global.getSettings().isDevMode() && Keyboard.isKeyDown(Keyboard.KEY_F2)) { 236// new DumpMemory().execute(dialog, new ArrayList<Token>(), memoryMap); 237// } 238 } 239 240 private void addText(String text) { 241 if (text == null || text.isEmpty()) return; 242 243 textPanel.addParagraph(text); 244 } 245 246 private void appendText(String text) { 247 textPanel.appendToLastParagraph(" " + text); 248 } 249 250 public Object getContext() { 251 return null; 252 } 253 254 public Map<String, MemoryAPI> getMemoryMap() { 255 return memoryMap; 256 } 257 public Object getCustom1() { 258 return custom1; 259 } 260 public void setCustom1(Object custom1) { 261 this.custom1 = custom1; 262 } 263 public Object getCustom2() { 264 return custom2; 265 } 266 public void setCustom2(Object custom2) { 267 this.custom2 = custom2; 268 } 269 public Object getCustom3() { 270 return custom3; 271 } 272 public void setCustom3(Object custom3) { 273 this.custom3 = custom3; 274 } 275 276} 277 278 279