1package com.fs.starfarer.api.impl.campaign.events;
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.HashSet;
6import java.util.Iterator;
9import java.util.Random;
14import org.apache.log4j.Logger;
16import com.fs.starfarer.api.EveryFrameScript;
17import com.fs.starfarer.api.Global;
18import com.fs.starfarer.api.campaign.CampaignClockAPI;
19import com.fs.starfarer.api.campaign.CampaignFleetAPI;
20import com.fs.starfarer.api.campaign.CargoAPI;
21import com.fs.starfarer.api.campaign.FactionAPI;
22import com.fs.starfarer.api.campaign.InteractionDialogAPI;
23import com.fs.starfarer.api.campaign.PlayerMarketTransaction;
24import com.fs.starfarer.api.campaign.TextPanelAPI;
25import com.fs.starfarer.api.campaign.econ.MarketAPI;
26import com.fs.starfarer.api.campaign.listeners.ColonyInteractionListener;
27import com.fs.starfarer.api.campaign.rules.MemoryAPI;
28import com.fs.starfarer.api.characters.AdminData;
29import com.fs.starfarer.api.characters.FullName.Gender;
30import com.fs.starfarer.api.characters.MutableCharacterStatsAPI;
31import com.fs.starfarer.api.characters.MutableCharacterStatsAPI.SkillLevelAPI;
32import com.fs.starfarer.api.characters.OfficerDataAPI;
33import com.fs.starfarer.api.characters.PersonAPI;
34import com.fs.starfarer.api.characters.SkillSpecAPI;
35import com.fs.starfarer.api.impl.campaign.ids.Factions;
36import com.fs.starfarer.api.impl.campaign.ids.Personalities;
37import com.fs.starfarer.api.impl.campaign.ids.Ranks;
38import com.fs.starfarer.api.impl.campaign.ids.Skills;
39import com.fs.starfarer.api.impl.campaign.ids.Stats;
40import com.fs.starfarer.api.impl.campaign.ids.Tags;
41import com.fs.starfarer.api.impl.campaign.rulecmd.AddRemoveCommodity;
42import com.fs.starfarer.api.impl.campaign.rulecmd.CallEvent.CallableEvent;
43import com.fs.starfarer.api.plugins.OfficerLevelupPlugin;
44import com.fs.starfarer.api.util.IntervalUtil;
45import com.fs.starfarer.api.util.Misc;
46import com.fs.starfarer.api.util.Misc.Token;
47import com.fs.starfarer.api.util.TimeoutTracker;
48import com.fs.starfarer.api.util.WeightedRandomPicker;
60 public static class AvailableOfficer {
62 public String marketId;
63 public int hiringBonus;
65 public float timeRemaining = 0f;
66 public AvailableOfficer(
PersonAPI person, String marketId,
int hiringBonus,
int salary) {
68 this.marketId = marketId;
69 this.hiringBonus = hiringBonus;
79 protected List<AvailableOfficer>
available =
new ArrayList<AvailableOfficer>();
80 protected List<AvailableOfficer>
availableAdmins =
new ArrayList<AvailableOfficer>();
91 Object readResolve() {
125 log.info(
" officerProb: " + officerProb);
126 log.info(
" additionalProb: " + additionalProb);
127 log.info(
" mercProb: " + mercProb);
128 log.info(
" adminProb: " + adminProb);
142 if (random.nextFloat() < officerProb) {
143 boolean merc = random.nextFloat() < mercProb;
148 officer.timeRemaining = dur;
150 log.info(
"Added officer at " + officer.marketId +
"");
152 if (random.nextFloat() < officerProb * additionalProb) {
153 merc = random.nextFloat() < mercProb;
157 officer.timeRemaining = dur;
159 log.info(
"Added officer at [" + officer.marketId +
"]");
163 if (random.nextFloat() < adminProb) {
165 officer.timeRemaining = dur;
169 log.info(
"Added admin at [" + officer.marketId +
"]");
174 return 60f + 60f * random.nextFloat();
192 for (AvailableOfficer curr :
new ArrayList<AvailableOfficer>(
available)) {
193 curr.timeRemaining -= interval;
194 if (curr.timeRemaining <= 0) {
196 log.info(
"Removed officer from [" + curr.marketId +
"]");
199 for (AvailableOfficer curr :
new ArrayList<AvailableOfficer>(
availableAdmins)) {
200 curr.timeRemaining -= interval;
201 if (curr.timeRemaining <= 0) {
203 log.info(
"Removed freelance admin from [" + curr.marketId +
"]");
211 for (AvailableOfficer curr :
new ArrayList<AvailableOfficer>(
available)) {
216 for (AvailableOfficer curr :
new ArrayList<AvailableOfficer>(
availableAdmins)) {
224 if (officer ==
null)
return;
232 if (officer ==
null)
return;
241 if (
market ==
null)
return;
252 if (officer ==
null)
return;
276 Set<String> exclude =
new HashSet<String>();
280 exclude.add(od.getPerson().getPortraitSprite());
284 exclude.add(ad.getPerson().getPortraitSprite());
287 if (exclude.contains(p))
continue;
293 return picker.
pick();
302 if (
market ==
null)
return null;
305 tierPicker.
add(0, 60);
306 tierPicker.
add(1, 40);
308 int tier = tierPicker.
pick();
313 String hireKey =
"adminHireTier" + tier;
318 AvailableOfficer result =
new AvailableOfficer(person,
market.
getId(), hiringBonus, salary);
323 if (random ==
null) random =
new Random();
329 for (String skillId : allSkillIds) {
339 for (
int i = 0; i < tier && !picker.
isEmpty(); i++) {
354 String personality = personalityPicker.
pick();
372 if (
market ==
null)
return null;
377 if ((
float) Math.random() > 0.75f) level = 2;
387 level = minLevel +
Misc.
random.nextInt(maxLevel + 1 - minLevel);
390 if (level == maxLevel) numElite = 2;
406 AvailableOfficer result =
new AvailableOfficer(person,
market.
getId(),
413 null,
false,
false, -1, random);
426 SkillPickPreference pref = SkillPickPreference.ANY;
428 null,
true,
true, numElite, random);
432 public static enum SkillPickPreference {
441 YES_ENERGY_YES_BALLISTIC_YES_MISSILE_YES_DEFENSE,
442 YES_ENERGY_YES_BALLISTIC_NO_MISSILE_YES_DEFENSE,
443 YES_ENERGY_YES_BALLISTIC_YES_MISSILE_NO_DEFENSE,
444 YES_ENERGY_YES_BALLISTIC_NO_MISSILE_NO_DEFENSE,
445 YES_ENERGY_NO_BALLISTIC_YES_MISSILE_YES_DEFENSE,
446 YES_ENERGY_NO_BALLISTIC_NO_MISSILE_YES_DEFENSE,
447 YES_ENERGY_NO_BALLISTIC_YES_MISSILE_NO_DEFENSE,
448 YES_ENERGY_NO_BALLISTIC_NO_MISSILE_NO_DEFENSE,
449 NO_ENERGY_YES_BALLISTIC_YES_MISSILE_YES_DEFENSE,
450 NO_ENERGY_YES_BALLISTIC_NO_MISSILE_YES_DEFENSE,
451 NO_ENERGY_YES_BALLISTIC_YES_MISSILE_NO_DEFENSE,
452 NO_ENERGY_YES_BALLISTIC_NO_MISSILE_NO_DEFENSE,
453 NO_ENERGY_NO_BALLISTIC_YES_MISSILE_YES_DEFENSE,
454 NO_ENERGY_NO_BALLISTIC_NO_MISSILE_YES_DEFENSE,
455 NO_ENERGY_NO_BALLISTIC_YES_MISSILE_NO_DEFENSE,
456 NO_ENERGY_NO_BALLISTIC_NO_MISSILE_NO_DEFENSE,
465 null,
false,
true, -1,
null);
471 public static boolean DEBUG =
false;
473 SkillPickPreference pref,
boolean allowNonDoctrinePersonality,
475 boolean withEliteSkills,
int eliteSkillsNumOverride, Random random) {
476 if (random ==
null) random =
new Random();
484 if (!allowAnyLevel) {
490 if (
DEBUG) System.out.println(
"Generating officer\n");
493 Iterator<String> iter = fixedSkills.iterator();
494 while (iter.hasNext()) {
495 String
id = iter.next();
503 Collections.shuffle(fixedSkills, random);
507 for (
int i = 0; i < 1; i++) {
509 String skillId =
pickSkill(person, skills, pref, numSpec, random);
510 if (!fixedSkills.isEmpty()) {
511 skillId = fixedSkills.remove(0);
513 if (skillId !=
null) {
514 if (
DEBUG) System.out.println(
"Picking initial skill: " + skillId);
527 officerData.
addXP(xp,
null,
false);
533 while (officerData.
canLevelUp(allowAnyLevel)) {
535 if (!fixedSkills.isEmpty()) {
536 skillId = fixedSkills.remove(0);
538 if (skillId !=
null) {
539 if (
DEBUG) System.out.println(
"Leveling up " + skillId);
540 officerData.
levelUp(skillId, random);
544 if (allowAnyLevel && officerData.
getSkillPicks().isEmpty()) {
552 if (withEliteSkills && eliteSkillsNumOverride != 0) {
553 int num = eliteSkillsNumOverride;
564 if (
DEBUG) System.out.println(
"Done\n");
571 if (allowNonDoctrinePersonality) {
579 String personality = personalityPicker.
pick();
590 if (num <= 0)
return;
595 if (sl.getSkill().isAptitudeEffect())
continue;
596 if (!sl.getSkill().isCombatOfficerSkill())
continue;
597 picker.
add(sl.getSkill().getId(), 1f);
600 for (
int i = 0; i < num && !picker.
isEmpty(); i++) {
603 if (
DEBUG) System.out.println(
"Making skill elite: " +
id);
609 public static String
pickSkill(
PersonAPI person, List<String> skills, SkillPickPreference pref,
int numSpec, Random random) {
610 if (random ==
null) random =
new Random();
613 List<String>
generic =
new ArrayList<String>();
615 boolean energy = pref.name().contains(
"YES_ENERGY");
616 boolean ballistic = pref.name().contains(
"YES_BALLISTIC");
617 boolean missile = pref.name().contains(
"YES_MISSILE");
618 boolean defense = pref.name().contains(
"YES_DEFENSE");
621 for (String
id : skills) {
632 boolean preferred =
true;
634 if (pref != SkillPickPreference.ANY) {
635 if (!energy && energySkill) preferred =
false;
636 if (!ballistic && ballisticSkill) preferred =
false;
637 if (!missile && missileSkill) preferred =
false;
638 if (!defense && defenseSkill) preferred =
false;
669 return picker.
pick();
674 String action = params.get(0).getString(memoryMap);
679 if (action.equals(
"printSkills")) {
680 String personId = params.get(1).getString(memoryMap);
681 AvailableOfficer officer =
getOfficer(personId);
682 boolean admin =
false;
684 if (officer ==
null) {
687 if (officer !=
null) {
692 if (officer !=
null) {
738 }
else if (action.equals(
"hireOfficer")) {
739 String personId = params.get(1).getString(memoryMap);
740 AvailableOfficer officer =
getOfficer(personId);
741 boolean admin =
false;
742 if (officer ==
null) {
744 if (officer !=
null) {
749 if (officer !=
null) {
772 }
else if (action.equals(
"atLimit")) {
774 String personId = params.get(1).getString(memoryMap);
775 AvailableOfficer officer =
getOfficer(personId);
776 boolean admin =
false;
777 if (officer ==
null) {
793 }
else if (action.equals(
"canAfford")) {
794 String personId = params.get(1).getString(memoryMap);
795 AvailableOfficer officer =
getOfficer(personId);
796 if (officer ==
null) {
799 if (officer !=
null) {
810 for (AvailableOfficer officer:
available) {
811 if (officer.person.getId().equals(personId)) {
818 public AvailableOfficer
getAdmin(String personId) {
820 if (officer.person.getId().equals(personId)) {
static SettingsAPI getSettings()
static FactoryAPI getFactory()
static Logger getLogger(Class c)
static SectorAPI getSector()
float computeEffective(float baseValue)
AvailableOfficer getAdmin(String personId)
void reportPlayerMarketTransaction(PlayerMarketTransaction transaction)
boolean callEvent(String ruleId, InteractionDialogAPI dialog, List< Token > params, Map< String, MemoryAPI > memoryMap)
void reportPlayerClosedMarket(MarketAPI market)
void addAvailable(AvailableOfficer officer)
static String pickSkill(PersonAPI person, List< String > skills, SkillPickPreference pref, int numSpec, Random random)
float getOfficerDuration(Random random)
List< AvailableOfficer > availableAdmins
static String pickPortraitPreferNonDuplicate(FactionAPI faction, Gender gender)
void removeAvailable(AvailableOfficer officer)
void addAvailableAdmin(AvailableOfficer officer)
static PersonAPI createOfficer(FactionAPI faction, int level, SkillPickPreference pref, Random random)
AvailableOfficer getOfficer(String personId)
void pruneFromRemovedMarkets()
IntervalUtil removeTracker
static PersonAPI createAdmin(FactionAPI faction, int tier, Random random)
static PersonAPI createOfficer(FactionAPI faction, int level, boolean allowNonDoctrinePersonality)
static PersonAPI createOfficerInternal(FactionAPI faction, int level, boolean allowNonDoctrinePersonality, Random random)
void reportPlayerOpenedMarketAndCargoUpdated(MarketAPI market)
AvailableOfficer createOfficer(boolean isMerc, MarketAPI market, Random random)
List< AvailableOfficer > available
AvailableOfficer createAdmin(MarketAPI market, Random random)
TimeoutTracker< String > recentlyChecked
static PersonAPI createOfficer(FactionAPI faction, int level)
void setEventDataAndAddToMarket(AvailableOfficer officer)
void advance(float amount)
static PersonAPI createMercInternal(FactionAPI faction, int level, int numElite, boolean allowNonDoctrinePersonality, Random random)
static PersonAPI createOfficer(FactionAPI faction, int level, SkillPickPreference pref, boolean allowNonDoctrinePersonality, CampaignFleetAPI fleet, boolean allowAnyLevel, boolean withEliteSkills, int eliteSkillsNumOverride, Random random)
static void addEliteSkills(PersonAPI person, int num, Random random)
void reportPlayerOpenedMarket(MarketAPI market)
static final String INDEPENDENT
static final String RECKLESS
static final String STEADY
static final String TIMID
static final String AGGRESSIVE
static final String CAUTIOUS
static String POST_OFFICER_FOR_HIRE
static String POST_OFFICER
static String POST_FREELANCE_ADMIN
static String POST_ADMINISTRATOR
static String SPACE_CAPTAIN
static String SPACE_LIEUTENANT
static String POST_MERCENARY
static final String TAG_ELITE_PLAYER_ONLY
static final String TAG_DEPRECATED
static final String TAG_BALLISTIC_WEAPONS
static final String TAG_MISSILE_WEAPONS
static final String TAG_SPEC
static final String TAG_ENERGY_WEAPONS
static final String TAG_PLAYER_ONLY
static final String TAG_AI_CORE_ONLY
static final String TAG_ACTIVE_DEFENSES
static final String OFFICER_IS_MERC_PROB_MOD
static final String ADMIN_PROB_MOD
static final String OFFICER_PROB_MOD
static final String OFFICER_ADDITIONAL_PROB_MULT_MOD
static void addAdminGainText(PersonAPI admin, TextPanelAPI text)
static void addOfficerGainText(PersonAPI officer, TextPanelAPI text)
static void addCreditsLossText(int credits, TextPanelAPI text)
float getIntervalDuration()
void advance(float amount)
static String getWithDGS(float num)
static String lcFirst(String str)
static boolean isMercenary(PersonAPI person)
static Color getNegativeHighlightColor()
static Random getRandom(long seed, int level)
static float getAdminSalary(PersonAPI admin)
static Color getHighlightColor()
static void setMercHiredNow(PersonAPI person)
static void setMercenary(PersonAPI person, boolean mercenary)
static int getNumNonMercOfficers(CampaignFleetAPI fleet)
static float getOfficerSalary(PersonAPI officer)
void addAll(Collection< T > items)
OfficerDataAPI createOfficerData(PersonAPI person)
SkillSpecAPI getSkillSpec(String skillId)
List< String > getSortedSkillIds()
Object getPlugin(String id)
float getFloat(String key)
float convertToDays(float realSeconds)
FleetDataAPI getFleetData()
MutableValue getCredits()
List< AdminData > getAdmins()
void addAdmin(PersonAPI admin)
void removePerson(PersonAPI person)
String addPerson(PersonAPI person)
WeightedRandomPicker< String > getPersonalityPicker()
WeightedRandomPicker< String > getPortraits(Gender gender)
PersonAPI createRandomPerson()
boolean isNeutralFaction()
FactionDoctrineAPI getDoctrine()
List< String > getOfficerSkills()
float getOfficerSkillsShuffleProbability()
void addOfficer(PersonAPI person)
List< OfficerDataAPI > getOfficersCopy()
TextPanelAPI getTextPanel()
CampaignFleetAPI getPlayerFleet()
CampaignClockAPI getClock()
FactionAPI getFaction(String factionId)
PersonAPI getPlayerPerson()
ListenerManagerAPI getListenerManager()
CharacterDataAPI getCharacterData()
void setFontSmallInsignia()
void addSkillPanel(PersonAPI person, boolean admin)
LabelAPI addParagraph(String text)
void highlightInLastPara(Color color, String ...strings)
MarketAPI getMarket(String id)
boolean isPlanetConditionMarketOnly()
MutableMarketStatsAPI getStats()
void addPerson(PersonAPI person)
CommDirectoryAPI getCommDirectory()
boolean hasTag(String tag)
void removePerson(PersonAPI person)
void addListener(Object listener)
float getFloat(String key)
void set(String key, Object value)
List< SkillLevelAPI > getSkillsCopy()
void increaseSkill(String id)
MutableStat getOfficerNumber()
void setSkillLevel(String id, float level)
void refreshCharacterStatsEffects()
void setSkipRefresh(boolean skipRefresh)
MutableStat getAdminNumber()
void levelUp(String skillId)
List< String > getSkillPicks()
String getPortraitSprite()
void setPortraitSprite(String portraitSprite)
void setFleet(CampaignFleetAPI fleet)
void setFaction(String factionId)
void setRankId(String rank)
MutableCharacterStatsAPI getStats()
void setPersonality(String personality)
MemoryAPI getMemoryWithoutUpdate()
PersonalityAPI getPersonalityAPI()
void setPostId(String postId)
boolean hasTag(String tag)
DynamicStatsAPI getDynamic()
List< String > pickLevelupSkills(PersonAPI person, Random random)
int getMaxEliteSkills(PersonAPI person)
int getMaxLevel(PersonAPI person)
long getXPForLevel(int level)
StatBonus getMod(String id)