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