1package com.fs.starfarer.api.impl;
3import java.util.ArrayList;
4import java.util.Iterator;
10import com.fs.starfarer.api.Global;
11import com.fs.starfarer.api.campaign.CampaignFleetAPI;
12import com.fs.starfarer.api.campaign.CargoAPI;
13import com.fs.starfarer.api.campaign.CargoStackAPI;
14import com.fs.starfarer.api.campaign.GenericPluginManagerAPI;
15import com.fs.starfarer.api.campaign.InteractionDialogAPI;
16import com.fs.starfarer.api.campaign.PlayerMarketTransaction;
17import com.fs.starfarer.api.campaign.SectorEntityToken;
18import com.fs.starfarer.api.campaign.econ.MarketAPI;
19import com.fs.starfarer.api.campaign.econ.SubmarketAPI;
20import com.fs.starfarer.api.campaign.listeners.CargoScreenListener;
21import com.fs.starfarer.api.campaign.listeners.ColonyInteractionListener;
22import com.fs.starfarer.api.campaign.listeners.CommodityIconProvider;
23import com.fs.starfarer.api.campaign.listeners.CommodityTooltipModifier;
24import com.fs.starfarer.api.campaign.listeners.GroundRaidObjectivesListener;
25import com.fs.starfarer.api.campaign.rules.MemoryAPI;
26import com.fs.starfarer.api.combat.MutableStat;
27import com.fs.starfarer.api.fleet.MutableFleetStatsAPI;
28import com.fs.starfarer.api.impl.campaign.CargoPodsEntityPlugin;
29import com.fs.starfarer.api.impl.campaign.graid.GroundRaidObjectivePlugin;
30import com.fs.starfarer.api.impl.campaign.ids.Commodities;
31import com.fs.starfarer.api.impl.campaign.ids.Stats;
32import com.fs.starfarer.api.impl.campaign.ids.Submarkets;
33import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD.RaidType;
34import com.fs.starfarer.api.ui.Alignment;
35import com.fs.starfarer.api.ui.LabelAPI;
36import com.fs.starfarer.api.ui.PositionAPI;
37import com.fs.starfarer.api.ui.TooltipMakerAPI;
38import com.fs.starfarer.api.util.Misc;
52 public static enum PersonnelRank {
53 REGULAR(
"Regular",
"icon_crew_green", 0.25f),
54 EXPERIENCED(
"Experienced",
"icon_crew_regular", 0.5f),
55 VETERAN(
"Veteran",
"icon_crew_veteran", 0.75f),
56 ELITE(
"Elite",
"icon_crew_elite", 1f),
59 public String iconKey;
60 public float threshold;
61 private PersonnelRank(String name, String iconKey,
float threshold) {
63 this.iconKey = iconKey;
64 this.threshold = threshold;
67 public static PersonnelRank getRankForXP(
float xp) {
70 for (PersonnelRank rank : values()) {
71 if (f < rank.threshold) {
75 return PersonnelRank.ELITE;
79 public static class CommodityIconProviderWrapper {
85 public static class CommodityDescriptionProviderWrapper {
86 public CargoStackAPI stack;
87 public CommodityDescriptionProviderWrapper(CargoStackAPI stack) {
92 public static class PersonnelData
implements Cloneable {
96 transient public float savedNum;
97 transient public float savedXP;
98 public PersonnelData(String
id) {
102 protected PersonnelData clone() {
104 PersonnelData copy = (PersonnelData) super.clone();
105 copy.savedNum = savedNum;
106 copy.savedXP = savedXP;
108 }
catch (CloneNotSupportedException e) {
109 throw new RuntimeException(e);
113 public void add(
int add) {
117 public void remove(
int remove,
boolean removeXP) {
120 if (
remove > num)
remove = (int) num;
121 if (removeXP) xp *= (num -
remove) / Math.max(1f, num);
125 xp = Math.min(xp, maxXP);
129 public void addXP(
float xp) {
132 this.xp = Math.min(this.xp, maxXP);
134 public void removeXP(
float xp) {
139 public float clampXP() {
142 this.xp = Math.min(this.xp, maxXP);
143 return Math.max(0f, prevXP - maxXP);
146 public void numMayHaveChanged(
float newNum,
boolean keepXP) {
153 xp *= newNum / Math.max(1f, num);
159 public float getXPLevel() {
160 float f = xp / Math.max(1f, num);
166 public PersonnelRank getRank() {
167 PersonnelRank rank = PersonnelRank.getRankForXP(getXPLevel());
171 public void integrateWithCurrentLocation(PersonnelAtEntity atLocation) {
173 int numTaken = (int) Math.round(num - savedNum);
174 if (atLocation !=
null) {
178 PersonnelData copy = atLocation.data;
181 }
else if (numTaken < 0) {
189 public static class PersonnelAtEntity
implements Cloneable {
190 public PersonnelData data;
191 public SectorEntityToken entity;
192 public String submarketId;
193 public PersonnelAtEntity(SectorEntityToken entity, String commodityId, String submarketId) {
194 this.entity = entity;
195 data =
new PersonnelData(commodityId);
196 this.submarketId = submarketId;
200 protected PersonnelAtEntity clone() {
202 PersonnelAtEntity copy = (PersonnelAtEntity) super.clone();
203 copy.data = data.clone();
205 }
catch (CloneNotSupportedException e) {
206 throw new RuntimeException(e);
212 public static final String
KEY =
"$core_personnelTracker";
224 protected List<PersonnelAtEntity>
droppedOff =
new ArrayList<PersonnelAtEntity>();
263 if (
pods ==
null && dialog !=
null) {
278 update(
false,
true,
null);
285 if (entity ==
null)
return;
296 if (!stack.isPersonnelStack())
continue;
297 if (stack.isMarineStack()) {
298 PersonnelAtEntity at =
getDroppedOffAt(stack.getCommodityId(), entity, sub,
true);
300 int num = (int) stack.getSize();
306 if (!stack.isPersonnelStack())
continue;
307 if (stack.isMarineStack()) {
308 PersonnelAtEntity at =
getDroppedOffAt(stack.getCommodityId(), entity, sub,
true);
310 int num = (int) stack.getSize();
319 public static void transferPersonnel(PersonnelData from, PersonnelData to,
int num, PersonnelData keepsXP) {
320 if (num > from.num) {
321 num = (int) from.num;
323 if (num <= 0)
return;
327 from.remove(num,
false);
329 float totalXP = to.xp + from.xp;
330 if (keepsXP == from) {
331 from.xp = Math.min(totalXP, from.num);
332 to.xp = Math.max(0f, totalXP - from.num);
333 }
else if (keepsXP == to) {
334 to.xp = Math.min(totalXP, to.num);
335 from.xp = Math.max(0f, totalXP - to.num);
338 float xp = from.xp * num / from.num;
343 from.remove(num,
true);
355 float total = marines + data.marinesLost;
356 float xpGain = 1f - data.raidEffectiveness;
359 if (xpGain < 0) xpGain = 0;
366 update(
false,
false,
null);
370 if (fleet ==
null)
return;
375 marineData.numMayHaveChanged(marines, keepXP);
377 if (withIntegrationFromCurrentLocation) {
380 marineData.integrateWithCurrentLocation(atLocation);
386 String
id =
"marineXP";
390 if (effectBonus > 0) {
397 if (casualtyReduction > 0) {
408 float f = data.getXPLevel();
413 float f = data.getXPLevel();
421 update(
true,
true, stack);
424 boolean nonPlayer =
false;
445 PersonnelRank rank = data.getRank();
457 info.
addPara(
"Regular marines - tough, competent, and disciplined.", opad);
459 info.
addPara(
"These marines are mostly regulars and have seen some combat, " +
460 "but are not, overall, accustomed to your style of command.", opad);
465 info.
addPara(
"Experienced marines with substantial training and a number of " +
466 "operations under their belts.", opad);
468 info.
addPara(
"You've led these marines on several operations, and " +
469 "the experience gained by both parties is beginning to show concrete benefits.", opad);
474 info.
addPara(
"These marines are veterans of many ground operations. " +
475 "Well-motivated and highly effective.", opad);
477 info.
addPara(
"These marines are veterans of many ground operations under your leadership; " +
478 "the command structure is well established and highly effective.", opad);
483 info.
addPara(
"These marines are an elite force, equipped, led, and motivated well " +
484 "above the standards of even the professional militaries in the Sector.", opad);
486 info.
addPara(
"These marines are an elite force, equipped, led, and motivated well " +
487 "above the standards of even the professional militaries in the Sector.", opad);
496 fake.
modifyPercentAlways(
"1", effectBonus,
"increased effectiveness of ground operations");
497 fake.
modifyPercentAlways(
"2", -casualtyReduction,
"reduction to marine casualties suffered during ground operations");
520 if (params instanceof CommodityIconProviderWrapper) {
521 CargoStackAPI stack = ((CommodityIconProviderWrapper) params).stack;
529 if (atLocation !=
null) {
547 update(
true,
true, stack);
548 PersonnelData data =
null;
555 if (atLocation !=
null) {
556 data = atLocation.data;
565 if (data ==
null || data.num <= 0) {
570 PersonnelRank rank = data.getRank();
615 if (withDroppedOff) {
616 Iterator<PersonnelAtEntity> iter =
droppedOff.iterator();
617 while (iter.hasNext()) {
618 PersonnelAtEntity pae = iter.next();
619 if (!pae.entity.isAlive() || pae.data.num <= 0 || pae.data.xp <= 0) {
629 if (dialog !=
null) {
644 if (stack.
getCargo() ==
null)
return null;
649 if (sub.getCargo() == stack.
getCargo()) {
657 String submarketId = sub ==
null ?
"" : sub.
getSpecId();
659 String otherSubmarketId = pae.submarketId ==
null ?
"" : pae.submarketId;
660 if (entity == pae.entity && commodityId.equals(pae.data.id) && submarketId.equals(otherSubmarketId)) {
665 if (submarketId.isEmpty()) submarketId =
null;
666 PersonnelAtEntity pae =
new PersonnelAtEntity(entity, commodityId, submarketId);
675 PersonnelAtEntity atLocation = entity ==
null ? null :
getDroppedOffAt(commodityId, entity, sub,
false);
static SettingsAPI getSettings()
static SectorAPI getSector()
SubmarketAPI getSubmarket()
void unmodifyMult(String source)
void modifyMult(String source, float value)
void modifyPercentAlways(String source, float value, String desc)
void modifyPercent(String source, float value)
void unmodifyPercent(String source)
transient PersonnelData savedMarineData
void reportSubmarketOpened(SubmarketAPI submarket)
static boolean KEEP_XP_DURING_TRANSFERS
SectorEntityToken getInteractionEntity()
static float XP_PER_RAID_MULT
void reportPlayerClosedMarket(MarketAPI market)
void addSectionAfterPrice(TooltipMakerAPI info, float width, boolean expanded, CargoStackAPI stack)
PlayerFleetPersonnelTracker()
void processTransaction(PlayerMarketTransaction transaction, SectorEntityToken entity)
transient SubmarketAPI currSubmarket
transient SectorEntityToken pods
static float MAX_LOSS_REDUCTION_PERCENT
PersonnelAtEntity getDroppedOffAt(String commodityId, SectorEntityToken entity, SubmarketAPI sub, boolean createIfNull)
static float MAX_EFFECTIVENESS_PERCENT
void modifyRaidObjectives(MarketAPI market, SectorEntityToken entity, List< GroundRaidObjectivePlugin > objectives, RaidType type, int marineTokens, int priority)
void reportCargoScreenOpened()
SubmarketAPI getSubmarketFor(CargoStackAPI stack)
static float getMarineEffectBonus(PersonnelData data)
static float getMarineLossesReductionPercent(PersonnelData data)
String getIconName(CargoStackAPI stack)
void reportRaidObjectivesAchieved(RaidResultData data, InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
void reportPlayerLeftCargoPods(SectorEntityToken entity)
PersonnelAtEntity getPersonnelAtLocation(String commodityId, SubmarketAPI sub)
int getHandlingPriority(Object params)
String getRankIconName(CargoStackAPI stack)
transient List< PersonnelAtEntity > savedPersonnelData
void reportPlayerOpenedMarketAndCargoUpdated(MarketAPI market)
void reportPlayerOpenedMarket(MarketAPI market)
void reportPlayerNonMarketTransaction(PlayerMarketTransaction transaction, InteractionDialogAPI dialog)
List< PersonnelAtEntity > getDroppedOff()
void update(boolean withIntegrationFromCurrentLocation, boolean keepXP, CargoStackAPI stack)
void doCleanup(boolean withDroppedOff)
static void transferPersonnel(PersonnelData from, PersonnelData to, int num, PersonnelData keepsXP)
PersonnelData getMarineData()
static PlayerFleetPersonnelTracker getInstance()
void reportPlayerMarketTransaction(PlayerMarketTransaction transaction)
List< PersonnelAtEntity > droppedOff
static final String MARINES
static final String PLANETARY_OPERATIONS_MOD
static final String PLANETARY_OPERATIONS_CASUALTIES_MULT
static final String SUBMARKET_STORAGE
static Color getBasePlayerColor()
static Color getHighlightColor()
static Color getDarkPlayerColor()
String getSpriteName(String category, String id)
MutableFleetStatsAPI getStats()
InteractionDialogAPI getCurrentInteractionDialog()
List< CargoStackAPI > getStacksCopy()
boolean isInPlayerCargo()
void addPlugin(GenericPlugin plugin)
SectorEntityToken getInteractionTarget()
CampaignFleetAPI getPlayerFleet()
GenericPluginManagerAPI getGenericPlugins()
CampaignUIAPI getCampaignUI()
MemoryAPI getMemoryWithoutUpdate()
ListenerManagerAPI getListenerManager()
CustomCampaignEntityPlugin getCustomPlugin()
List< SubmarketAPI > getSubmarketsCopy()
SectorEntityToken getPrimaryEntity()
void addListener(Object listener)
void set(String key, Object value)
DynamicStatsAPI getDynamic()
PositionAPI getPosition()
PositionAPI autoSizeToWidth(float width)
PositionAPI setSize(float width, float height)
MutableStat getStat(String id)
StatBonus getMod(String id)