1package com.fs.starfarer.api.impl.campaign;
4import java.util.ArrayList;
7import com.fs.starfarer.api.Global;
8import com.fs.starfarer.api.campaign.CampaignFleetAPI;
9import com.fs.starfarer.api.campaign.FactionAPI;
10import com.fs.starfarer.api.campaign.RepLevel;
11import com.fs.starfarer.api.campaign.ReputationActionResponsePlugin;
12import com.fs.starfarer.api.campaign.SectorEntityToken;
13import com.fs.starfarer.api.campaign.TextPanelAPI;
14import com.fs.starfarer.api.campaign.comm.CommMessageAPI;
15import com.fs.starfarer.api.campaign.comm.MessageParaAPI;
16import com.fs.starfarer.api.campaign.comm.MessageSectionAPI;
17import com.fs.starfarer.api.campaign.econ.MarketAPI;
18import com.fs.starfarer.api.characters.PersonAPI;
19import com.fs.starfarer.api.characters.RelationshipAPI;
20import com.fs.starfarer.api.impl.campaign.ids.Factions;
21import com.fs.starfarer.api.impl.campaign.ids.Tags;
22import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
23import com.fs.starfarer.api.impl.campaign.intel.MessageIntel;
24import com.fs.starfarer.api.ui.LabelAPI;
25import com.fs.starfarer.api.ui.TooltipMakerAPI;
26import com.fs.starfarer.api.util.Misc;
30 public static class MissionCompletionRep {
31 public float successDelta;
33 public float failureDelta;
35 public MissionCompletionRep(
float successDelta,
RepLevel successLimit,
36 float failureDelta,
RepLevel failureLimit) {
37 this.successDelta = successDelta;
38 this.successLimit = successLimit;
39 this.failureDelta = failureDelta;
40 this.failureLimit = failureLimit;
45 public static class RepActionEnvelope {
46 public RepActions action;
47 public Object param =
null;
50 public boolean addMessageOnNoChange =
true;
51 public boolean withMessage =
true;
53 public RepActionEnvelope(RepActions action, Object param) {
57 public RepActionEnvelope(RepActions action) {
66 public RepActionEnvelope(RepActions action, Object param,
CommMessageAPI message,
TextPanelAPI textPanel,
boolean addMessageOnNoChange) {
67 this(action, param, message, textPanel, addMessageOnNoChange,
true);
69 public RepActionEnvelope(RepActions action, Object param,
TextPanelAPI textPanel,
boolean addMessageOnNoChange) {
70 this(action, param,
null, textPanel, addMessageOnNoChange,
true);
72 public RepActionEnvelope(RepActions action, Object param,
CommMessageAPI message,
TextPanelAPI textPanel,
boolean addMessageOnNoChange,
boolean withMessage) {
73 this(action, param, message, textPanel, addMessageOnNoChange, withMessage,
null);
75 public RepActionEnvelope(RepActions action, Object param,
TextPanelAPI textPanel,
boolean addMessageOnNoChange,
boolean withMessage) {
76 this(action, param,
null, textPanel, addMessageOnNoChange, withMessage,
null);
78 public RepActionEnvelope(RepActions action, Object param,
TextPanelAPI textPanel,
boolean addMessageOnNoChange,
boolean withMessage, String reason) {
79 this(action, param,
null, textPanel, addMessageOnNoChange, withMessage, reason);
81 public RepActionEnvelope(RepActions action, Object param,
CommMessageAPI message,
TextPanelAPI textPanel,
boolean addMessageOnNoChange,
boolean withMessage, String reason) {
84 this.message = message;
85 this.addMessageOnNoChange = addMessageOnNoChange;
86 this.textPanel = textPanel;
87 this.withMessage = withMessage;
90 public RepActionEnvelope(RepActions action, Object param,
TextPanelAPI textPanel) {
93 this.textPanel = textPanel;
97 public static class CustomRepImpact {
98 public float delta = 0;
100 public RepLevel ensureAtBest =
null;
101 public RepLevel ensureAtWorst =
null;
102 public RepLevel requireAtBest =
null;
103 public RepLevel requireAtWorst =
null;
106 public static enum RepActions {
107 COMBAT_NO_DAMAGE_ESCAPE,
113 COMBAT_AGGRESSIVE_TOFF,
117 COMBAT_HELP_CRITICAL,
119 COMBAT_FRIENDLY_FIRE,
121 FOOD_SHORTAGE_PLAYER_ENDED_FAST,
122 FOOD_SHORTAGE_PLAYER_ENDED_NORMAL,
124 SYSTEM_BOUNTY_REWARD,
125 PERSON_BOUNTY_REWARD,
132 OTHER_FACTION_GOOD_REP_INVESTIGATION_MINOR,
133 OTHER_FACTION_GOOD_REP_INVESTIGATION_MAJOR,
134 OTHER_FACTION_GOOD_REP_INVESTIGATION_CRITICAL,
136 SMUGGLING_INVESTIGATION_GUILTY,
137 COMM_SNIFFER_INVESTIGATION_GUILTY,
138 FOOD_INVESTIGATION_GUILTY,
139 FOOD_INVESTIGATION_GUILTY_MAJOR,
141 CAUGHT_INSTALLING_SNIFFER,
143 CUSTOMS_NOTICED_EVADING,
144 CUSTOMS_CAUGHT_SMUGGLING,
145 CUSTOMS_REFUSED_TOLL,
146 CUSTOMS_REFUSED_FINE,
147 CUSTOMS_COULD_NOT_AFFORD,
154 TRANSPONDER_OFF_REFUSE,
161 MAKE_SUSPICOUS_AT_WORST,
163 MAKE_HOSTILE_AT_BEST,
165 COMMISSION_BOUNTY_REWARD,
167 COMMISSION_NEUTRAL_BATTLE_PENALTY,
168 COMMISSION_PENALTY_HOSTILE_TO_NON_ENEMY,
186 public static class RepRewards {
187 public static final float TINY = 0.01f;
188 public static final float SMALL = 0.02f;
189 public static final float MEDIUM = 0.03f;
190 public static final float HIGH = 0.05f;
191 public static final float VERY_HIGH = 0.07f;
192 public static final float EXTREME = 0.1f;
201 if (faction ==
null)
return new ReputationAdjustmentResult(0);
215 if (!(actionObject instanceof RepActionEnvelope) && !(actionObject instanceof RepActions)) {
216 return new ReputationAdjustmentResult(0);
220 return new ReputationAdjustmentResult(0);
228 RepActions action =
null;
229 String reason =
null;
233 boolean withMessage =
true;
234 boolean addMessageOnNoChange =
true;
235 if (actionObject instanceof RepActions) {
236 action = (RepActions) actionObject;
238 }
else if (actionObject instanceof RepActionEnvelope) {
239 RepActionEnvelope envelope = (RepActionEnvelope) actionObject;
240 action = envelope.action;
241 param = envelope.param;
242 message = envelope.message;
243 panel = envelope.textPanel;
244 addMessageOnNoChange = envelope.addMessageOnNoChange;
245 withMessage = envelope.withMessage;
246 reason = envelope.reason;
258 if (action == RepActions.CUSTOM) {
259 if (!(param instanceof CustomRepImpact)) {
260 throw new RuntimeException(
"For RepActions.CUSTOM, use CustomRepImpact as a param in a RepActionEnvelope");
263 CustomRepImpact impact = (CustomRepImpact) param;
265 delta = impact.delta;
266 limit = impact.limit;
267 ensureAtBest = impact.ensureAtBest;
268 ensureAtWorst = impact.ensureAtWorst;
269 requireAtBest = impact.requireAtBest;
270 requireAtWorst = impact.requireAtWorst;
274 case COMBAT_HELP_MINOR:
275 delta = RepRewards.TINY;
279 case COMBAT_HELP_MAJOR:
280 delta = RepRewards.MEDIUM;
284 case COMBAT_HELP_CRITICAL:
285 delta = RepRewards.HIGH;
297 case COMBAT_FRIENDLY_FIRE:
298 float fpHull = (float) Math.ceil((Float) param);
303 delta = -1f * fpHull * 0.01f;
306 delta = -RepRewards.MEDIUM;
310 case COMBAT_AGGRESSIVE:
311 delta = -RepRewards.HIGH;
315 case COMBAT_NORMAL_TOFF:
316 delta = -RepRewards.MEDIUM;
319 case COMBAT_AGGRESSIVE_TOFF:
320 delta = -RepRewards.HIGH;
323 case FOOD_SHORTAGE_PLAYER_ENDED_FAST:
324 delta = getRepRewardForFoodShortage(action, (
MarketAPI) param);
328 case FOOD_SHORTAGE_PLAYER_ENDED_NORMAL:
329 delta = getRepRewardForFoodShortage(action, (
MarketAPI) param);
333 case SYSTEM_BOUNTY_REWARD:
334 float fp = (Float) param;
336 delta = RepRewards.SMALL;
338 }
else if (fp < 30) {
339 delta = RepRewards.MEDIUM;
342 delta = RepRewards.HIGH;
347 case PERSON_BOUNTY_REWARD:
348 delta = RepRewards.MEDIUM;
352 case COMBAT_WITH_ENEMY:
355 delta = RepRewards.TINY;
357 }
else if (fp < 30) {
358 delta = RepRewards.SMALL;
361 delta = RepRewards.MEDIUM;
367 delta = (Float) param * 0.01f;
376 case SMUGGLING_EFFECT:
377 delta = -(Float) param * 0.01f;
380 case TRADE_WITH_ENEMY:
381 delta = -(Float) param * 0.01f;
384 case SMUGGLING_INVESTIGATION_GUILTY:
385 delta = -RepRewards.HIGH;
389 case OTHER_FACTION_GOOD_REP_INVESTIGATION_MINOR:
390 delta = -RepRewards.HIGH;
393 case OTHER_FACTION_GOOD_REP_INVESTIGATION_MAJOR:
394 delta = -RepRewards.HIGH;
398 case OTHER_FACTION_GOOD_REP_INVESTIGATION_CRITICAL:
399 delta = -RepRewards.HIGH;
403 case CAUGHT_INSTALLING_SNIFFER:
404 delta = -RepRewards.TINY;
407 case COMM_SNIFFER_INVESTIGATION_GUILTY:
408 delta = -RepRewards.SMALL;
411 case FOOD_INVESTIGATION_GUILTY:
412 delta = -RepRewards.HIGH;
415 case FOOD_INVESTIGATION_GUILTY_MAJOR:
416 delta = -RepRewards.HIGH;
420 case CUSTOMS_NOTICED_EVADING:
421 delta = -RepRewards.MEDIUM;
424 case CUSTOMS_CAUGHT_SMUGGLING:
425 delta = -(Float) param * 0.01f;
428 case CUSTOMS_REFUSED_TOLL:
429 delta = -RepRewards.MEDIUM;
432 case CUSTOMS_REFUSED_FINE:
433 delta = -RepRewards.VERY_HIGH;
436 case CUSTOMS_COULD_NOT_AFFORD:
437 delta = -RepRewards.SMALL;
441 delta = RepRewards.TINY;
444 case REP_DECAY_POSITIVE:
449 case MISSION_SUCCESS:
450 MissionCompletionRep rep = (MissionCompletionRep) param;
451 delta = rep.successDelta;
452 limit = rep.successLimit;
454 case MISSION_FAILURE:
455 rep = (MissionCompletionRep) param;
456 delta = rep.failureDelta;
457 limit = rep.failureLimit;
459 case TRANSPONDER_OFF:
460 if (person !=
null) {
461 delta = -RepRewards.MEDIUM;
463 delta = -RepRewards.SMALL;
467 case TRANSPONDER_OFF_REFUSE:
468 case CARGO_SCAN_REFUSE:
469 if (person !=
null) {
470 delta = -RepRewards.HIGH;
472 delta = -RepRewards.MEDIUM;
476 case COMMISSION_ACCEPT:
477 delta = RepRewards.HIGH;
479 case SHRINE_OFFERING:
480 delta = RepRewards.MEDIUM;
484 delta = -RepRewards.TINY;
487 case MAKE_HOSTILE_AT_BEST:
491 case MAKE_SUSPICOUS_AT_WORST:
495 case COMMISSION_BOUNTY_REWARD:
498 delta = RepRewards.TINY;
500 }
else if (fp < 50) {
501 delta = RepRewards.SMALL;
504 delta = RepRewards.MEDIUM;
508 case COMMISSION_PENALTY_HOSTILE_TO_NON_ENEMY:
512 delta = -RepRewards.TINY;
513 }
else if (fp < 50) {
514 delta = -RepRewards.SMALL;
516 delta = -RepRewards.MEDIUM;
522 if (delta < 0 && delta > -0.01f) delta = -0.01f;
523 if (delta > 0 && delta < 0.01f) delta = 0.01f;
524 delta = Math.round(delta * 100f) / 100f;
533 float deltaSign = Math.signum(delta);
535 float before = delegate.
getRel();
537 if (ensureAtBest !=
null) {
540 if (ensureAtWorst !=
null) {
544 if ((requireAtBest ==
null || curr.
isAtBest(requireAtBest)) &&
545 (requireAtWorst ==
null || curr.
isAtWorst(requireAtWorst))) {
550 float after = delegate.
getRel();
551 delta = after - before;
555 if (Math.abs(delta) >= 0.005f) {
557 }
else if (deltaSign != 0 && addMessageOnNoChange) {
558 addNoChangeMessage(deltaSign, faction, person, message, panel,
null,
null,
true, 0f, reason);
563 if (person ==
null) {
570 return new ReputationAdjustmentResult(delta);
574 private float getRepRewardForFoodShortage(RepActions action,
MarketAPI market) {
575 float mult = (float) market.
getSize() / 10f + 0.5f;
578 case FOOD_SHORTAGE_PLAYER_ENDED_NORMAL:
579 delta = RepRewards.MEDIUM;
581 case FOOD_SHORTAGE_PLAYER_ENDED_FAST:
582 delta = RepRewards.HIGH;
601 addNoChangeMessage(deltaSign, faction, person, message, panel, info, tc, withCurrent, pad,
null);
604 TooltipMakerAPI info, Color tc,
boolean withCurrent,
float pad, String reason) {
621 if (person !=
null) {
628 String standing =
"" + repInt +
"/100" +
" (" + level.
getDisplayName().toLowerCase() +
")";
633 String text =
"Your relationship with " + targetName +
634 ", currently at " + standing +
", is already well-established and is not affected by your recent actions";
636 if (panel ==
null && info ==
null) {
642 if (person ==
null) {
643 intel.
addLine(
"Relationship with " + targetName +
" not affected",
null,
644 new String[] {targetNameHighlight},
650 intel.
addLine(
"Relationship with " + targetName +
" not affected");
662 if (target !=
null) {
672 if (message !=
null) {
673 text = text.replaceAll(
" by your recent actions",
" by this.");
674 appendToSection2(text, message);
676 new String [] {standing},
677 new Color [] {relColor});
680 if (person ==
null) {
689 text = text.replaceAll(
" by your recent actions",
"");
690 printToTextPanel(panel, text,
691 new String [] {standing},
692 new Color [] {relColor});
697 if (person ==
null) {
698 LabelAPI label = info.
addPara(
"Relationship with " + targetName +
" not affected", tc, pad);
701 if (withCurrent) info.
addPara(
"Currently at %s", 0f, tc, relColor, standing);
703 LabelAPI label = info.
addPara(
"Relationship with " + targetName +
" not affected", tc, pad);
704 if (withCurrent) info.
addPara(
"Currently at %s", 0f, tc, relColor, standing);
725 if (person !=
null) {
732 String standing =
"" + repInt +
"/100" +
" (" + level.
getDisplayName().toLowerCase() +
")";
734 String text =
"Current standing with " + targetName +
735 " is " + standing +
"";
738 printToTextPanel(panel, text,
739 new String [] {targetNameHighlight, standing},
740 new Color [] {factionColor, relColor});
748 if (person ==
null) {
750 " is %s" + end, pad, tc, relColor, standing);
755 " is %s" + end, pad, tc, relColor, standing);
767 float rel = level.
getMin() + 0.01f;
784 if (person !=
null) {
790 String standing =
"" + repInt +
"/100" +
" (" + level.
getDisplayName().toLowerCase() +
")";
792 String mid =
"or better";
796 String text =
"Requires " + standing +
" " + mid +
" standing with " + targetName;
799 printToTextPanel(panel, text,
800 new String [] {standing, targetNameHighlight},
801 new Color [] {relColor, factionColor});
809 if (person ==
null) {
810 LabelAPI label = info.
addPara(
"Requires %s " + mid +
" standing with " + targetName + end,
811 pad, tc, relColor, standing);
815 LabelAPI label = info.
addPara(
"Requires %s " + mid +
" standing with " + targetName + end,
816 pad, tc, relColor, standing);
849 int deltaInt = (int) Math.round((Math.abs(delta) * 100f));
850 String targetName =
null;
851 String targetNameHighlight =
null;
852 Color relColor =
null;
855 if (faction !=
null) {
867 if (person !=
null) {
874 String standing =
"" + repInt +
"/100" +
" (" + level.
getDisplayName().toLowerCase() +
")";
880 Color factionColor =
null;
884 String deltaString =
"improved by " + deltaInt;
885 if (Math.abs(delta) <= 0.0049f || deltaInt == 0) {
886 deltaString =
"not affected";
888 }
else if (delta < 0) {
890 deltaString =
"reduced by " + deltaInt;
893 text =
"Relationship with " + targetName +
" " + deltaString +
", currently at " + standing +
"";
895 if (panel ==
null && info ==
null) {
901 if (person ==
null) {
902 intel.
addLine(
"Relationship with " + targetName +
" " + deltaString,
null,
903 new String[] {targetNameHighlight, deltaString},
904 factionColor, deltaColor);
909 intel.
addLine(
"Relationship with " + targetName +
" " + deltaString,
null,
910 new String[] {deltaString},
922 if (message !=
null) {
924 appendToSection2(text, message);
927 new String [] {deltaString, standing},
928 new Color [] {deltaColor, relColor});
931 if (person ==
null) {
940 printToTextPanel(panel, text,
941 new String [] {deltaString, standing},
942 new Color [] {deltaColor, relColor});
947 if (person ==
null) {
963 LabelAPI label = info.
addPara(
"Relationship with " + targetName +
" " + deltaString, tc, pad);
967 if (withCurrent) info.
addPara(
"Currently at %s", 0f, tc, relColor, standing);
970 LabelAPI label = info.
addPara(
"Relationship with " + targetName +
" " + deltaString, tc, pad);
973 if (withCurrent) info.
addPara(
"Currently at %s", 0f, tc, relColor, standing);
978 private static void printToTextPanel(
TextPanelAPI panel, String text, String [] highlights, Color [] colors) {
987 private static void appendToSectionHighlights(MessageSectionAPI section, String [] strings, Color [] colors) {
988 String [] currStrings = section.getHighlights();
989 Color [] currColors = section.getHighlightColors();
990 if (currStrings ==
null) {
991 section.setHighlights(strings);
992 section.setHighlightColors(colors);
994 List<String> stringList =
new ArrayList<String>();
995 for (String s : currStrings) stringList.add(s);
996 for (String s : strings) stringList.add(s);
998 List<Color> colorList =
new ArrayList<Color>();
999 for (Color s : currColors) colorList.add(s);
1000 for (Color s : colors) colorList.add(s);
1002 section.setHighlights(stringList.toArray(
new String [0]));
1003 section.setHighlightColors(colorList.toArray(
new Color [0]));
1007 private static void appendToSection2(String text, CommMessageAPI message) {
1008 List<MessageParaAPI> body = message.getSection2().getBody();
1009 if (body.isEmpty()) {
1010 message.getSection2().addPara(text);
1012 MessageParaAPI lastPara = body.get(body.size() - 1);
1013 String str = lastPara.getBody();
1014 str = str +
"\n\n" + text;
1015 lastPara.setBody(str);
static SettingsAPI getSettings()
static FactoryAPI getFactory()
static SectorAPI getSector()
ReputationAdjustmentResult handlePlayerReputationActionInner(Object actionObject, String factionId, PersonAPI person, RelationshipAPI delegate)
static void addRequiredStanding(FactionAPI faction, RepLevel req, PersonAPI person, TextPanelAPI panel, TooltipMakerAPI info, Color tc, float pad, boolean orBetter)
static void addNoChangeMessage(float deltaSign, FactionAPI faction, PersonAPI person, CommMessageAPI message, TextPanelAPI panel, TooltipMakerAPI info, Color tc, boolean withCurrent, float pad, String reason)
static void addNoChangeMessage(float deltaSign, FactionAPI faction, PersonAPI person, CommMessageAPI message, TextPanelAPI panel, TooltipMakerAPI info, Color tc, boolean withCurrent, float pad)
static void addAdjustmentMessage(float delta, FactionAPI faction, PersonAPI person, TextPanelAPI panel, TooltipMakerAPI info, Color tc, boolean withCurrent, float pad)
ReputationAdjustmentResult handlePlayerReputationAction(Object action, final String factionId)
static void addCurrentStanding(FactionAPI faction, PersonAPI person, TextPanelAPI panel, TooltipMakerAPI info, Color tc, float pad)
static void addAdjustmentMessage(float delta, FactionAPI faction, PersonAPI person, TextPanelAPI panel, TooltipMakerAPI info, Color tc, boolean withCurrent, float pad, String reason)
static void addAdjustmentMessage(float delta, FactionAPI faction, PersonAPI person, CommMessageAPI message, TextPanelAPI panel, TooltipMakerAPI info, Color tc, boolean withCurrent, float pad, String reason)
static void addAdjustmentMessage(float delta, FactionAPI faction, PersonAPI person, CommMessageAPI message, TextPanelAPI panel, TooltipMakerAPI info, Color tc, boolean withCurrent, float pad)
ReputationAdjustmentResult handlePlayerReputationAction(Object action, PersonAPI person)
static void addDeltaMessage(float delta, FactionAPI faction, PersonAPI person, TextPanelAPI panel, TooltipMakerAPI info, Color tc, boolean withCurrent, float pad)
static final String NEUTRAL
static final String PLAYER
static final String INDEPENDENT
static final String BULLET
void setIcon(String icon)
void addLine(String text)
static Color getNegativeHighlightColor()
static int getRepInt(float f)
boolean isAtWorst(RepLevel level)
boolean isAtBest(RepLevel level)
Color getColor(String id)
void addMessage(String text)
String getDisplayNameWithArticle()
RelationshipAPI getRelToPlayer()
float getRelationship(String id)
String getDisplayNameLongWithArticle()
RepLevel getRelationshipLevel(FactionAPI faction)
Color getRelColor(String otherFactionId)
String getDisplayNameLong()
SectorEntityToken getInteractionTarget()
CampaignFleetAPI getPlayerFleet()
FactionAPI getPlayerFaction()
CampaignUIAPI getCampaignUI()
FactionAPI getFaction(String factionId)
PersonAPI getPlayerPerson()
void reportPlayerReputationChange(String faction, float delta)
PersonAPI getActivePerson()
void setHighlightColorsInLastPara(Color ...colors)
void setFontSmallInsignia()
LabelAPI addParagraph(String text)
InteractionDialogAPI getDialog()
void highlightInLastPara(Color color, String ...strings)
static final String MESSAGE_PERSON_ID_KEY
MessageSectionAPI getSection2()
static final String MESSAGE_FACTION_ID_KEY
Map< String, Object > getCustomMap()
String getPortraitSprite()
RelationshipAPI getRelToPlayer()
boolean ensureAtWorst(RepLevel level)
boolean adjustRelationship(float delta, RepLevel limit)
RelationshipTarget getTarget()
boolean ensureAtBest(RepLevel level)
void setHighlight(int start, int end)
void setHighlightColors(Color ... colors)