Skip to content

Commit 1044ef3

Browse files
authored
feat: LunaLib overlay options and relationship-change UI (#2)
1 parent 4db2f3e commit 1044ef3

12 files changed

Lines changed: 322 additions & 61 deletions

FactionRelationships/COMPILATION.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ FactionRelationships/
3939
│ └── com/factionrelationships/
4040
│ ├── FactionRelationshipsPlugin.java
4141
│ ├── FactionRelationshipsUIRenderer.java
42-
│ └── FactionRelationshipsKeybindScript.java
42+
│ ├── FactionRelationshipsCampaignInputListener.java
43+
│ ├── FactionRelationshipsKeybindScript.java # stub for save compatibility
44+
│ ├── FactionRelationshipChangeListener.java
45+
│ ├── RelationshipChangeStore.java
46+
│ └── SystemFactionRelationshipsIntel.java
4347
├── compile.local.example.bat # copy to compile.local.bat (gitignored) to set GAME_DIR
4448
└── COMPILATION.md
4549
```
@@ -62,7 +66,7 @@ set LUNALIB=%GAME_DIR%\mods\LunaLib\jars\LunaLib.jar
6266
set LAZYLIB=%GAME_DIR%\mods\LazyLib\jars\LazyLib.jar
6367
set CORE=%GAME_DIR%\starsector-core
6468
set VERSION=1.3.0
65-
javac -encoding UTF-8 -cp "%CORE%\starfarer.api.jar;%CORE%\starfarer_obf.jar;%CORE%\json.jar;%CORE%\log4j-1.2.9.jar;%CORE%\lwjgl.jar;%CORE%\lwjgl_util.jar;%LAZYLIB%;%LUNALIB%" -d FactionRelationships-%VERSION%\classes FactionRelationships\src\com\factionrelationships\FactionRelationshipsPlugin.java FactionRelationships\src\com\factionrelationships\FactionRelationshipsUIRenderer.java FactionRelationships\src\com\factionrelationships\FactionRelationshipsKeybindScript.java
69+
javac -encoding UTF-8 -cp "%CORE%\starfarer.api.jar;%CORE%\starfarer_obf.jar;%CORE%\json.jar;%CORE%\log4j-1.2.9.jar;%CORE%\lwjgl.jar;%CORE%\lwjgl_util.jar;%LAZYLIB%;%LUNALIB%" -d FactionRelationships-%VERSION%\classes FactionRelationships\src\com\factionrelationships\FactionRelationshipsPlugin.java FactionRelationships\src\com\factionrelationships\FactionRelationshipsUIRenderer.java FactionRelationships\src\com\factionrelationships\FactionRelationshipsCampaignInputListener.java FactionRelationships\src\com\factionrelationships\FactionRelationshipsKeybindScript.java FactionRelationships\src\com\factionrelationships\FactionRelationshipChangeListener.java FactionRelationships\src\com\factionrelationships\RelationshipChangeStore.java FactionRelationships\src\com\factionrelationships\SystemFactionRelationshipsIntel.java
6670
jar cvf FactionRelationships-%VERSION%\jars\FactionRelationships.jar -C FactionRelationships-%VERSION%\classes .
6771
```
6872

@@ -92,7 +96,7 @@ Set `GAME_DIR` (and optionally `LUNALIB`, `LAZYLIB`) before running (e.g. via `c
9296
└── FactionRelationships.jar
9397
```
9498

95-
Configure max factions, text size, overlay keybind (toggle or hold), and hostile-only filter in **Mod Settings** (F2 in campaign).
99+
Configure max factions, text size, overlay keybind (toggle or hold), hostile-only filter, relationship-change display, and auto-show overlay on change in **Mod Settings** (F2 in campaign).
96100

97101
## Quick Reference
98102

FactionRelationships/compile.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ if not exist "%OUT%" mkdir "%OUT%"
3434
if not exist "..\%PKG%\jars" mkdir "..\%PKG%\jars"
3535

3636
echo Compiling...
37-
javac -encoding UTF-8 -cp "%CORE%\starfarer.api.jar;%CORE%\starfarer_obf.jar;%CORE%\json.jar;%CORE%\log4j-1.2.9.jar;%CORE%\lwjgl.jar;%CORE%\lwjgl_util.jar;%LAZYLIB%;%LUNALIB%" -d "%OUT%" "%SRC%\FactionRelationshipsPlugin.java" "%SRC%\FactionRelationshipsUIRenderer.java" "%SRC%\FactionRelationshipsKeybindScript.java"
37+
javac -encoding UTF-8 -cp "%CORE%\starfarer.api.jar;%CORE%\starfarer_obf.jar;%CORE%\json.jar;%CORE%\log4j-1.2.9.jar;%CORE%\lwjgl.jar;%CORE%\lwjgl_util.jar;%LAZYLIB%;%LUNALIB%" -d "%OUT%" "%SRC%\FactionRelationshipsPlugin.java" "%SRC%\FactionRelationshipsUIRenderer.java" "%SRC%\FactionRelationshipsCampaignInputListener.java" "%SRC%\FactionRelationshipsKeybindScript.java" "%SRC%\FactionRelationshipChangeListener.java" "%SRC%\RelationshipChangeStore.java" "%SRC%\SystemFactionRelationshipsIntel.java"
3838
if errorlevel 1 (
3939
echo Compilation failed.
4040
exit /b 1

FactionRelationships/data/config/LunaSettings.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ showOnlyHostile,Show Only Hostile Factions,Boolean,false,,Only display factions
55
textSize,Text Size,Radio,Medium,"Small,Medium,Large",Text size for the overlay. Use [Large] for 4K or high-DPI displays.,,,General
66
overlayKeybindMode,Overlay Keybind Mode,Radio,Toggle,"Toggle,Hold",[Toggle]: Press key to show or hide overlay. [Hold]: Overlay only visible while key is held.,,,General
77
toggleOverlayKeybind,Toggle Overlay Keybind,Keycode,0,,Key to show or hide the faction relationship overlay on the campaign map. Set in Mod Settings (F2). Keycode 0 = unbound.,,,General
8+
showRelationshipChangeInOverlay,Show Relationship Change in Overlay,Boolean,true,,"When a faction relationship changes, show the change (e.g. +5 or -10) next to that faction for the duration set below.",,,General
9+
relationshipChangeDisplaySeconds,Relationship Change Display (seconds),Int,30,,"How long to show the change next to a faction in the overlay, in seconds.",5,120,General
10+
autoShowOverlayOnRelationshipChange,Auto-Show Overlay When Relationship Changes,Boolean,false,,"When a faction relationship changes, automatically show the overlay (for the duration set above).",,,General

FactionRelationships/mod_info.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"id": "factionrelationships",
33
"name": "Faction Relationships",
44
"author": "boop",
5-
"version": "1.3.1",
5+
"version": "1.4.8",
66
"description": "Shows a list of factions and their relationship with the player on the main navigation screen.",
77
"gameVersion": "0.98a-RC8",
88
"jars": ["jars/FactionRelationships.jar"],
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.factionrelationships;
2+
3+
import com.fs.starfarer.api.Global;
4+
import com.fs.starfarer.api.campaign.BaseCampaignEventListener;
5+
import com.fs.starfarer.api.characters.PersonAPI;
6+
import lunalib.lunaSettings.LunaSettings;
7+
8+
/**
9+
* Listens for faction relationship changes and records them for the overlay.
10+
* Registered as a transient listener in onGameLoad so it is not saved with the game.
11+
*/
12+
public class FactionRelationshipChangeListener extends BaseCampaignEventListener {
13+
14+
private static final String AUTO_SHOW_SETTING = "autoShowOverlayOnRelationshipChange";
15+
private static final String DISPLAY_SECONDS_SETTING = "relationshipChangeDisplaySeconds";
16+
private static final int DEFAULT_DISPLAY_SECONDS = 30;
17+
private static final int MIN_DISPLAY_SECONDS = 5;
18+
private static final int MAX_DISPLAY_SECONDS = 120;
19+
20+
public FactionRelationshipChangeListener() {
21+
super(false);
22+
}
23+
24+
private static int getDisplayDurationSeconds() {
25+
if (!FactionRelationshipsPlugin.isLunaLibEnabled()) {
26+
return DEFAULT_DISPLAY_SECONDS;
27+
}
28+
Integer v = LunaSettings.getInt(FactionRelationshipsPlugin.MOD_ID, DISPLAY_SECONDS_SETTING);
29+
if (v == null) {
30+
return DEFAULT_DISPLAY_SECONDS;
31+
}
32+
int sec = v.intValue();
33+
if (sec < MIN_DISPLAY_SECONDS) sec = MIN_DISPLAY_SECONDS;
34+
if (sec > MAX_DISPLAY_SECONDS) sec = MAX_DISPLAY_SECONDS;
35+
return sec;
36+
}
37+
38+
@Override
39+
public void reportPlayerReputationChange(String factionId, float delta) {
40+
long durationMs = getDisplayDurationSeconds() * 1000L;
41+
RelationshipChangeStore.record(factionId, delta, durationMs);
42+
if (FactionRelationshipsPlugin.isLunaLibEnabled()) {
43+
Boolean autoShow = LunaSettings.getBoolean(FactionRelationshipsPlugin.MOD_ID, AUTO_SHOW_SETTING);
44+
if (Boolean.TRUE.equals(autoShow)) {
45+
FactionRelationshipsPlugin.setOverlayVisible(true);
46+
RelationshipChangeStore.setAutoShowExpiry(System.currentTimeMillis() + durationMs);
47+
}
48+
}
49+
}
50+
51+
@Override
52+
public void reportPlayerReputationChange(PersonAPI person, float delta) {
53+
if (person == null || person.getFaction() == null) {
54+
return;
55+
}
56+
reportPlayerReputationChange(person.getFaction().getId(), delta);
57+
}
58+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.factionrelationships;
2+
3+
import com.fs.starfarer.api.Global;
4+
import com.fs.starfarer.api.campaign.listeners.CampaignInputListener;
5+
import com.fs.starfarer.api.input.InputEventAPI;
6+
import lunalib.lunaSettings.LunaSettings;
7+
8+
import java.util.List;
9+
10+
/**
11+
* Handles the overlay toggle keybind on the campaign map using the game's input
12+
* event stream. This runs when the campaign is active (and while paused when
13+
* registered with addListener(..., true)), so the key is detected reliably
14+
* instead of polling {@code Keyboard.isKeyDown} in an EveryFrameScript.
15+
* <p>
16+
* Pattern used by mods like Console Commands and Advanced Weapon Control:
17+
* implement {@link CampaignInputListener} and handle keys in
18+
* {@link #processCampaignInputPreCore(List)}.
19+
*/
20+
public class FactionRelationshipsCampaignInputListener implements CampaignInputListener {
21+
22+
@Override
23+
public int getListenerInputPriority() {
24+
return 0;
25+
}
26+
27+
@Override
28+
public void processCampaignInputPreCore(List<InputEventAPI> events) {
29+
if (!FactionRelationshipsPlugin.isLunaLibEnabled()) {
30+
return;
31+
}
32+
Integer keycodeObj = LunaSettings.getInt(FactionRelationshipsPlugin.MOD_ID, "toggleOverlayKeybind");
33+
if (keycodeObj == null || keycodeObj.intValue() == 0) {
34+
FactionRelationshipsPlugin.setOverlayKeyHeld(false);
35+
return;
36+
}
37+
final int keycode = keycodeObj.intValue();
38+
final String mode = FactionRelationshipsPlugin.getOverlayKeybindMode();
39+
40+
for (InputEventAPI event : events) {
41+
if (event.isConsumed()) {
42+
continue;
43+
}
44+
if (event.isKeyDownEvent() && event.getEventValue() == keycode) {
45+
RelationshipChangeStore.clearAutoShowExpiry();
46+
if ("Hold".equals(mode)) {
47+
FactionRelationshipsPlugin.setOverlayKeyHeld(true);
48+
} else {
49+
FactionRelationshipsPlugin.setOverlayVisible(!FactionRelationshipsPlugin.isOverlayVisible());
50+
}
51+
event.consume();
52+
break;
53+
}
54+
if ("Hold".equals(mode) && event.isKeyUpEvent() && event.getEventValue() == keycode) {
55+
RelationshipChangeStore.clearAutoShowExpiry();
56+
FactionRelationshipsPlugin.setOverlayKeyHeld(false);
57+
event.consume();
58+
break;
59+
}
60+
}
61+
}
62+
63+
@Override
64+
public void processCampaignInputPreFleetControl(List<InputEventAPI> events) {
65+
}
66+
67+
@Override
68+
public void processCampaignInputPostCore(List<InputEventAPI> events) {
69+
}
70+
}
Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
package com.factionrelationships;
22

3-
import com.fs.starfarer.api.Global;
43
import com.fs.starfarer.api.EveryFrameScript;
5-
import lunalib.lunaSettings.LunaSettings;
6-
import org.lwjgl.input.Keyboard;
74

85
/**
9-
* Polls the LunaLib keybind. In Toggle mode: press to show/hide overlay (edge detection).
10-
* In Hold mode: overlay visible only while key is held.
6+
* Stub for save compatibility only. Old saves serialized this script in the
7+
* campaign engine; this class allows them to load. The script reports itself
8+
* done immediately so the engine removes it after load.
119
*/
1210
public class FactionRelationshipsKeybindScript implements EveryFrameScript {
1311

14-
private boolean keyWasDown;
15-
1612
@Override
1713
public boolean isDone() {
18-
return false;
14+
return true;
1915
}
2016

2117
@Override
@@ -25,25 +21,5 @@ public boolean runWhilePaused() {
2521

2622
@Override
2723
public void advance(float amount) {
28-
if (!Global.getSettings().getModManager().isModEnabled("lunalib")) {
29-
return;
30-
}
31-
Integer keycodeObj = LunaSettings.getInt("factionrelationships", "toggleOverlayKeybind");
32-
if (keycodeObj == null || keycodeObj.intValue() == 0) {
33-
FactionRelationshipsPlugin.setOverlayKeyHeld(false);
34-
return;
35-
}
36-
int keycode = keycodeObj.intValue();
37-
boolean keyDown = Keyboard.isKeyDown(keycode);
38-
String mode = FactionRelationshipsPlugin.getOverlayKeybindMode();
39-
if ("Hold".equals(mode)) {
40-
FactionRelationshipsPlugin.setOverlayKeyHeld(keyDown);
41-
} else {
42-
FactionRelationshipsPlugin.setOverlayKeyHeld(false);
43-
if (!keyWasDown && keyDown) {
44-
FactionRelationshipsPlugin.setOverlayVisible(!FactionRelationshipsPlugin.isOverlayVisible());
45-
}
46-
}
47-
keyWasDown = keyDown;
4824
}
4925
}

FactionRelationships/src/com/factionrelationships/FactionRelationshipsPlugin.java

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88

99
public class FactionRelationshipsPlugin extends BaseModPlugin {
1010

11+
/** Mod ID for LunaSettings and mod manager; must match mod_info.json "id". */
12+
public static final String MOD_ID = "factionrelationships";
13+
1114
private static Logger log;
1215

13-
/** Overlay visibility toggle; read by renderer, written by keybind script (Toggle mode). Default true. */
16+
/** Overlay visibility toggle; read by renderer, written by campaign input listener (Toggle mode). Default true. */
1417
private static volatile boolean overlayVisible = true;
1518

1619
/** Key currently held; used in Hold mode so overlay shows only while key is down. */
@@ -41,8 +44,8 @@ public static String getOverlayKeybindMode() {
4144
return cachedOverlayKeybindMode;
4245
}
4346
String mode = "Toggle";
44-
if (Global.getSettings().getModManager().isModEnabled("lunalib")) {
45-
String s = LunaSettings.getString("factionrelationships", "overlayKeybindMode");
47+
if (FactionRelationshipsPlugin.isLunaLibEnabled()) {
48+
String s = LunaSettings.getString(MOD_ID, "overlayKeybindMode");
4649
if (s != null && ("Hold".equalsIgnoreCase(s) || "Toggle".equalsIgnoreCase(s))) {
4750
mode = "Hold".equalsIgnoreCase(s) ? "Hold" : "Toggle";
4851
}
@@ -51,6 +54,11 @@ public static String getOverlayKeybindMode() {
5154
return mode;
5255
}
5356

57+
/** Whether LunaLib is enabled; used for settings and keybinds. */
58+
public static boolean isLunaLibEnabled() {
59+
return Global.getSettings().getModManager().isModEnabled("lunalib");
60+
}
61+
5462
/** Called when LunaSettings change so mode and other caches are re-read. */
5563
public static void invalidateSettingsCache() {
5664
cachedOverlayKeybindMode = null;
@@ -60,11 +68,11 @@ public static void invalidateSettingsCache() {
6068
public void onApplicationLoad() throws Exception {
6169
log = Global.getLogger(FactionRelationshipsPlugin.class);
6270
log.info("Faction Relationships mod loaded.");
63-
if (Global.getSettings().getModManager().isModEnabled("lunalib")) {
71+
if (FactionRelationshipsPlugin.isLunaLibEnabled()) {
6472
LunaSettings.addSettingsListener(new LunaSettingsListener() {
6573
@Override
6674
public void settingsChanged(String modID) {
67-
if ("factionrelationships".equals(modID)) {
75+
if (MOD_ID.equals(modID)) {
6876
FactionRelationshipsPlugin.invalidateSettingsCache();
6977
FactionRelationshipsUIRenderer.invalidateSettingsCache();
7078
}
@@ -76,11 +84,10 @@ public void settingsChanged(String modID) {
7684
@Override
7785
public void onGameLoad(boolean newGame) {
7886
Global.getSector().getListenerManager().addListener(new FactionRelationshipsUIRenderer(), true);
79-
if (Global.getSettings().getModManager().isModEnabled("lunalib")) {
80-
Global.getSector().addScript(new FactionRelationshipsKeybindScript());
81-
}
87+
Global.getSector().getListenerManager().addListener(new FactionRelationshipsCampaignInputListener(), true);
88+
Global.getSector().addTransientListener(new FactionRelationshipChangeListener());
8289
if (log != null) {
83-
log.info("Faction Relationships UI renderer and keybind script registered.");
90+
log.info("Faction Relationships UI renderer, campaign input listener, and relationship change listener registered.");
8491
}
8592
}
8693
}

0 commit comments

Comments
 (0)