diff --git a/README.md b/README.md index 8026cab..1eef3da 100644 --- a/README.md +++ b/README.md @@ -24,49 +24,38 @@ amount of micromanagement needed drastically. To run the mod: -* Download my distribution of ROTP-1.5.jar (large file) and run that instead of +* Download my distribution of ROTP-1.5.1.jar (large file) and run that instead of original game. or -* Download only the ROTP-1.5-governor.jar +* Download only the ROTP-1.5.1-governor.jar * Place it in same directory that contains original Remnants.jar version Beta 1.4 -* Run ROTP-1.5-governor.jar +* Run ROTP-1.5.1-governor.jar To enable governor, use 'q' key on keyboard, or else click "Allocate Spending" -text in the planetary spending screen. Since version 1.5 Governor is on by default. +text in the planetary spending screen. Since version 1.5.1 Governor is on by default. --- Additional features. -* This mod will transport population from planets that are full to planets that +* Since version 1.5 governor will be on by default on new colonies. + +* Governor will transport population from planets that are full to planets that are underpopulated. Population from planets with maximum population will be transported. Only population that will grow back in 1 turn will be transported (usually 1-2 pop). When choosing destination, target population and distance will -be taken into account. If you want to turn this off, add "-Dautotransport=false" -to Java command line like this: - -java -Dautotransport=false -Xmx2560m -jar ROTP-1.5.jar arg1 -or -java -Dautotransport=false -Xmx2560m -jar ROTP-1.5-governor.jar +be taken into account. -* This mod will build stargates on all planets when technology is available. If you -want to turn this off, add "-Dautogate=false" to Java command line. +* Governor will build stargates on Rich and Ultra Rich planets when technology is +available. -java -Dautogate=false -Xmx2560m -jar ROTP-1.5.jar arg1 -or -java -Dautogate=false -Xmx2560m -jar ROTP-1.5-governor.jar - -* Since version 1.5 governor will be on by default on new colonies. If you want to -turn this off, add "-Ddefaultgovernor=false" to Java command line. - -java -Ddefaultgovernor=false -Xmx2560m -jar ROTP-1.5.jar arg1 -or -java -Ddefaultgovernor=false -Xmx2560m -jar ROTP-1.5-governor.jar +GUI has now been added to control behaviour of the governor. Please click "Options" +next to "Allocate Spending" to go to governor options. Old system properties based +options are supported for now but will be dropped in future releases. -* You can add multiple "-Dxxx=yyy" options on command line. I will implement GUI at -some point to toggle these options... +Governor options should be saved in your save game file. --- diff --git a/pom.xml b/pom.xml index 786765a..669b8d2 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.rayfowler ROTP - 1.5 + 1.5.1 UTF-8 diff --git a/src/assembly/governor.xml b/src/assembly/governor.xml index 21c3268..e8f35bb 100644 --- a/src/assembly/governor.xml +++ b/src/assembly/governor.xml @@ -15,6 +15,11 @@ **/EmpireColonySpendingPane*.class **/EmpireSystemPanel*.class **/PlanetsUI*.class + **/GameSession*.class + **/GovernorOptions*.class + **/GovernorOptionsPanel*.class + **/Galaxy*.class + **/en/labels.txt / diff --git a/src/rotp/RotpGovernor.java b/src/rotp/RotpGovernor.java index 5330f31..7c816ed 100644 --- a/src/rotp/RotpGovernor.java +++ b/src/rotp/RotpGovernor.java @@ -24,7 +24,7 @@ * to get more memory it uses the right jar file name. */ public class RotpGovernor { - static String governorVersion = "1.5"; + static String governorVersion = "1.5.1"; static String expectedROTPVersion = "Beta 1.5"; public static void main(String[] args) { diff --git a/src/rotp/lang/en/labels.txt b/src/rotp/lang/en/labels.txt index 669c874..590e290 100644 --- a/src/rotp/lang/en/labels.txt +++ b/src/rotp/lang/en/labels.txt @@ -447,6 +447,7 @@ MAIN_COLONY_INDUSTRY | Ind MAIN_COLONY_ECOLOGY | Eco MAIN_COLONY_TECHNOLOGY | Tech MAIN_COLONY_ALLOCATE_SPENDING | Allocate Spending +GOVERNOR_OPTIONS | Options MAIN_COLONY_SPENDING_NONE | None MAIN_COLONY_SPENDING_RESERVE | Reserve MAIN_COLONY_SPENDING_CONVERT | Convert diff --git a/src/rotp/model/colony/Colony.java b/src/rotp/model/colony/Colony.java index 8d2f353..d1a2c7f 100644 --- a/src/rotp/model/colony/Colony.java +++ b/src/rotp/model/colony/Colony.java @@ -28,6 +28,8 @@ import rotp.model.galaxy.ShipFleet; import rotp.model.galaxy.StarSystem; import rotp.model.galaxy.Transport; +import rotp.model.game.GameSession; +import rotp.model.game.GovernorOptions; import rotp.model.incidents.ColonyCapturedIncident; import rotp.model.incidents.ColonyInvadedIncident; import rotp.model.planet.Planet; @@ -1069,7 +1071,7 @@ public void destroy() { } } - private boolean governor = !"false".equalsIgnoreCase(System.getProperty("defaultgovernor", "true")); + private boolean governor = GameSession.instance().getGovernorOptions().isGovernorOnByDefault(); public boolean isGovernor() { return governor; @@ -1123,7 +1125,7 @@ public void governIfNeeded() { * */ public void govern() { - if (!"false".equalsIgnoreCase(System.getProperty("autotransport"))) { + if (session().getGovernorOptions().isAutotransport()) { autotransport(); } // unlock all sliders @@ -1153,25 +1155,9 @@ public void govern() { if (!defense().isCompleted()) { moveSlider(Colony.DEFENSE, null, "Reserve"); } + // Build gate if tech is available. Also add a system property to turn it off. - if (!"false".equalsIgnoreCase(System.getProperty("autogate"))) { - if (this.shipyard().canBuildStargate()) { - Design first = this.shipyard().design(); - Design current = this.shipyard().design(); - while (!this.empire.shipLab().stargateDesign().equals(current)) { - this.shipyard().goToNextDesign(); - current = this.shipyard().design(); - if (current.equals(first)) { - System.out.println("unable to cycle to Shargate design"); - break; - } - } - if (this.empire.shipLab().stargateDesign().equals(current)) { - locked(Colony.SHIP, false); - moveSlider(Colony.SHIP, null, "Reserve"); - } - } - } + buildStargate(); // if all sliders are set to 0, increase research. boolean noSpending = true; @@ -1278,8 +1264,40 @@ private void autotransport() { scheduleTransportsToSystem(targets.get(0), toTransport); governor = true; } - public int incomingTransportsNextTurn() { + private int incomingTransportsNextTurn() { return galaxy().friendlyPopApproachingSystemNextTurn(starSystem()); } + private void buildStargate() { + if (!this.shipyard().canBuildStargate()) { + return; + } + if (session().getGovernorOptions().getGates() == GovernorOptions.GatesGovernor.None) { + return; + } + if (session().getGovernorOptions().getGates() == GovernorOptions.GatesGovernor.Rich) { + if (!planet().isResourceRich() && !planet.isResourceUltraRich()) { + return; + } + } + // don't build gate if planet production is below 300 + // Not sure about this one, now that maintenance is taken from global pool +// if (production() < 300) { +// return; +// } + Design first = this.shipyard().design(); + Design current = this.shipyard().design(); + while (!this.empire.shipLab().stargateDesign().equals(current)) { + this.shipyard().goToNextDesign(); + current = this.shipyard().design(); + if (current.equals(first)) { + System.out.println("unable to cycle to Shargate design"); + break; + } + } + if (this.empire.shipLab().stargateDesign().equals(current)) { + locked(Colony.SHIP, false); + moveSlider(Colony.SHIP, null, "Reserve"); + } + } } diff --git a/src/rotp/model/game/GameSession.java b/src/rotp/model/game/GameSession.java index 000c6e7..894491e 100644 --- a/src/rotp/model/game/GameSession.java +++ b/src/rotp/model/game/GameSession.java @@ -791,4 +791,14 @@ static ThreadFactory minThreadFactory() { return t; }; } + + private GovernorOptions governorOptions = new GovernorOptions(); + + public GovernorOptions getGovernorOptions() { + // can happen on deserialized stock save game + if (governorOptions == null) { + governorOptions = new GovernorOptions(); + } + return governorOptions; + } } diff --git a/src/rotp/model/game/GovernorOptions.java b/src/rotp/model/game/GovernorOptions.java new file mode 100644 index 0000000..9fab679 --- /dev/null +++ b/src/rotp/model/game/GovernorOptions.java @@ -0,0 +1,45 @@ +package rotp.model.game; + +import java.io.Serializable; + +/** + * Governor options. + */ +public class GovernorOptions implements Serializable { + public enum GatesGovernor { + None, + Rich, + All + } + // keep backwards compatibility with system properties + private boolean governorOnByDefault = !"false".equalsIgnoreCase(System.getProperty("defaultgovernor", "true"));; + private boolean autotransport = !"false".equalsIgnoreCase(System.getProperty("autotransport", "true")); + private GatesGovernor gates = "false".equalsIgnoreCase(System.getProperty("autogate", "true")) ? GatesGovernor.None : GatesGovernor.Rich; + + public GovernorOptions() { + } + + public boolean isGovernorOnByDefault() { + return governorOnByDefault; + } + + public boolean isAutotransport() { + return autotransport; + } + + public GatesGovernor getGates() { + return gates; + } + + public void setGovernorOnByDefault(boolean governorOnByDefault) { + this.governorOnByDefault = governorOnByDefault; + } + + public void setAutotransport(boolean autotransport) { + this.autotransport = autotransport; + } + + public void setGates(GatesGovernor gates) { + this.gates = gates; + } +} diff --git a/src/rotp/ui/main/EmpireColonySpendingPane.java b/src/rotp/ui/main/EmpireColonySpendingPane.java index 5c233f9..ff70a74 100644 --- a/src/rotp/ui/main/EmpireColonySpendingPane.java +++ b/src/rotp/ui/main/EmpireColonySpendingPane.java @@ -34,6 +34,8 @@ import rotp.ui.BasePanel; import rotp.ui.SystemViewer; +import javax.swing.*; + public class EmpireColonySpendingPane extends BasePanel { private static final long serialVersionUID = 1L; static final Color sliderHighlightColor = new Color(255,255,255); @@ -183,6 +185,9 @@ public void paintComponent(Graphics g0) { String titleText = text("MAIN_COLONY_ALLOCATE_SPENDING"); int titleY = getHeight() - s6; drawShadowedString(g, titleText, 2, s5, titleY, color, textC); + + String governorOptionsText = text("GOVERNOR_OPTIONS"); + drawShadowedString(g, governorOptionsText, 2, w-s60, titleY, MainUI.shadeBorderC(), textC); return; } String text = text(Colony.categoryName(category)); @@ -362,7 +367,11 @@ else if (rightArrow.contains(x,y)) increment(true); else { if (this.category < 0) { - toggleGovernor(); + if (x < EmpireColonySpendingPane.this.getWidth() - s60) { + toggleGovernor(); + } else { + governorOptions(); + } } float pct = pctBoxSelected(x,y); if (pct >= 0) { @@ -425,6 +434,28 @@ public float pctBoxSelected(int x, int y) { return num/den; } } + + JFrame governorOptionsFrame = null; + private void governorOptions() { + javax.swing.SwingUtilities.invokeLater(new Runnable() { + public void run() { + if (governorOptionsFrame == null) { + governorOptionsFrame = new JFrame("GovernorOptions"); + governorOptionsFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); + + //Create and set up the content pane. + GovernorOptionsPanel newContentPane = new GovernorOptionsPanel(governorOptionsFrame); + newContentPane.getPanel().setOpaque(true); //content panes must be opaque + governorOptionsFrame.setContentPane(newContentPane.getPanel()); + } + //Display the window. + governorOptionsFrame.pack(); + governorOptionsFrame.setVisible(true); + + } + }); + } + private void toggleGovernor() { if (parent.systemViewToDisplay() != null && parent.systemViewToDisplay().colony() != null) { Colony colony = parent.systemViewToDisplay().colony(); diff --git a/src/rotp/ui/main/GovernorOptionsPanel.java b/src/rotp/ui/main/GovernorOptionsPanel.java new file mode 100644 index 0000000..75833c3 --- /dev/null +++ b/src/rotp/ui/main/GovernorOptionsPanel.java @@ -0,0 +1,153 @@ +package rotp.ui.main; + +import rotp.model.galaxy.StarSystem; +import rotp.model.game.GameSession; +import rotp.model.game.GovernorOptions; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import javax.swing.border.EtchedBorder; +import java.awt.*; + +/** + * Controls + *

+ * [ X ] Governor on by default + * [ X ] Automatically send transports + * [ X ] Turn governor on all colonies + * BOX Stargates + * ( o ) Never build automatically + * ( o ) Rich and Ultra Rich planets + * ( o ) Always build + */ + +public class GovernorOptionsPanel { + private JFrame frame; + private JPanel panel; + private JCheckBox governorDefault; + private JCheckBox autotransport; + private JRadioButton gateNever; + private JRadioButton gateRich; + private JRadioButton gateAlways; + + public GovernorOptionsPanel(JFrame frame) { + this.frame = frame; + panel = new JPanel(); + + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + panel.setBorder(BorderFactory.createLineBorder(Color.red, 1)); + + governorDefault = new JCheckBox("Governor is on by default"); + governorDefault.setBorder(new EmptyBorder(10, 10, 10, 10)); + governorDefault.setSelected(GameSession.instance().getGovernorOptions().isGovernorOnByDefault()); + + panel.add(governorDefault); + autotransport = new JCheckBox("Population automatically transported from full colonies"); + autotransport.setBorder(new EmptyBorder(10, 10, 10, 10)); + autotransport.setSelected(GameSession.instance().getGovernorOptions().isAutotransport()); + panel.add(autotransport); + + panel.add(new Box.Filler(new Dimension(100, 5), new Dimension(100, 20), new Dimension(100, 30))); + JButton allOn = new JButton("All governors ON"); + allOn.addActionListener(e -> { + for (StarSystem ss : GameSession.instance().galaxy().player().orderedColonies()) { + if (!ss.isColonized()) { + // shouldn't happen + continue; + } + ss.colony().setGovernor(true); + } + }); + panel.add(allOn); + panel.add(new Box.Filler(new Dimension(100, 5), new Dimension(100, 20), new Dimension(100, 30))); + JButton allOff = new JButton("All governors OFF"); + allOff.addActionListener(e -> { + for (StarSystem ss : GameSession.instance().galaxy().player().orderedColonies()) { + if (!ss.isColonized()) { + // shouldn't happen + continue; + } + ss.colony().setGovernor(false); + } + }); + panel.add(allOff); + panel.add(new Box.Filler(new Dimension(100, 5), new Dimension(100, 20), new Dimension(100, 30))); + + JPanel radioButtons = new JPanel(); + radioButtons.setLayout(new BoxLayout(radioButtons, BoxLayout.PAGE_AXIS)); + radioButtons.setBorder(BorderFactory.createTitledBorder( + BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), + "Stargate Options")); + ButtonGroup gates = new ButtonGroup(); + gateNever = new JRadioButton("Never build stargates"); + gateRich = new JRadioButton("Build stargates on Rich and Ultra Rich planets"); + gateAlways = new JRadioButton("Always build stargates"); + gates.add(gateNever); + gates.add(gateRich); + gates.add(gateAlways); + radioButtons.add(gateNever); + radioButtons.add(gateRich); + radioButtons.add(gateAlways); + switch (GameSession.instance().getGovernorOptions().getGates()) { + case None: + gateNever.setSelected(true); + break; + case Rich: + gateRich.setSelected(true); + break; + case All: + gateAlways.setSelected(true); + break; + } + panel.add(radioButtons); + + JPanel okCancelButtons = new JPanel(); + JButton ok = new JButton("OK"); + ok.addActionListener(e -> { + GameSession.instance().getGovernorOptions().setGovernorOnByDefault(governorDefault.isSelected()); + GameSession.instance().getGovernorOptions().setAutotransport(autotransport.isSelected()); + if (gateNever.isSelected()) { + GameSession.instance().getGovernorOptions().setGates(GovernorOptions.GatesGovernor.None); + } + if (gateRich.isSelected()) { + GameSession.instance().getGovernorOptions().setGates(GovernorOptions.GatesGovernor.Rich); + } + if (gateAlways.isSelected()) { + GameSession.instance().getGovernorOptions().setGates(GovernorOptions.GatesGovernor.All); + } + frame.setVisible(false); + }); + JButton cancel = new JButton("Cancel"); + cancel.addActionListener(e -> { + frame.setVisible(false); + }); + okCancelButtons.add(ok); + okCancelButtons.add(cancel); + panel.add(okCancelButtons); + } + + public JPanel getPanel() { + return panel; + } + + // for testing + public static void main(String[] args) { + //Schedule a job for the event-dispatching thread: + //creating and showing this application's GUI. + javax.swing.SwingUtilities.invokeLater(new Runnable() { + public void run() { + JFrame frame = new JFrame("GovernorOptions"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + //Create and set up the content pane. + GovernorOptionsPanel newContentPane = new GovernorOptionsPanel(frame); + newContentPane.getPanel().setOpaque(true); //content panes must be opaque + frame.setContentPane(newContentPane.getPanel()); + + //Display the window. + frame.pack(); + frame.setVisible(true); + } + }); + } +}