1package com.fs.starfarer.api.impl.campaign.skills;
4import java.util.ArrayList;
5import java.util.LinkedHashMap;
9import org.lwjgl.input.Mouse;
11import com.fs.starfarer.api.Global;
12import com.fs.starfarer.api.characters.PersonAPI;
13import com.fs.starfarer.api.combat.BaseEveryFrameCombatPlugin;
14import com.fs.starfarer.api.combat.CombatEngineAPI;
15import com.fs.starfarer.api.combat.CombatFleetManagerAPI;
16import com.fs.starfarer.api.combat.DeployedFleetMemberAPI;
17import com.fs.starfarer.api.combat.ShipAIPlugin;
18import com.fs.starfarer.api.combat.ShipAPI;
19import com.fs.starfarer.api.combat.ShipCommand;
20import com.fs.starfarer.api.combat.ViewportAPI;
21import com.fs.starfarer.api.combat.WeaponGroupAPI;
22import com.fs.starfarer.api.impl.campaign.ids.Stats;
23import com.fs.starfarer.api.impl.hullmods.NeuralInterface;
24import com.fs.starfarer.api.input.InputEventAPI;
25import com.fs.starfarer.api.loading.WeaponGroupSpec;
26import com.fs.starfarer.api.mission.FleetSide;
46 public static class SavedShipControlState {
48 public Map<WeaponGroupAPI, Boolean> autofiring =
new LinkedHashMap<WeaponGroupAPI, Boolean>();
49 public WeaponGroupAPI selected;
62 protected List<ShipAPI>
linked =
new ArrayList<ShipAPI>();
75 savedState.ship = ship;
76 for (WeaponGroupAPI group : ship.getWeaponGroupsCopy()) {
77 savedState.autofiring.put(group, group.isAutofiring());
79 savedState.selected = ship.getSelectedGroupAPI();
87 List<WeaponGroupAPI> groups = ship.getWeaponGroupsCopy();
89 for (WeaponGroupSpec groupSpec : ship.getVariant().getWeaponGroups()) {
90 if (index >= groups.size())
break;
92 boolean auto = groupSpec.isAutofireOnByDefault();
93 WeaponGroupAPI group = groups.get(index);
103 if (groups.size() >= 1) {
104 ship.giveCommand(ShipCommand.SELECT_GROUP,
null, 0);
110 for (WeaponGroupAPI group : ship.getWeaponGroupsCopy()) {
111 Boolean auto =
prevState.autofiring.get(group);
112 if (auto ==
null) auto =
false;
119 int index = ship.getWeaponGroupsCopy().indexOf(
prevState.selected);
121 ship.giveCommand(ShipCommand.SELECT_GROUP,
null, index);
125 public void advance(
float amount, List<InputEventAPI> events) {
126 if (
engine ==
null)
return;
127 if (
engine.isPaused())
return;
130 ShipAPI playerShip =
engine.getPlayerShip();
131 if (playerShip ==
null) {
135 if (!playerShip.isAlive()) {
141 float timeMult = playerShip.getMutableStats().getTimeMult().getModifiedValue();
148 engine.getCombatUI().hideShipInfo();
154 engine.getCombatUI().reFanOutShipInfo();
155 boolean autopilot =
engine.getCombatUI().isAutopilotOn();
157 if (playerShip.getAI() ==
null) {
158 CombatFleetManagerAPI manager =
engine.getFleetManager(FleetSide.PLAYER);
159 DeployedFleetMemberAPI member = manager.getDeployedFleetMember(playerShip);
163 playerShip.setShipAI(
null);
189 playerShip.blockCommandForOneFrame(ShipCommand.FIRE);
190 playerShip.blockCommandForOneFrame(ShipCommand.TOGGLE_AUTOFIRE);
191 playerShip.blockCommandForOneFrame(ShipCommand.PULL_BACK_FIGHTERS);
192 playerShip.blockCommandForOneFrame(ShipCommand.VENT_FLUX);
193 playerShip.blockCommandForOneFrame(ShipCommand.USE_SELECTED_GROUP);
194 playerShip.blockCommandForOneFrame(ShipCommand.USE_SYSTEM);
195 playerShip.blockCommandForOneFrame(ShipCommand.HOLD_FIRE);
197 engine.getCombatUI().setDisablePlayerShipControlOneFrame(
true);
202 ShipAPI playerShip =
engine.getPlayerShip();
203 if (playerShip ==
null)
return;
204 float timeMult = playerShip.getMutableStats().getTimeMult().getModifiedValue();
205 Color color =
new Color(0,121,216,255);
218 engine.addFloatingTextAlways(playerShip.getLocation(),
"Neural transfer in " + show,
219 getFloatySize(playerShip), color, playerShip, 4f * timeMult, 0.8f/timeMult, 1f/timeMult, 0f, 0f,
231 ShipAPI playerShip =
engine.getPlayerShip();
233 if (ship == playerShip && ship.getOriginalCaptain() !=
null &&
234 !ship.getOriginalCaptain().isDefault() && !ship.getOriginalCaptain().isPlayer()) {
238 if (
engine.isInCampaign() ||
engine.isInCampaignSim()) {
239 if (
Global.
getSector().getPlayerStats().getDynamic().getMod(Stats.HAS_NEURAL_LINK).computeEffective(0f) <= 0) {
244 boolean aliveOrDisabledButNonPhysical = ship.isAlive();
245 ShipAPI physicalLocation =
engine.getShipPlayerLastTransferredCommandTo();
246 if (ship == playerShip && ship != physicalLocation) {
247 aliveOrDisabledButNonPhysical =
true;
250 return aliveOrDisabledButNonPhysical && !ship.isShuttlePod() &&
251 ship.getMutableStats().getDynamic().getMod(Stats.HAS_NEURAL_LINK).computeEffective(0f) > 0;
256 ShipAPI playerShip =
engine.getPlayerShip();
257 if (playerShip ==
null)
return;
259 ShipAPI physicalLocation =
engine.getShipPlayerLastTransferredCommandTo();
260 for (ShipAPI ship :
new ArrayList<ShipAPI>(
linked)) {
261 if (!ship.isAlive()) {
262 if (ship == playerShip && ship != physicalLocation) {
266 if (ship != playerShip) {
267 PersonAPI orig = ship.getOriginalCaptain();
268 if (orig.isPlayer()) {
270 if (
engine.isInCampaign() ||
engine.isInCampaignSim()) {
271 orig.setPersonality(
Global.
getSector().getPlayerFaction().pickPersonality());
274 ship.setCaptain(orig);
280 boolean physicallyPresent =
linked.contains(physicalLocation);
281 if (!
linked.contains(playerShip) || !physicallyPresent ||
283 for (ShipAPI ship :
linked) {
284 PersonAPI orig = ship.getOriginalCaptain();
285 if (orig.isPlayer()) {
287 if (
engine.isInCampaign() ||
engine.isInCampaignSim()) {
288 orig.setPersonality(
Global.
getSector().getPlayerFaction().pickPersonality());
291 if (ship.getCaptain() != orig) {
292 ship.setCaptain(orig);
293 if (ship.getFleetMember() !=
null) {
294 ship.getFleetMember().setCaptain(ship.getOriginalCaptain());
304 if (
linked.isEmpty())
return;
307 CombatFleetManagerAPI manager =
engine.getFleetManager(FleetSide.PLAYER);
308 List<DeployedFleetMemberAPI> members = manager.getDeployedCopyDFM();
310 if (physicallyPresent) {
311 for (DeployedFleetMemberAPI dfm : members) {
312 if (
linked.size() >= 2)
break;
314 if (dfm.isFighterWing())
continue;
315 if (dfm.isAlly())
continue;
317 ShipAPI ship = dfm.getShip();
318 if (
linked.contains(ship))
continue;
319 if (!ship.getCaptain().isDefault() && ship != playerShip &&
320 !ship.getCaptain().isPlayer()) {
328 if (ship == playerShip && ship.getOriginalCaptain() !=
null &&
329 !ship.getOriginalCaptain().isDefault() &&
330 !ship.getOriginalCaptain().isPlayer()) {
333 if (ship.controlsLocked())
continue;
342 if (player ==
null) {
343 player = playerShip.getCaptain();
349 for (ShipAPI ship :
linked) {
350 if (ship.getCaptain() != player) {
351 ship.setCaptain(player);
352 if (ship.getFleetMember() !=
null) {
353 ship.getFleetMember().setCaptain(player);
358 if (
linked.contains(playerShip)) {
359 ShipAPI other =
null;
360 for (ShipAPI ship :
linked) {
361 if (ship != playerShip) {
367 String title =
"Neural System Reset";
370 String key = NeuralInterface.SYSTEM_RESET_TIMEOUT_KEY;
373 Float timeout =
null;
374 if (other !=
null) timeout = (Float) other.getCustomData().get(key);
375 if (timeout ==
null) timeout = 0f;
378 }
else if (timeout <= 0) {
379 engine.maintainStatusForPlayerShip(
KEY_STATUS2, icon, title,
"Ready on transfer",
false);
381 int show = (int) Math.ceil(timeout);
382 engine.maintainStatusForPlayerShip(
KEY_STATUS2, icon, title,
"Ready in " + show +
" seconds",
true);
386 for (ShipAPI ship :
linked) {
387 if (ship != playerShip) {
390 String title =
"Neural Link Active";
393 String data =
"Target: " + ship.getHullSpec().getHullNameWithDashClass();
399 String title =
"Neural Transfer";
400 String data =
"Link in " + show +
" seconds";
410 if (
linked.size() <= 1 &&
linked.contains(playerShip)) {
411 String title =
"Neural Link Inactive";
412 String data =
"No signal";
413 if (!physicallyPresent) {
414 data =
"requires physical transfer";
423 if (
engine ==
null ||
engine.getCombatUI() ==
null ||
engine.getCombatUI().isShowingCommandUI())
return;
425 ShipAPI playerShip =
engine.getPlayerShip();
426 if (playerShip ==
null)
return;
427 if (!
linked.contains(playerShip) ||
linked.size() < 2)
return;
430 for (InputEventAPI event : events) {
431 if (event.isConsumed())
continue;
435 for (ShipAPI ship :
linked) {
436 if (ship != playerShip) {
451 if (ship ==
null)
return;
452 ShipAPI playerShip =
engine.getPlayerShip();
453 if (playerShip ==
null)
return;
454 if (!
linked.contains(playerShip))
return;
455 if (!
linked.contains(ship))
return;
461 engine.getCombatUI().reFanOutShipInfo();
476 ShipAIPlugin playerShipAI = playerShip.getShipAI();
477 ShipAIPlugin prevTargetAI = ship.getShipAI();
478 engine.setPlayerShipExternal(ship);
479 if (ship.getFleetMember() !=
null) {
480 ship.getFleetMember().setCaptain(playerShip.getCaptain());
483 if (playerShipAI !=
null) {
484 playerShip.setShipAI(playerShipAI);
487 boolean autopilot =
engine.getCombatUI().isAutopilotOn();
491 ship.setShipAI(prevTargetAI);
496 }
else if (autopilot) {
497 CombatFleetManagerAPI manager =
engine.getFleetManager(FleetSide.PLAYER);
498 DeployedFleetMemberAPI member = manager.getDeployedFleetMember(ship);
513 for (ShipAPI ship :
linked) {
514 if (ship.getFleetMember() ==
null)
continue;
515 total += ship.getFleetMember().getDeploymentPointsCost();
518 total = Math.round(total);
530 time = (float) Math.ceil(time);
543 switch (ship.getHullSize()) {
544 case FIGHTER:
return 15f;
545 case FRIGATE:
return 17f;
546 case DESTROYER:
return 21f;
547 case CRUISER:
return 24f;
548 case CAPITAL_SHIP:
return 27f;
static SettingsAPI getSettings()
static SoundPlayerAPI getSoundPlayer()
static FactoryAPI getFactory()
static SectorAPI getSector()
void suppressControlsDuringTransfer(ShipAPI playerShip)
static float TRANSFER_MIN_SECONDS_IF_NOT_INSTANT
static final String TRANSFER_COMPLETE_KEY
void renderInWorldCoords(ViewportAPI viewport)
static boolean ALLOW_ENGINE_CONTROL_DURING_TRANSFER
void renderInUICoords(ViewportAPI viewport)
static String TRANSFER_CONTROL
SavedShipControlState prevState
void processInputPreCoreControls(float amount, List< InputEventAPI > events)
static float getFloatySize(ShipAPI ship)
void saveControlState(ShipAPI ship)
void restoreControlState(ShipAPI ship)
void init(CombatEngineAPI engine)
void doTransfer(ShipAPI ship)
static float TRANSFER_MAX_SECONDS
static float INSTANT_TRANSFER_DP
void advance(float amount, List< InputEventAPI > events)
static final Object KEY_STATUS2
static final Object KEY_STATUS
void showTranferFloatyIfNeeded()
SavedShipControlState savedState
static float TRANSFER_SECONDS_PER_DP
boolean canLink(ShipAPI ship)
String getSpriteName(String category, String id)
float getScreenWidthPixels()
ShipAIPlugin pickShipAIPlugin(FleetMemberAPI member, ShipAPI ship)
float getScreenHeightPixels()
void applyLowPassFilter(float gain, float gainHF)
SoundAPI playUISound(String id, float pitch, float volume)