001package com.fs.starfarer.api.impl.campaign.events; 002 003import java.util.ArrayList; 004import java.util.List; 005import java.util.Map; 006 007import org.apache.log4j.Logger; 008 009import com.fs.starfarer.api.Global; 010import com.fs.starfarer.api.campaign.BaseOnMessageDeliveryScript; 011import com.fs.starfarer.api.campaign.CampaignFleetAPI; 012import com.fs.starfarer.api.campaign.CargoAPI; 013import com.fs.starfarer.api.campaign.FactionAPI; 014import com.fs.starfarer.api.campaign.InteractionDialogAPI; 015import com.fs.starfarer.api.campaign.RepLevel; 016import com.fs.starfarer.api.campaign.comm.CommMessageAPI; 017import com.fs.starfarer.api.campaign.comm.MessagePriority; 018import com.fs.starfarer.api.campaign.econ.MarketAPI; 019import com.fs.starfarer.api.campaign.events.CampaignEventTarget; 020import com.fs.starfarer.api.campaign.rules.MemoryAPI; 021import com.fs.starfarer.api.characters.PersonAPI; 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.Conditions; 025import com.fs.starfarer.api.impl.campaign.ids.Factions; 026import com.fs.starfarer.api.impl.campaign.ids.MemFlags; 027import com.fs.starfarer.api.impl.campaign.ids.Ranks; 028import com.fs.starfarer.api.util.Misc; 029import com.fs.starfarer.api.util.WeightedRandomPicker; 030import com.fs.starfarer.api.util.Misc.Token; 031 032/** 033 * @author Alex Mosolov 034 * 035 * Copyright 2015 Fractal Softworks, LLC 036 */ 037public class InvestigationEventGoodRepWithOther extends BaseEventPlugin { 038 public static final String PERSON_CHECKOUT_REASON = "IGR_investigator"; 039 040 public static class InvestigationGoodRepData { 041 protected FactionAPI faction; 042 protected FactionAPI other; 043 public InvestigationGoodRepData(FactionAPI faction, FactionAPI other) { 044 this.faction = faction; 045 this.other = other; 046 } 047 public InvestigationGoodRepData(String faction, String other) { 048 this.faction = Global.getSector().getFaction(faction); 049 this.other = Global.getSector().getFaction(other); 050 } 051 public FactionAPI getFaction() { 052 return faction; 053 } 054 public FactionAPI getOther() { 055 return other; 056 } 057 058 059 @Override 060 public int hashCode() { 061 final int prime = 31; 062 int result = 1; 063 result = prime * result 064 + ((faction == null) ? 0 : faction.hashCode()); 065 result = prime * result + ((other == null) ? 0 : other.hashCode()); 066 return result; 067 } 068 @Override 069 public boolean equals(Object obj) { 070 if (this == obj) 071 return true; 072 if (obj == null) 073 return false; 074 if (getClass() != obj.getClass()) 075 return false; 076 InvestigationGoodRepData other = (InvestigationGoodRepData) obj; 077 if (faction == null) { 078 if (other.faction != null) 079 return false; 080 } else if (faction != other.faction) 081 return false; 082 if (this.other == null) { 083 if (other.other != null) 084 return false; 085 } else if (this.other != other.other) 086 return false; 087 return true; 088 } 089 } 090 091 092 public static Logger log = Global.getLogger(InvestigationEventGoodRepWithOther.class); 093 094 private float elapsedDays = 0f; 095 private float duration = 0f; 096 097 private InvestigationGoodRepData target = null; 098 099 private float guiltProb = 0f; 100 private int bribeAmount = 1; 101 private boolean bribed = false; 102 private PersonAPI investigator; 103 private FactionAPI other; 104 private boolean ended = false; 105 private float numPrior; 106 private RepActions punishment = null; 107 108 public void init(String type, CampaignEventTarget eventTarget) { 109 super.init(type, eventTarget); 110 } 111 112 public void startEvent() { 113 super.startEvent(); 114 115 116 if (!(eventTarget.getCustom() instanceof InvestigationGoodRepData)) { 117 endEvent(); 118 return; 119 } 120 target = (InvestigationGoodRepData) eventTarget.getCustom(); 121 faction = target.faction; 122 other = target.other; 123 124 numPrior = faction.getMemoryWithoutUpdate().getFloat(MemFlags.MEMORY_KEY_NUM_GR_INVESTIGATIONS); 125 126 pickMarket(); 127 if (market == null) { 128 endEvent(); 129 return; 130 } 131 132 if (faction.isAtBest(Factions.PLAYER, RepLevel.HOSTILE) || 133 other.isAtBest(Factions.PLAYER, RepLevel.FAVORABLE) || 134 faction.isAtWorst(other, RepLevel.COOPERATIVE) || 135 !faction.getCustom().optBoolean(Factions.CUSTOM_INVESTIGATES_PLAYER_FOR_GOOD_REP) || 136 !other.getCustom().optBoolean(Factions.CUSTOM_WORTH_INVESTIGATING_FOR_GOOD_REP) || 137 faction == other) { 138 // shouldn't have gotten here, abort 139 endEvent(); 140 return; 141 } 142 143 144 float repFaction = faction.getRelationship(Factions.PLAYER); 145 float repOther = other.getRelationship(Factions.PLAYER); 146 RepLevel relFaction = faction.getRelationshipLevel(Factions.PLAYER); 147 RepLevel relOther = other.getRelationshipLevel(Factions.PLAYER); 148 149// switch (relOther) { 150// case WELCOMING: 151// guiltProb = 0.25f + numPrior * 0.1f; 152// punishment = RepActions.OTHER_FACTION_GOOD_REP_INVESTIGATION_MINOR; 153// break; 154// case FRIENDLY: 155// guiltProb = 0.5f + numPrior * 0.1f; 156// punishment = RepActions.OTHER_FACTION_GOOD_REP_INVESTIGATION_MAJOR; 157// break; 158// case COOPERATIVE: 159// guiltProb = 1f; 160// punishment = RepActions.OTHER_FACTION_GOOD_REP_INVESTIGATION_CRITICAL; 161// break; 162// } 163 switch ((int) numPrior) { 164 case 0: 165 guiltProb = 0.25f; 166 punishment = RepActions.OTHER_FACTION_GOOD_REP_INVESTIGATION_MINOR; 167 break; 168 case 1: 169 guiltProb = 0.5f; 170 punishment = RepActions.OTHER_FACTION_GOOD_REP_INVESTIGATION_MAJOR; 171 break; 172 default: 173 guiltProb = 1f; 174 punishment = RepActions.OTHER_FACTION_GOOD_REP_INVESTIGATION_CRITICAL; 175 break; 176 } 177 bribeAmount = (int) (10000 + (int)(10000 * (numPrior + guiltProb * 2f + (float) Math.random())) / 1000 * 1000); 178 179 180 duration = 60f + 30f * (float) Math.random(); 181 //duration = 1f; 182 183 184 log.info(String.format("Starting faction investigation at %s, %s -> %s", market.getName(), faction.getDisplayName(), other.getDisplayName())); 185 186 investigator = Global.getSector().getImportantPeople().getPerson(market.getFaction(), market, 187 PERSON_CHECKOUT_REASON, Ranks.CITIZEN, Ranks.POST_INVESTIGATOR).getPerson(); 188 market.getCommDirectory().addPerson(investigator); 189 190 investigator.getMemoryWithoutUpdate().set("$igr_eventRef", this, duration); 191 investigator.getMemoryWithoutUpdate().set("$igr_investigator", true, duration); 192 investigator.getMemoryWithoutUpdate().set("$igr_bribeAmount", "" + bribeAmount, duration); 193 investigator.getMemoryWithoutUpdate().set("$igr_bribeAmountDGS", Misc.getWithDGS(bribeAmount), duration); 194 Misc.setFlagWithReason(investigator.getMemoryWithoutUpdate(), 195 MemFlags.MEMORY_KEY_REQUIRES_DISCRETION, "igr", 196 true, duration); 197 198 Global.getSector().reportEventStage(this, "start_goodrep", null, MessagePriority.ENSURE_DELIVERY, null); 199 } 200 201 public void advance(float amount) { 202 if (!isEventStarted()) return; 203 if (isDone()) return; 204 205 float days = Global.getSector().getClock().convertToDays(amount); 206 elapsedDays += days; 207 208 if (elapsedDays >= duration) { 209 if (!bribed && 210 !other.isAtBest(Factions.PLAYER, RepLevel.FAVORABLE) && 211 (float) Math.random() < guiltProb) { 212 Global.getSector().reportEventStage(this, "player_guilty_goodrep", null, MessagePriority.ENSURE_DELIVERY, new BaseOnMessageDeliveryScript() { 213 public void beforeDelivery(CommMessageAPI message) { 214 if (punishment != null) { 215 Global.getSector().adjustPlayerReputation( 216 new RepActionEnvelope(punishment, null, null, true), 217 market.getFactionId()); 218 } 219 } 220 }); 221 } else { 222 if (bribed) { 223 Global.getSector().reportEventStage(this, "clear_goodrep_bribe", null, MessagePriority.ENSURE_DELIVERY, null); 224 } else { 225 Global.getSector().reportEventStage(this, "clear_goodrep", null, MessagePriority.ENSURE_DELIVERY, null); 226 } 227 } 228 numPrior++; 229 faction.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_NUM_GR_INVESTIGATIONS, numPrior); 230 endEvent(); 231 } 232 } 233 234 @Override 235 public String getEventName() { 236 if (isDone()) { 237 return other.getDisplayName() + " ties investigation - " + faction.getDisplayName() + " (over)"; 238 } 239 return other.getDisplayName() + " ties investigation - " + faction.getDisplayName() + ""; 240// if (isDone()) { 241// return faction.getDisplayName() + " investigation - " + other.getDisplayName() + " ties (over)"; 242// } 243// return faction.getDisplayName() + " investigation - " + other.getDisplayName() + " ties"; 244// if (isDone()) { 245// return "Faction Investigation - " + market.getName() + " (over)"; 246// } 247// return "Faction Investigation - " + market.getName(); 248 } 249 250 251 252 @Override 253 public boolean callEvent(String ruleId, InteractionDialogAPI dialog, 254 List<Token> params, Map<String, MemoryAPI> memoryMap) { 255 String action = params.get(0).getString(memoryMap); 256 257 CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet(); 258 CargoAPI cargo = playerFleet.getCargo(); 259 260 if (action.equals("paidBribe")) { 261 return bribed; 262 } else if (action.equals("setBribePaid")) { 263 bribed = true; 264 return true; 265 } 266 return true; 267 } 268 269 @Override 270 public Map<String, String> getTokenReplacements() { 271 Map<String, String> map = super.getTokenReplacements(); 272 273 map.put("$otherFaction", other.getDisplayName()); 274 map.put("$OtherFaction", Misc.ucFirst(other.getDisplayName())); 275 map.put("$TheOtherFaction", Misc.ucFirst(other.getDisplayNameWithArticle())); 276 map.put("$theOtherFaction", other.getDisplayNameWithArticle()); 277 map.put("$TheOtherFactionLong", Misc.ucFirst(other.getDisplayNameLongWithArticle())); 278 map.put("$theOtherFactionLong", other.getDisplayNameLongWithArticle()); 279 280 map.put("$InvestigatorPost", Misc.ucFirst(investigator.getPost())); 281 map.put("$investigatorName", investigator.getName().getFullName()); 282 if (investigator.isMale()) { 283 map.put("$invHimOrHer", "him"); 284 } else { 285 map.put("$invHimOrHer", "her"); 286 } 287 288 map.put("$sender", "Unknown"); 289 map.put("$duration", Misc.getAtLeastStringForDays((int)duration)); 290 291 return map; 292 } 293 294 public String[] getHighlights(String stageId) { 295 List<String> result = new ArrayList<String>(); 296 addTokensToList(result, "$duration"); 297 return result.toArray(new String[0]); 298 } 299 300 301 protected void endEvent() { 302 if (investigator != null) { 303 investigator.getMemoryWithoutUpdate().unset("$igr_eventRef"); 304 investigator.getMemoryWithoutUpdate().unset("$igr_investigator"); 305 investigator.getMemoryWithoutUpdate().unset("$igr_bribeAmount"); 306 investigator.getMemoryWithoutUpdate().unset("$igr_bribeAmountDGS"); 307 Misc.setFlagWithReason(investigator.getMemoryWithoutUpdate(), 308 MemFlags.MEMORY_KEY_REQUIRES_DISCRETION, "igr", 309 false, 0f); 310 311 Global.getSector().getImportantPeople().returnPerson(investigator, PERSON_CHECKOUT_REASON); 312 if (!Global.getSector().getImportantPeople().isCheckedOutForAnything(investigator)) { 313 market.getCommDirectory().removePerson(investigator); 314 } 315 } 316 ended = true; 317 } 318 319 public boolean isDone() { 320 return ended; 321 } 322 323 private void pickMarket() { 324 WeightedRandomPicker<MarketAPI> picker = new WeightedRandomPicker<MarketAPI>(); 325 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) { 326 if (market.getFaction() != faction) continue; 327 328 if (market.hasCondition(Conditions.DECIVILIZED)) continue; 329 if (market.getSize() < 5) continue; 330 331 float weight = market.getSize(); 332 333 picker.add(market, weight); 334 } 335 336 market = picker.pick(); 337 if (market == null) return; 338 //market = Global.getSector().getEconomy().getMarket("jangala"); 339 eventTarget.setEntity(market.getPrimaryEntity()); 340 eventTarget.setLocation(market.getContainingLocation()); 341 } 342} 343 344 345 346 347 348 349