Starsector API
Loading...
Searching...
No Matches
OfficerManagerEvent.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.events;
2
3import java.awt.Color;
4import java.util.ArrayList;
5import java.util.Collections;
6import java.util.HashSet;
7import java.util.Iterator;
8import java.util.List;
9import java.util.Map;
10import java.util.Random;
11import java.util.Set;
12
13import org.apache.log4j.Logger;
14
15import com.fs.starfarer.api.EveryFrameScript;
16import com.fs.starfarer.api.Global;
17import com.fs.starfarer.api.campaign.CampaignClockAPI;
18import com.fs.starfarer.api.campaign.CampaignFleetAPI;
19import com.fs.starfarer.api.campaign.CargoAPI;
20import com.fs.starfarer.api.campaign.FactionAPI;
21import com.fs.starfarer.api.campaign.InteractionDialogAPI;
22import com.fs.starfarer.api.campaign.PlayerMarketTransaction;
23import com.fs.starfarer.api.campaign.TextPanelAPI;
24import com.fs.starfarer.api.campaign.econ.MarketAPI;
25import com.fs.starfarer.api.campaign.listeners.ColonyInteractionListener;
26import com.fs.starfarer.api.campaign.rules.MemoryAPI;
27import com.fs.starfarer.api.characters.AdminData;
28import com.fs.starfarer.api.characters.FullName.Gender;
29import com.fs.starfarer.api.characters.MutableCharacterStatsAPI;
30import com.fs.starfarer.api.characters.MutableCharacterStatsAPI.SkillLevelAPI;
31import com.fs.starfarer.api.characters.OfficerDataAPI;
32import com.fs.starfarer.api.characters.PersonAPI;
33import com.fs.starfarer.api.characters.SkillSpecAPI;
34import com.fs.starfarer.api.impl.campaign.ids.Factions;
35import com.fs.starfarer.api.impl.campaign.ids.Personalities;
36import com.fs.starfarer.api.impl.campaign.ids.Ranks;
37import com.fs.starfarer.api.impl.campaign.ids.Skills;
38import com.fs.starfarer.api.impl.campaign.ids.Stats;
39import com.fs.starfarer.api.impl.campaign.ids.Tags;
40import com.fs.starfarer.api.impl.campaign.rulecmd.AddRemoveCommodity;
41import com.fs.starfarer.api.impl.campaign.rulecmd.CallEvent.CallableEvent;
42import com.fs.starfarer.api.plugins.OfficerLevelupPlugin;
43import com.fs.starfarer.api.util.IntervalUtil;
44import com.fs.starfarer.api.util.Misc;
45import com.fs.starfarer.api.util.Misc.Token;
46import com.fs.starfarer.api.util.TimeoutTracker;
47import com.fs.starfarer.api.util.WeightedRandomPicker;
48
57public class OfficerManagerEvent extends BaseEventPlugin implements CallableEvent, ColonyInteractionListener, EveryFrameScript {
58
59 public static class AvailableOfficer {
60 public PersonAPI person;
61 public String marketId;
62 public int hiringBonus;
63 public int salary;
64 public float timeRemaining = 0f;
65 public AvailableOfficer(PersonAPI person, String marketId, int hiringBonus, int salary) {
66 this.person = person;
67 this.marketId = marketId;
68 this.hiringBonus = hiringBonus;
69 this.salary = salary;
70 }
71
72 }
73
74 public static Logger log = Global.getLogger(OfficerManagerEvent.class);
75
76 protected IntervalUtil removeTracker = new IntervalUtil(1f, 3f);
77
78 protected List<AvailableOfficer> available = new ArrayList<AvailableOfficer>();
79 protected List<AvailableOfficer> availableAdmins = new ArrayList<AvailableOfficer>();
80
81 protected TimeoutTracker<String> recentlyChecked = new TimeoutTracker<String>();
82
83 protected long seed = 0;
84
86 readResolve();
87 Global.getSector().getListenerManager().addListener(this);
88 }
89
90 Object readResolve() {
91 if (availableAdmins == null) {
92 availableAdmins = new ArrayList<AvailableOfficer>();
93 }
94 if (recentlyChecked == null) {
95 recentlyChecked = new TimeoutTracker<String>();
96 }
97 if (seed == 0) {
98 seed = Misc.random.nextLong();
99 }
100// Global.getSector().getListenerManager().addListener(this);
101 return this;
102 }
103
104 public void reportPlayerClosedMarket(MarketAPI market) {}
105
106 public void reportPlayerOpenedMarket(MarketAPI market) {
107 if (recentlyChecked.contains(market.getId())) return;
108
109 if (market.isPlanetConditionMarketOnly()) return;
110 if (market.getFaction().isNeutralFaction()) return;
111 if (!market.isInEconomy()) return;
112 if (market.hasTag(Tags.MARKET_NO_OFFICER_SPAWN)) return;
113
114
116
117 float officerProb = market.getStats().getDynamic().getMod(Stats.OFFICER_PROB_MOD).computeEffective(0f);
118 float additionalProb = market.getStats().getDynamic().getMod(Stats.OFFICER_ADDITIONAL_PROB_MULT_MOD).computeEffective(0f);
119 float mercProb = market.getStats().getDynamic().getMod(Stats.OFFICER_IS_MERC_PROB_MOD).computeEffective(0f);
120 float adminProb = market.getStats().getDynamic().getMod(Stats.ADMIN_PROB_MOD).computeEffective(0f);
121 //adminProb = 1f;
122
123 log.info("Spawning officers/admins at " + market.getId());
124 log.info(" officerProb: " + officerProb);
125 log.info(" additionalProb: " + additionalProb);
126 log.info(" mercProb: " + mercProb);
127 log.info(" adminProb: " + adminProb);
128 log.info("");
129
130
131 CampaignClockAPI clock = Global.getSector().getClock();
132 long mult = clock.getCycle() * 12L + clock.getMonth();
133
134 //Random random = new Random(seed + market.getId().hashCode() * mult);
135 Random random = Misc.getRandom(seed + market.getId().hashCode() * mult, 11);
136 //random = new Random();
137
138 float dur = getOfficerDuration(random);
139 recentlyChecked.add(market.getId(), dur * 0.5f);
140
141 if (random.nextFloat() < officerProb) {
142 boolean merc = random.nextFloat() < mercProb;
143 AvailableOfficer officer = createOfficer(merc, market, random);
144 //officer.person.setPortraitSprite(pickPortraitPreferNonDuplicate(officer.person.getFaction(), officer.person.getGender()));
145 // always independent at this point
146 officer.person.setPortraitSprite(pickPortraitPreferNonDuplicate(market.getFaction(), officer.person.getGender()));
147 officer.timeRemaining = dur;
148 addAvailable(officer);
149 log.info("Added officer at " + officer.marketId + "");
150
151 if (random.nextFloat() < officerProb * additionalProb) {
152 merc = random.nextFloat() < mercProb;
153 officer = createOfficer(merc, market, random);
154 //officer.person.setPortraitSprite(pickPortraitPreferNonDuplicate(officer.person.getFaction(), officer.person.getGender()));
155 officer.person.setPortraitSprite(pickPortraitPreferNonDuplicate(market.getFaction(), officer.person.getGender()));
156 officer.timeRemaining = dur;
157 addAvailable(officer);
158 log.info("Added officer at [" + officer.marketId + "]");
159 }
160 }
161
162 if (random.nextFloat() < adminProb) {
163 AvailableOfficer officer = createAdmin(market, random);
164 officer.timeRemaining = dur;
165 //officer.person.setPortraitSprite(pickPortraitPreferNonDuplicate(officer.person.getFaction(), officer.person.getGender()));
166 officer.person.setPortraitSprite(pickPortraitPreferNonDuplicate(market.getFaction(), officer.person.getGender()));
167 addAvailableAdmin(officer);
168 log.info("Added admin at [" + officer.marketId + "]");
169 }
170 }
171
172 protected float getOfficerDuration(Random random) {
173 return 60f + 60f * random.nextFloat();
174 }
175
176 public void advance(float amount) {
177 float days = Global.getSector().getClock().convertToDays(amount);
178
179 recentlyChecked.advance(days);
180
181// if (!Global.getSector().getListenerManager().hasListener(this)) {
182// Global.getSector().getListenerManager().addListener(this);
183// }
184
185 removeTracker.advance(days);
186 if (removeTracker.intervalElapsed()) {
188
189 float interval = removeTracker.getIntervalDuration();
190
191 for (AvailableOfficer curr : new ArrayList<AvailableOfficer>(available)) {
192 curr.timeRemaining -= interval;
193 if (curr.timeRemaining <= 0) {
194 removeAvailable(curr);
195 log.info("Removed officer from [" + curr.marketId + "]");
196 }
197 }
198 for (AvailableOfficer curr : new ArrayList<AvailableOfficer>(availableAdmins)) {
199 curr.timeRemaining -= interval;
200 if (curr.timeRemaining <= 0) {
201 removeAvailable(curr);
202 log.info("Removed freelance admin from [" + curr.marketId + "]");
203 }
204 }
205 }
206
207 }
208
210 for (AvailableOfficer curr : new ArrayList<AvailableOfficer>(available)) {
211 if (Global.getSector().getEconomy().getMarket(curr.marketId) == null) {
212 removeAvailable(curr);
213 }
214 }
215 for (AvailableOfficer curr : new ArrayList<AvailableOfficer>(availableAdmins)) {
216 if (Global.getSector().getEconomy().getMarket(curr.marketId) == null) {
217 removeAvailable(curr);
218 }
219 }
220 }
221
222 public void addAvailable(AvailableOfficer officer) {
223 if (officer == null) return;
224
225 available.add(officer);
226
228 }
229
230 public void addAvailableAdmin(AvailableOfficer officer) {
231 if (officer == null) return;
232
233 availableAdmins.add(officer);
234
236 }
237
238 protected void setEventDataAndAddToMarket(AvailableOfficer officer) {
239 MarketAPI market = Global.getSector().getEconomy().getMarket(officer.marketId);
240 if (market == null) return;
241 market.getCommDirectory().addPerson(officer.person);
242 market.addPerson(officer.person);
243
244 officer.person.getMemoryWithoutUpdate().set("$ome_hireable", true);
245 officer.person.getMemoryWithoutUpdate().set("$ome_eventRef", this);
246 officer.person.getMemoryWithoutUpdate().set("$ome_hiringBonus", Misc.getWithDGS(officer.hiringBonus));
247 officer.person.getMemoryWithoutUpdate().set("$ome_salary", Misc.getWithDGS(officer.salary));
248 }
249
250 public void removeAvailable(AvailableOfficer officer) {
251 if (officer == null) return;
252
253 available.remove(officer);
254 availableAdmins.remove(officer);
255
256 MarketAPI market = Global.getSector().getEconomy().getMarket(officer.marketId);
257 if (market != null) {
258 market.getCommDirectory().removePerson(officer.person);
259 market.removePerson(officer.person);
260 }
261
262 officer.person.getMemoryWithoutUpdate().unset("$ome_hireable");
263 officer.person.getMemoryWithoutUpdate().unset("$ome_eventRef");
264 officer.person.getMemoryWithoutUpdate().unset("$ome_hiringBonus");
265 officer.person.getMemoryWithoutUpdate().unset("$ome_salary");
266 }
267
268 public static String pickPortraitPreferNonDuplicate(FactionAPI faction, Gender gender) {
269 if (faction == null) {
270 faction = Global.getSector().getFaction(Factions.INDEPENDENT);
271 }
272 WeightedRandomPicker<String> all = faction.getPortraits(gender);
273 WeightedRandomPicker<String> picker = new WeightedRandomPicker<String>();
274
275 Set<String> exclude = new HashSet<String>();
276 exclude.add(Global.getSector().getPlayerPerson().getPortraitSprite());
277 if (Global.getSector().getPlayerFleet() != null) {
278 for (OfficerDataAPI od : Global.getSector().getPlayerFleet().getFleetData().getOfficersCopy()) {
279 exclude.add(od.getPerson().getPortraitSprite());
280 }
281 }
282 for (AdminData ad : Global.getSector().getCharacterData().getAdmins()) {
283 exclude.add(ad.getPerson().getPortraitSprite());
284 }
285 for (String p : all.getItems()) {
286 if (exclude.contains(p)) continue;
287 picker.add(p);
288 }
289 if (picker.isEmpty()) {
290 picker = all;
291 }
292 return picker.pick();
293 }
294
295 protected AvailableOfficer createAdmin(MarketAPI market, Random random) {
296// WeightedRandomPicker<MarketAPI> marketPicker = new WeightedRandomPicker<MarketAPI>();
297// for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
298// marketPicker.add(market, market.getSize());
299// }
300// MarketAPI market = marketPicker.pick();
301 if (market == null) return null;
302
303 WeightedRandomPicker<Integer> tierPicker = new WeightedRandomPicker<Integer>();
304 tierPicker.add(0, 60);
305 tierPicker.add(1, 40);
306
307 int tier = tierPicker.pick();
308
309 PersonAPI person = createAdmin(market.getFaction(), tier, random);
310 person.setFaction(Factions.INDEPENDENT);
311
312 String hireKey = "adminHireTier" + tier;
313 int hiringBonus = Global.getSettings().getInt(hireKey);
314
315 int salary = (int) Misc.getAdminSalary(person);
316
317 AvailableOfficer result = new AvailableOfficer(person, market.getId(), hiringBonus, salary);
318 return result;
319 }
320
321 public static PersonAPI createAdmin(FactionAPI faction, int tier, Random random) {
322 if (random == null) random = new Random();
323 PersonAPI person = faction.createRandomPerson(random);
324
325 person.getStats().setSkipRefresh(true);
326 WeightedRandomPicker<String> picker = new WeightedRandomPicker<String>(random);
327 List<String> allSkillIds = Global.getSettings().getSortedSkillIds();
328 for (String skillId : allSkillIds) {
329 SkillSpecAPI skill = Global.getSettings().getSkillSpec(skillId);
330 if (skill.hasTag(Skills.TAG_DEPRECATED)) continue;
331 if (skill.hasTag(Skills.TAG_PLAYER_ONLY)) continue;
332 if (skill.hasTag(Skills.TAG_AI_CORE_ONLY)) continue;
333 if (skill.isAdminSkill()) {
334 picker.add(skillId);
335 }
336 }
337
338 for (int i = 0; i < tier && !picker.isEmpty(); i++) {
339 String pick = picker.pickAndRemove();
340 person.getStats().setSkillLevel(pick, 3);
341 }
342
343 person.getMemoryWithoutUpdate().set("$ome_isAdmin", true);
344 person.getMemoryWithoutUpdate().set("$ome_adminTier", tier);
345
346
347 person.setRankId(Ranks.CITIZEN);
348 person.setPostId(Ranks.POST_FREELANCE_ADMIN);
349
350
351 WeightedRandomPicker<String> personalityPicker = faction.getPersonalityPicker().clone();
352
353 String personality = personalityPicker.pick();
354 person.setPersonality(personality);
355
356 person.getStats().setSkipRefresh(false);
357 person.getStats().refreshCharacterStatsEffects();
358
359 //person.setPortraitSprite(pickPortrait(person.getFaction(), person.getGender()));
360
361 return person;
362 }
363
364
365 protected AvailableOfficer createOfficer(boolean isMerc, MarketAPI market, Random random) {
366// WeightedRandomPicker<MarketAPI> marketPicker = new WeightedRandomPicker<MarketAPI>();
367// for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
368// marketPicker.add(market, market.getSize());
369// }
370// MarketAPI market = marketPicker.pick();
371 if (market == null) return null;
372
373 //FactionAPI faction = Global.getSector().getFaction(Factions.INDEPENDENT);
374
375 int level = 1;
376 if ((float) Math.random() > 0.75f) level = 2;
377
378 float payMult = 1f;
379
380 PersonAPI person = null;
381 if (isMerc) {
382 payMult = Global.getSettings().getFloat("officerMercPayMult");
383
384 int minLevel = Global.getSettings().getInt("officerMercMinLevel");
385 int maxLevel = Global.getSettings().getInt("officerMercMaxLevel");
386 level = minLevel + Misc.random.nextInt(maxLevel + 1 - minLevel);
387
388 int numElite = 1;
389 if (level == maxLevel) numElite = 2;
390 person = createMercInternal(market.getFaction(), level, numElite, true, random);
391
392 person.setRankId(Ranks.SPACE_CAPTAIN);
393 person.setPostId(Ranks.POST_MERCENARY);
394 Misc.setMercenary(person, true);
395 } else {
396 person = createOfficerInternal(market.getFaction(), level, true, random);
397 person.setPostId(Ranks.POST_OFFICER_FOR_HIRE);
398 }
399
400 person.setFaction(Factions.INDEPENDENT);
401
402
403
404 int salary = (int) Misc.getOfficerSalary(person);
405 AvailableOfficer result = new AvailableOfficer(person, market.getId(),
406 (int) (person.getStats().getLevel() * 2000* payMult), salary);
407 return result;
408 }
409
410 public static PersonAPI createOfficerInternal(FactionAPI faction, int level, boolean allowNonDoctrinePersonality, Random random) {
411 return createOfficer(faction, level, SkillPickPreference.ANY, allowNonDoctrinePersonality,
412 null, false, false, -1, random);
413 }
414
415 public static PersonAPI createMercInternal(FactionAPI faction, int level, int numElite, boolean allowNonDoctrinePersonality, Random random) {
416// SkillPickPreference pref = SkillPickPreference.GENERIC;
417// float f = (float) Math.random();
418// if (f < 0.05f) {
419// pref = SkillPickPreference.ANY;
420// } else if (f < 0.1f) {
421// pref = SkillPickPreference.PHASE;
422// } else if (f < 0.25f) {
423// pref = SkillPickPreference.CARRIER;
424// }
425 SkillPickPreference pref = SkillPickPreference.ANY;
426 return createOfficer(faction, level, pref, allowNonDoctrinePersonality,
427 null, true, true, numElite, random);
428 }
429
430
431 public static enum SkillPickPreference {
432 @Deprecated CARRIER,
433 @Deprecated GENERIC,
434 @Deprecated PHASE,
435
440 YES_ENERGY_YES_BALLISTIC_YES_MISSILE_YES_DEFENSE,
441 YES_ENERGY_YES_BALLISTIC_NO_MISSILE_YES_DEFENSE,
442 YES_ENERGY_YES_BALLISTIC_YES_MISSILE_NO_DEFENSE,
443 YES_ENERGY_YES_BALLISTIC_NO_MISSILE_NO_DEFENSE,
444 YES_ENERGY_NO_BALLISTIC_YES_MISSILE_YES_DEFENSE,
445 YES_ENERGY_NO_BALLISTIC_NO_MISSILE_YES_DEFENSE,
446 YES_ENERGY_NO_BALLISTIC_YES_MISSILE_NO_DEFENSE,
447 YES_ENERGY_NO_BALLISTIC_NO_MISSILE_NO_DEFENSE,
448 NO_ENERGY_YES_BALLISTIC_YES_MISSILE_YES_DEFENSE,
449 NO_ENERGY_YES_BALLISTIC_NO_MISSILE_YES_DEFENSE,
450 NO_ENERGY_YES_BALLISTIC_YES_MISSILE_NO_DEFENSE,
451 NO_ENERGY_YES_BALLISTIC_NO_MISSILE_NO_DEFENSE,
452 NO_ENERGY_NO_BALLISTIC_YES_MISSILE_YES_DEFENSE,
453 NO_ENERGY_NO_BALLISTIC_NO_MISSILE_YES_DEFENSE,
454 NO_ENERGY_NO_BALLISTIC_YES_MISSILE_NO_DEFENSE,
455 NO_ENERGY_NO_BALLISTIC_NO_MISSILE_NO_DEFENSE,
456 ANY,
457 }
458
459 public static PersonAPI createOfficer(FactionAPI faction, int level) {
460 return createOfficer(faction, level, false);
461 }
462 public static PersonAPI createOfficer(FactionAPI faction, int level, boolean allowNonDoctrinePersonality) {
463 return createOfficer(faction, level, SkillPickPreference.ANY, allowNonDoctrinePersonality,
464 null, false, true, -1, null);
465 }
466 public static PersonAPI createOfficer(FactionAPI faction, int level, SkillPickPreference pref, Random random) {
467 return createOfficer(faction, level, pref, false, null, false, true, -1, random);
468 }
469
470 public static boolean DEBUG = false;
471 public static PersonAPI createOfficer(FactionAPI faction, int level,
472 SkillPickPreference pref, boolean allowNonDoctrinePersonality,
473 CampaignFleetAPI fleet, boolean allowAnyLevel,
474 boolean withEliteSkills, int eliteSkillsNumOverride, Random random) {
475 if (random == null) random = new Random();
476
477 //DEBUG = true;
478
479 PersonAPI person = faction.createRandomPerson(random);
480 person.setFleet(fleet);
481 OfficerLevelupPlugin plugin = (OfficerLevelupPlugin) Global.getSettings().getPlugin("officerLevelUp");
482
483 if (!allowAnyLevel) {
484 if (level > plugin.getMaxLevel(person)) level = plugin.getMaxLevel(person);
485 }
486
487 person.getStats().setSkipRefresh(true);
488
489 if (DEBUG) System.out.println("Generating officer\n");
490
491 List<String> fixedSkills = new ArrayList<String>(faction.getDoctrine().getOfficerSkills());
492 Iterator<String> iter = fixedSkills.iterator();
493 while (iter.hasNext()) {
494 String id = iter.next();
495 SkillSpecAPI spec = Global.getSettings().getSkillSpec(id);
496 if (spec != null && spec.hasTag(Skills.TAG_PLAYER_ONLY)) {
497 iter.remove();
498 }
499 }
500
501 if (random.nextFloat() < faction.getDoctrine().getOfficerSkillsShuffleProbability()) {
502 Collections.shuffle(fixedSkills, random);
503 }
504
505 int numSpec = 0;
506 for (int i = 0; i < 1; i++) {
507 List<String> skills = plugin.pickLevelupSkills(person, random);
508 String skillId = pickSkill(person, skills, pref, numSpec, random);
509 if (!fixedSkills.isEmpty()) {
510 skillId = fixedSkills.remove(0);
511 }
512 if (skillId != null) {
513 if (DEBUG) System.out.println("Picking initial skill: " + skillId);
514 person.getStats().increaseSkill(skillId);
515 SkillSpecAPI spec = Global.getSettings().getSkillSpec(skillId);
516 if (spec.hasTag(Skills.TAG_SPEC)) numSpec++;
517
518 }
519 }
520
521// level = 20;
522// pref = SkillPickPreference.NON_CARRIER;
523
524 long xp = plugin.getXPForLevel(level);
525 OfficerDataAPI officerData = Global.getFactory().createOfficerData(person);
526 officerData.addXP(xp, null, false);
527
528 //DEBUG = true;
529
530 officerData.makeSkillPicks(random);
531
532 while (officerData.canLevelUp(allowAnyLevel)) {
533 String skillId = pickSkill(officerData.getPerson(), officerData.getSkillPicks(), pref, numSpec, random);
534 if (!fixedSkills.isEmpty()) {
535 skillId = fixedSkills.remove(0);
536 }
537 if (skillId != null) {
538 if (DEBUG) System.out.println("Leveling up " + skillId);
539 officerData.levelUp(skillId, random);
540 SkillSpecAPI spec = Global.getSettings().getSkillSpec(skillId);
541 if (spec.hasTag(Skills.TAG_SPEC)) numSpec++;
542
543 if (allowAnyLevel && officerData.getSkillPicks().isEmpty()) {
544 officerData.makeSkillPicks(random);
545 }
546 } else {
547 break;
548 }
549 }
550
551 if (withEliteSkills && eliteSkillsNumOverride != 0) {
552 int num = eliteSkillsNumOverride;
553 if (num < 0) {
554 num = plugin.getMaxEliteSkills(person);
555 }
556 addEliteSkills(person, num, random);
557 }
558
559 if (DEBUG) System.out.println("Done\n");
560
561 person.setRankId(Ranks.SPACE_LIEUTENANT);
562 person.setPostId(Ranks.POST_OFFICER);
563
564
565 WeightedRandomPicker<String> personalityPicker = faction.getPersonalityPicker().clone();
566 if (allowNonDoctrinePersonality) {
567 personalityPicker.add(Personalities.TIMID, 4f);
568 personalityPicker.add(Personalities.CAUTIOUS, 4f);
569 personalityPicker.add(Personalities.STEADY, 4f);
570 personalityPicker.add(Personalities.AGGRESSIVE, 4f);
571 personalityPicker.add(Personalities.RECKLESS, 4f);
572 }
573
574 String personality = personalityPicker.pick();
575 person.setPersonality(personality);
576
577
578 person.getStats().setSkipRefresh(false);
579 person.getStats().refreshCharacterStatsEffects();
580
581 return person;
582 }
583
584 public static void addEliteSkills(PersonAPI person, int num, Random random) {
585 if (num <= 0) return;
586
587 WeightedRandomPicker<String> picker = new WeightedRandomPicker<String>(random);
588 for (SkillLevelAPI sl : person.getStats().getSkillsCopy()) {
589 if (sl.getSkill().hasTag(Skills.TAG_ELITE_PLAYER_ONLY)) continue;
590 if (sl.getSkill().isAptitudeEffect()) continue;
591 if (!sl.getSkill().isCombatOfficerSkill()) continue;
592 picker.add(sl.getSkill().getId(), 1f);
593 }
594
595 for (int i = 0; i < num && !picker.isEmpty(); i++) {
596 String id = picker.pickAndRemove();
597 if (id != null) {
598 if (DEBUG) System.out.println("Making skill elite: " + id);
599 person.getStats().increaseSkill(id);
600 }
601 }
602 }
603
604 public static String pickSkill(PersonAPI person, List<String> skills, SkillPickPreference pref, int numSpec, Random random) {
605 if (random == null) random = new Random();
606
607 WeightedRandomPicker<String> picker = new WeightedRandomPicker<String>(random);
608 List<String> generic = new ArrayList<String>();
609
610 boolean energy = pref.name().contains("YES_ENERGY"); // lol
611 boolean ballistic = pref.name().contains("YES_BALLISTIC");
612 boolean missile = pref.name().contains("YES_MISSILE");
613 boolean defense = pref.name().contains("YES_DEFENSE");
614
615
616 for (String id : skills) {
617 SkillSpecAPI spec = Global.getSettings().getSkillSpec(id);
618// boolean carrierSkill = spec.hasTag(Skills.TAG_CARRIER);
619// boolean phaseSkill = spec.hasTag(Skills.TAG_PHASE);
620// boolean specSkill = spec.hasTag(Skills.TAG_SPEC);
621
622 boolean energySkill = spec.hasTag(Skills.TAG_ENERGY_WEAPONS);
623 boolean ballisticSkill = spec.hasTag(Skills.TAG_BALLISTIC_WEAPONS);
624 boolean missileSkill = spec.hasTag(Skills.TAG_MISSILE_WEAPONS);
625 boolean defenseSkill = spec.hasTag(Skills.TAG_ACTIVE_DEFENSES);
626
627 boolean preferred = true;
628
629 if (pref != SkillPickPreference.ANY) {
630 if (!energy && energySkill) preferred = false;
631 if (!ballistic && ballisticSkill) preferred = false;
632 if (!missile && missileSkill) preferred = false;
633 if (!defense && defenseSkill) preferred = false;
634 }
635
636// preferred |= pref == SkillPickPreference.ANY;
637// preferred |= pref == SkillPickPreference.CARRIER && carrierSkill;
638// preferred |= pref == SkillPickPreference.PHASE && phaseSkill;
639// preferred |= pref == SkillPickPreference.GENERIC && !phaseSkill && !carrierSkill;
640
641// if (specSkill && !carrierSkill && !phaseSkill && numSpec >= 1) {
642// preferred = false;
643// }
644 if (spec.hasTag(Skills.TAG_PLAYER_ONLY)) {
645 preferred = false;
646 }
647
648 if (preferred) {
649 picker.add(id);
650 } else {
651 generic.add(id);
652 }
653
654 //if ((!specSkill || numSpec < 1) && !carrierSkill && !phaseSkill) {
655 //}
656 }
657 if (picker.isEmpty()) {
658 picker.addAll(generic);
659 if (picker.isEmpty()) {
660 picker.addAll(skills);
661 }
662 }
663
664 return picker.pick();
665 }
666
667
668 public boolean callEvent(String ruleId, InteractionDialogAPI dialog, List<Token> params, Map<String, MemoryAPI> memoryMap) {
669 String action = params.get(0).getString(memoryMap);
670
671 CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet();
672 CargoAPI cargo = playerFleet.getCargo();
673
674 if (action.equals("printSkills")) {
675 String personId = params.get(1).getString(memoryMap);
676 AvailableOfficer officer = getOfficer(personId);
677 boolean admin = false;
678 int adminTier = 0;
679 if (officer == null) {
680 officer = getAdmin(personId);
681 admin = true;
682 if (officer != null) {
683 adminTier = (int) officer.person.getMemoryWithoutUpdate().getFloat("$ome_adminTier");
684 }
685 }
686
687 if (officer != null) {
688 MutableCharacterStatsAPI stats = officer.person.getStats();
689 TextPanelAPI text = dialog.getTextPanel();
690
691 Color hl = Misc.getHighlightColor();
692 Color red = Misc.getNegativeHighlightColor();
693
694 //text.addParagraph("-----------------------------------------------------------------------------");
695
696// if (!admin) {
697// text.addParagraph("Level: " + (int) stats.getLevel());
698// text.highlightInLastPara(hl, "" + (int) stats.getLevel());
699// }
700// for (String skillId : Global.getSettings().getSortedSkillIds()) {
701// int level = (int) stats.getSkillLevel(skillId);
702// if (level > 0) {
703// SkillSpecAPI spec = Global.getSettings().getSkillSpec(skillId);
704// String skillName = spec.getName();
705// if (spec.isAptitudeEffect()) {
706// skillName += " Aptitude";
707// }
708//
709// if (level <= 1) {
710// text.addParagraph(skillName);
711// } else {
712// text.addParagraph(skillName + " (Elite)");
713// }
714// //text.highlightInLastPara(hl, "" + level);
715// }
716// }
717
718 text.addSkillPanel(officer.person, admin);
719
720 text.setFontSmallInsignia();
721
722 if (!admin) {
723 String personality = Misc.lcFirst(officer.person.getPersonalityAPI().getDisplayName());
724 text.addParagraph("Personality: " + personality + ", level: " + stats.getLevel());
725 text.highlightInLastPara(hl, personality, "" + stats.getLevel());
726 text.addParagraph(officer.person.getPersonalityAPI().getDescription());
727 }
728
729 //text.addParagraph("-----------------------------------------------------------------------------");
730
731 text.setFontInsignia();
732 }
733 } else if (action.equals("hireOfficer")) {
734 String personId = params.get(1).getString(memoryMap);
735 AvailableOfficer officer = getOfficer(personId);
736 boolean admin = false;
737 if (officer == null) {
738 officer = getAdmin(personId);
739 if (officer != null) {
740 officer.person.setPostId(Ranks.POST_ADMINISTRATOR);
741 }
742 admin = true;
743 }
744 if (officer != null) {
745 removeAvailable(officer);
746 if (admin) {
747 Global.getSector().getCharacterData().addAdmin(officer.person);
748 } else {
749 playerFleet.getFleetData().addOfficer(officer.person);
750 if (Misc.isMercenary(officer.person)) {
751 Misc.setMercHiredNow(officer.person);
752 } else {
753 officer.person.setPostId(Ranks.POST_OFFICER);
754 }
755 }
756 AddRemoveCommodity.addCreditsLossText(officer.hiringBonus, dialog.getTextPanel());
757 if (admin) {
758 AddRemoveCommodity.addAdminGainText(officer.person, dialog.getTextPanel());
759 } else {
760 AddRemoveCommodity.addOfficerGainText(officer.person, dialog.getTextPanel());
761 }
762 playerFleet.getCargo().getCredits().subtract(officer.hiringBonus);
763 if (playerFleet.getCargo().getCredits().get() <= 0) {
764 playerFleet.getCargo().getCredits().set(0);
765 }
766 }
767 } else if (action.equals("atLimit")) {
768 //int max = (int) Global.getSettings().getFloat("officerPlayerMax");
769 String personId = params.get(1).getString(memoryMap);
770 AvailableOfficer officer = getOfficer(personId);
771 boolean admin = false;
772 if (officer == null) {
773 officer = getAdmin(personId);
774 admin = true;
775 }
776 int max = playerFleet.getCommander().getStats().getOfficerNumber().getModifiedInt();
777 if (admin) {
778 max = playerFleet.getCommander().getStats().getAdminNumber().getModifiedInt();
779 return Global.getSector().getCharacterData().getAdmins().size() >= max;
780 }
781
782 // can hire more than max number of admins, just can't assign to govern w/o penalty
783 //if (admin) return false;
784
785 return Misc.getNumNonMercOfficers(playerFleet) >= max;
786
787 //return playerFleet.getFleetData().getOfficersCopy().size() >= max;
788 } else if (action.equals("canAfford")) {
789 String personId = params.get(1).getString(memoryMap);
790 AvailableOfficer officer = getOfficer(personId);
791 if (officer == null) {
792 officer = getAdmin(personId);
793 }
794 if (officer != null) {
795 return playerFleet.getCargo().getCredits().get() >= officer.hiringBonus;
796 } else {
797 return false;
798 }
799 }
800
801 return true;
802 }
803
804 public AvailableOfficer getOfficer(String personId) {
805 for (AvailableOfficer officer: available) {
806 if (officer.person.getId().equals(personId)) {
807 return officer;
808 }
809 }
810 return null;
811 }
812
813 public AvailableOfficer getAdmin(String personId) {
814 for (AvailableOfficer officer: availableAdmins) {
815 if (officer.person.getId().equals(personId)) {
816 return officer;
817 }
818 }
819 return null;
820 }
821
822 public void reportPlayerMarketTransaction(PlayerMarketTransaction transaction) {
823
824 }
825
827
828 }
829
830 public boolean runWhilePaused() {
831 return false;
832 }
833
834 public boolean isDone() {
835 return false;
836 }
837}
838
839
840
841
842
843
844
845
846
847
static SettingsAPI getSettings()
Definition Global.java:51
static FactoryAPI getFactory()
Definition Global.java:35
static Logger getLogger(Class c)
Definition Global.java:26
static SectorAPI getSector()
Definition Global.java:59
void reportPlayerMarketTransaction(PlayerMarketTransaction transaction)
boolean callEvent(String ruleId, InteractionDialogAPI dialog, List< Token > params, Map< String, MemoryAPI > memoryMap)
static String pickSkill(PersonAPI person, List< String > skills, SkillPickPreference pref, int numSpec, Random random)
static String pickPortraitPreferNonDuplicate(FactionAPI faction, Gender gender)
static PersonAPI createOfficer(FactionAPI faction, int level, SkillPickPreference pref, Random random)
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)
AvailableOfficer createOfficer(boolean isMerc, MarketAPI market, Random random)
AvailableOfficer createAdmin(MarketAPI market, Random random)
static PersonAPI createOfficer(FactionAPI faction, int level)
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)
OfficerDataAPI createOfficerData(PersonAPI person)
SkillSpecAPI getSkillSpec(String skillId)
List< String > getSortedSkillIds()