From f11e7e7421061e16bbdf0ddefd9ae1c7ad5a5bfb Mon Sep 17 00:00:00 2001 From: S-Numan Date: Tue, 10 Jun 2025 23:31:18 -0700 Subject: [PATCH 01/17] Moderate Bounty Board Revamp Took into account the `job_show_distance` "distance" setting. Removed AssassinationMagicBountyInfo and added into MagicBountyInfo. (why does that class exist anyway?) Handle position of bounty shown to user properly. E.G, no arrow and name showing the destination when only the constellation should be showing, like vanilla! Plot course now follows the above as well. When job_show_distance is "None" or "Distance", plot course is removed entirely. --- src/org/magiclib/bounty/MagicBountyIntel.java | 13 +- .../intel/AssassinationMagicBountyInfo.kt | 98 --------- .../bounty/intel/MagicBountyBoardProvider.kt | 3 - .../magiclib/bounty/intel/MagicBountyInfo.kt | 203 ++++++++++++++---- 4 files changed, 174 insertions(+), 143 deletions(-) delete mode 100644 src/org/magiclib/bounty/intel/AssassinationMagicBountyInfo.kt diff --git a/src/org/magiclib/bounty/MagicBountyIntel.java b/src/org/magiclib/bounty/MagicBountyIntel.java index 3e944d3b..8f2e6d0f 100644 --- a/src/org/magiclib/bounty/MagicBountyIntel.java +++ b/src/org/magiclib/bounty/MagicBountyIntel.java @@ -426,6 +426,13 @@ public void createSmallDescription(TooltipMakerAPI info, float width, float heig Misc.ucFirst(MagicBountyUtilsInternal.getPronoun(bounty.getCaptain())), bounty.getFleetSpawnLocation().getStarSystem().getNameWithLowercaseType()); break; + case Distance: + info.addPara(MagicTxt.getString("mb_distance"), + 10f, + Misc.getTextColor(), + Misc.getHighlightColor(), + Math.round(Misc.getDistanceLY(Global.getSector().getPlayerFleet(), bounty.getFleetSpawnLocation())) + ""); + break; default: info.addPara(MagicBountyUtilsInternal.createLocationEstimateText(bounty), 10f); break; @@ -459,8 +466,10 @@ public SectorEntityToken getMapLocation(SectorMapAPI map) { case Exact: case System: return hideoutLocation; -// case None: -// return null; NOPE, the icon should always be placed somewhere otherwise there is no way to get the location information again. + //case Vague: + case Distance: + case None: + return Global.getSector().getPlayerFleet(); default: // From PersonBountyIntel.getMapLocation Constellation c = hideoutLocation.getConstellation(); diff --git a/src/org/magiclib/bounty/intel/AssassinationMagicBountyInfo.kt b/src/org/magiclib/bounty/intel/AssassinationMagicBountyInfo.kt deleted file mode 100644 index c215da3d..00000000 --- a/src/org/magiclib/bounty/intel/AssassinationMagicBountyInfo.kt +++ /dev/null @@ -1,98 +0,0 @@ -package org.magiclib.bounty.intel - -import com.fs.starfarer.api.Global -import com.fs.starfarer.api.campaign.StarSystemAPI -import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin -import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.BreadcrumbSpecial -import com.fs.starfarer.api.ui.CustomPanelAPI -import com.fs.starfarer.api.ui.MapParams -import com.fs.starfarer.api.ui.TooltipMakerAPI -import com.fs.starfarer.api.util.Misc -import org.magiclib.bounty.MagicBountyLoader -import org.magiclib.bounty.MagicBountySpec -import org.magiclib.kotlin.ucFirst -import org.magiclib.util.MagicTxt -import java.awt.Color -import kotlin.math.roundToInt - -class AssassinationMagicBountyInfo(bountyKey: String, bountySpec: MagicBountySpec) : - MagicBountyInfo(bountyKey, bountySpec) { - override fun showTargetInfo(panel: CustomPanelAPI, width: Float, height: Float): TooltipMakerAPI { - val targetInfoTooltip = panel.createUIElement(width, height, true) - val childPanelWidth = width - 16f - val activeBountyLocal = activeBounty ?: return targetInfoTooltip - - if (bountySpec.job_show_captain) { - val portrait = targetInfoTooltip.beginImageWithText(getJobIcon(), 64f) - var displayName = activeBountyLocal.fleet.commander.nameString - val targetFirstName = activeBountyLocal.captain.name.first - val targetLastName = activeBountyLocal.captain.name.last - if (targetFirstName != null || targetLastName != null) { - displayName = "$targetFirstName $targetLastName" - if (targetFirstName == null || targetFirstName.isEmpty()) - displayName = targetLastName - else if (targetLastName == null || targetLastName.isEmpty()) - displayName = targetFirstName - } - portrait.addPara(displayName, activeBountyLocal.targetFactionTextColor, 0f) - portrait.addPara(activeBountyLocal.fleet.commander.rank.ucFirst(), 2f) - targetInfoTooltip.addImageWithText(0f) - } - - val location = getLocationIfBountyIsActive() - if (location is StarSystemAPI) { - val params = MapParams() - params.showSystem(location) - val w = targetInfoTooltip.widthSoFar - val h = (w / 1.6f).roundToInt().toFloat() - params.positionToShowAllMarkersAndSystems(false, w.coerceAtMost(h)) - params.filterData.fuel = true - params.arrows.add(IntelInfoPlugin.ArrowData(Global.getSector().playerFleet, location.center)) - - val map = targetInfoTooltip.createSectorMap(childPanelWidth, 200f, params, null) - targetInfoTooltip.addCustom(map, 4f) - - if (bountySpec.job_show_distance != MagicBountyLoader.ShowDistance.None) { - when (bountySpec.job_show_distance) { - MagicBountyLoader.ShowDistance.Exact -> targetInfoTooltip.addPara( - createLocationPreciseText(activeBounty!!), - 10f, - location.lightColor, - activeBounty!!.fleetSpawnLocation.starSystem.nameWithLowercaseType - ) - - MagicBountyLoader.ShowDistance.System -> targetInfoTooltip.addPara( - MagicTxt.getString("mb_distance_system"), - 10f, - arrayOf(Misc.getTextColor(), location.lightColor), - MagicTxt.getString("mb_distance_they"), - activeBounty!!.fleetSpawnLocation.starSystem.nameWithLowercaseType - ) - - else -> targetInfoTooltip.addPara( - createLocationEstimateText(activeBounty!!), - 10f, - location.lightColor, - BreadcrumbSpecial.getLocationDescription(activeBounty!!.fleetSpawnLocation, false) - ) - } - } - } else { - targetInfoTooltip.setButtonFontOrbitron20Bold() - targetInfoTooltip.addPara(MagicTxt.getString("mb_descLocationUnknown"), 3f, Color.RED).position.inTMid(2f) - } - - activeBounty?.let { - showFleet(targetInfoTooltip, childPanelWidth, it) - - if (it.spec.job_show_captain) { - targetInfoTooltip.addPara(MagicTxt.getString("mb_hvb_skillsHeader"), 8f) - targetInfoTooltip.addSkillPanel(it.captain, 2f) - } - } - - panel.addUIElement(targetInfoTooltip).inTL(0f, 0f) - - return targetInfoTooltip - } -} \ No newline at end of file diff --git a/src/org/magiclib/bounty/intel/MagicBountyBoardProvider.kt b/src/org/magiclib/bounty/intel/MagicBountyBoardProvider.kt index e3a1f90f..e479964a 100644 --- a/src/org/magiclib/bounty/intel/MagicBountyBoardProvider.kt +++ b/src/org/magiclib/bounty/intel/MagicBountyBoardProvider.kt @@ -9,9 +9,6 @@ class MagicBountyBoardProvider: BountyBoardProvider { .entries .distinctBy { it.key } .map { (key, spec) -> - if (spec.job_type == MagicBountyLoader.JobType.Assassination) - AssassinationMagicBountyInfo(key, spec) - else MagicBountyInfo(key, spec) } } diff --git a/src/org/magiclib/bounty/intel/MagicBountyInfo.kt b/src/org/magiclib/bounty/intel/MagicBountyInfo.kt index c5a4d29e..eac688f5 100644 --- a/src/org/magiclib/bounty/intel/MagicBountyInfo.kt +++ b/src/org/magiclib/bounty/intel/MagicBountyInfo.kt @@ -2,17 +2,16 @@ package org.magiclib.bounty.intel import com.fs.starfarer.api.Global import com.fs.starfarer.api.campaign.LocationAPI +import com.fs.starfarer.api.campaign.SectorEntityToken import com.fs.starfarer.api.campaign.StarSystemAPI import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin -import com.fs.starfarer.api.campaign.rules.MemoryAPI import com.fs.starfarer.api.fleet.FleetMemberAPI import com.fs.starfarer.api.impl.campaign.ids.Factions +import com.fs.starfarer.api.impl.campaign.procgen.Constellation import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.BreadcrumbSpecial -import com.fs.starfarer.api.ui.CustomPanelAPI -import com.fs.starfarer.api.ui.LabelAPI -import com.fs.starfarer.api.ui.MapParams -import com.fs.starfarer.api.ui.TooltipMakerAPI +import com.fs.starfarer.api.ui.* import com.fs.starfarer.api.util.Misc +import org.lwjgl.util.vector.Vector2f import org.magiclib.bounty.ActiveBounty import org.magiclib.bounty.MagicBountyCoordinator import org.magiclib.bounty.MagicBountyLoader.* @@ -20,11 +19,13 @@ import org.magiclib.bounty.MagicBountySpec import org.magiclib.bounty.MagicBountyUtilsInternal import org.magiclib.bounty.ui.InteractiveUIPanelPlugin import org.magiclib.kotlin.setAlpha +import org.magiclib.kotlin.ucFirst import org.magiclib.util.MagicCampaign import org.magiclib.util.MagicTxt import java.awt.Color import kotlin.math.ceil import kotlin.math.roundToInt +import kotlin.text.isEmpty open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpec) : BountyInfo { val activeBounty: ActiveBounty? @@ -278,13 +279,31 @@ open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpe BountyBoardIntelPlugin.refreshPanel(this) } } else if (activeBountyLocal.stage == ActiveBounty.Stage.Accepted) { - val courseButton = - actionTooltip.addButton(MagicTxt.getString("mb_plot_course"), null, rightPanelWidth, 24f, 0f) - rightPanelPlugin.addButton(courseButton) { - courseButton.isChecked = false - Global.getSector().layInCourseFor( - Misc.getDistressJumpPoint(activeBountyLocal.fleet.containingLocation as StarSystemAPI) - ) + + //Add plot course button if there is a clear destination + val dis = activeBountyLocal.spec.job_show_distance + if(dis != ShowDistance.Distance && dis != ShowDistance.None// && dis != ShowDistance.Vague + ) { + + var location: SectorEntityToken? = null + if(dis == ShowDistance.Exact || dis == ShowDistance.System) { + location = Misc.getDistressJumpPoint(activeBountyLocal.fleet.containingLocation as StarSystemAPI) + } else { + val constellation = activeBountyLocal.fleet.constellation + if(constellation != null) + location = createConstellationCenterToken(constellation) + } + + if(location != null) { + val courseButton = + actionTooltip.addButton(MagicTxt.getString("mb_plot_course"), null, rightPanelWidth, 24f, 0f) + rightPanelPlugin.addButton(courseButton) { + courseButton.isChecked = false + Global.getSector().layInCourseFor( + location + ) + } + } } } @@ -455,45 +474,128 @@ open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpe val targetInfoTooltip = panel.createUIElement(width, height, true) val childPanelWidth = width - 16f + val bounty = activeBounty!! + + if (bountySpec.job_type == JobType.Assassination && bountySpec.job_show_captain) { + val portrait = targetInfoTooltip.beginImageWithText(getJobIcon(), 64f) + var displayName = bounty.fleet.commander.nameString + val targetFirstName = bounty.captain.name.first + val targetLastName = bounty.captain.name.last + if (targetFirstName != null || targetLastName != null) { + displayName = "$targetFirstName $targetLastName" + if (targetFirstName == null || targetFirstName.isEmpty()) + displayName = targetLastName + else if (targetLastName == null || targetLastName.isEmpty()) + displayName = targetFirstName + } + portrait.addPara(displayName, bounty.targetFactionTextColor, 0f) + portrait.addPara(bounty.fleet.commander.rank.ucFirst(), 2f) + targetInfoTooltip.addImageWithText(0f) + } + val location = getLocationIfBountyIsActive() if (location is StarSystemAPI) { + val params = MapParams() - params.showSystem(location) val w = targetInfoTooltip.widthSoFar val h = (w / 1.6f).roundToInt().toFloat() - params.positionToShowAllMarkersAndSystems(false, w.coerceAtMost(h)) - params.filterData.fuel = true - params.arrows.add(IntelInfoPlugin.ArrowData(Global.getSector().playerFleet, location.center)) - - val map = targetInfoTooltip.createSectorMap(childPanelWidth, 200f, params, null) - targetInfoTooltip.addCustom(map, 2f) if (bountySpec.job_show_distance != ShowDistance.None) { - val bounty = activeBounty!! when (bountySpec.job_show_distance) { - ShowDistance.Exact -> targetInfoTooltip.addPara( - createLocationPreciseText(bounty), - 10f, - location.lightColor, - bounty.fleetSpawnLocation.starSystem.nameWithLowercaseType - ) + ShowDistance.Exact -> { + params.showSystem(location) + params.arrows.add(IntelInfoPlugin.ArrowData(Global.getSector().playerFleet, location.center)) + + targetInfoTooltip.addPara( + createLocationPreciseText(bounty), + 10f, + location.lightColor, + bounty.fleetSpawnLocation.starSystem.nameWithLowercaseType + ) + } - ShowDistance.System -> targetInfoTooltip.addPara( - MagicTxt.getString("mb_distance_system"), - 10f, - arrayOf(Misc.getTextColor(), location.lightColor), - MagicTxt.getString("mb_distance_they"), - bounty.fleetSpawnLocation.starSystem.nameWithLowercaseType - ) + ShowDistance.System -> { + params.showSystem(location) + params.arrows.add(IntelInfoPlugin.ArrowData(Global.getSector().playerFleet, location.center)) + + targetInfoTooltip.addPara( + MagicTxt.getString("mb_distance_system"), + 10f, + arrayOf(Misc.getTextColor(), location.lightColor), + MagicTxt.getString("mb_distance_they"), + bounty.fleetSpawnLocation.starSystem.nameWithLowercaseType + ) + } - else -> targetInfoTooltip.addPara( - createLocationEstimateText(bounty), - 10f, - location.lightColor, - BreadcrumbSpecial.getLocationDescription(bounty.fleetSpawnLocation, false) - ) + /*ShowDistance.Vague -> { + params.filterData.names = false + + val distance = bounty.fleetSpawnLocation.containingLocation.location.length() + var vague = MagicTxt.getString("mb_distance_core") + if (distance > MagicVariables.getSectorSize() * 0.6f) { + vague = MagicTxt.getString("mb_distance_far") + } else if (distance > MagicVariables.getSectorSize() * 0.33f) { + vague = MagicTxt.getString("mb_distance_close") + } + targetInfoTooltip.addPara( + MagicTxt.getString("mb_distance_vague"), + 10f, + Misc.getTextColor(), + Misc.getHighlightColor(), + vague + ) + }*///Commented out due to seeming to be a bad mechanic with the current implementation of the bounty board. Given pre-existing use of it in some mods (such as Seeker), enabling this on an update may cause issues for some users. + + ShowDistance.Distance -> { + params.filterData.names = false + + targetInfoTooltip.addPara(MagicTxt.getString("mb_distance"), + 10f, + Misc.getTextColor(), + Misc.getHighlightColor(), + Misc.getDistanceLY(Global.getSector().playerFleet, bounty.fleetSpawnLocation).roundToInt().toString()); + } + + else -> { + val constellation = location.constellation + if(constellation != null) { + //Show constellation + params.filterData.constellations = true + params.filterData.names = false + params.showConsellations = setOf(constellation) + params.smallConstellations = true + + //Point towards center of constellation + val token = createConstellationCenterToken(constellation) + if (token != null) { + params.arrows.add(IntelInfoPlugin.ArrowData(Global.getSector().playerFleet, token)) + + params.markers = listOf(MarkerData(token.location, Global.getSector().hyperspace)) + } + + } else { + params.showSystem(location) + params.arrows.add(IntelInfoPlugin.ArrowData(Global.getSector().playerFleet, location.center)) + } + + targetInfoTooltip.addPara( + createLocationEstimateText(bounty), + 10f, + location.lightColor, + BreadcrumbSpecial.getLocationDescription(bounty.fleetSpawnLocation, false) + ) + } } } + + params.positionToShowAllMarkersAndSystems(false, w.coerceAtMost(h)) + params.markers = null//Markers are purely for positioning the camera. Don't render them. + + params.filterData.fuel = true + + val map = targetInfoTooltip.createSectorMap(childPanelWidth, 200f, params, null) + targetInfoTooltip.addCustom(map, 2f) + } else { targetInfoTooltip.setButtonFontOrbitron20Bold() targetInfoTooltip.addPara(MagicTxt.getString("mb_descLocationUnknown"), 3f, Color.RED).position.inTMid(2f) @@ -793,4 +895,25 @@ fun ActiveBounty.calculateCreditReward(): Float? { MagicBountyCoordinator.getInstance().preScalingCreditRewardMultiplier, MagicBountyCoordinator.getInstance().postScalingCreditRewardMultiplier ) -} \ No newline at end of file +} + +fun getConstellationSystemsCenter(constellation: Constellation): Vector2f? { + val systems = constellation.systems + if (systems.isEmpty()) return null + + val total = Vector2f(0f, 0f) + for (system in systems) { + Vector2f.add(total, system.location, total) + } + + total.scale(1f / systems.size) + return total +} + +fun createConstellationCenterToken(constellation: Constellation): SectorEntityToken? { + val center = getConstellationSystemsCenter(constellation) ?: return null + val hyperspace = Global.getSector().hyperspace + + // Create a temporary token at the calculated position + return hyperspace.createToken(center.x, center.y) +} From 35831eabdbfe1f5f93448f01fc0133c4f085ab7c Mon Sep 17 00:00:00 2001 From: S-Numan Date: Fri, 13 Jun 2025 21:15:14 -0700 Subject: [PATCH 02/17] Cleaning up a bit --- .../magiclib/bounty/intel/MagicBountyInfo.kt | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/org/magiclib/bounty/intel/MagicBountyInfo.kt b/src/org/magiclib/bounty/intel/MagicBountyInfo.kt index eac688f5..58b52ff3 100644 --- a/src/org/magiclib/bounty/intel/MagicBountyInfo.kt +++ b/src/org/magiclib/bounty/intel/MagicBountyInfo.kt @@ -496,6 +496,11 @@ open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpe val location = getLocationIfBountyIsActive() if (location is StarSystemAPI) { + fun setupSystemParams(params: MapParams, location: StarSystemAPI) { + params.showSystem(location) + params.arrows.add(IntelInfoPlugin.ArrowData(Global.getSector().playerFleet, location.center)) + } + val params = MapParams() val w = targetInfoTooltip.widthSoFar val h = (w / 1.6f).roundToInt().toFloat() @@ -503,8 +508,7 @@ open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpe if (bountySpec.job_show_distance != ShowDistance.None) { when (bountySpec.job_show_distance) { ShowDistance.Exact -> { - params.showSystem(location) - params.arrows.add(IntelInfoPlugin.ArrowData(Global.getSector().playerFleet, location.center)) + setupSystemParams(params, location) targetInfoTooltip.addPara( createLocationPreciseText(bounty), @@ -515,8 +519,7 @@ open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpe } ShowDistance.System -> { - params.showSystem(location) - params.arrows.add(IntelInfoPlugin.ArrowData(Global.getSector().playerFleet, location.center)) + setupSystemParams(params, location) targetInfoTooltip.addPara( MagicTxt.getString("mb_distance_system"), @@ -549,11 +552,14 @@ open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpe ShowDistance.Distance -> { params.filterData.names = false - targetInfoTooltip.addPara(MagicTxt.getString("mb_distance"), + val distance = Misc.getDistanceLY(Global.getSector().playerFleet, bounty.fleetSpawnLocation).roundToInt() + targetInfoTooltip.addPara( + MagicTxt.getString("mb_distance"), 10f, Misc.getTextColor(), Misc.getHighlightColor(), - Misc.getDistanceLY(Global.getSector().playerFleet, bounty.fleetSpawnLocation).roundToInt().toString()); + distance.toString() + ) } else -> { @@ -569,13 +575,11 @@ open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpe val token = createConstellationCenterToken(constellation) if (token != null) { params.arrows.add(IntelInfoPlugin.ArrowData(Global.getSector().playerFleet, token)) - params.markers = listOf(MarkerData(token.location, Global.getSector().hyperspace)) } } else { - params.showSystem(location) - params.arrows.add(IntelInfoPlugin.ArrowData(Global.getSector().playerFleet, location.center)) + setupSystemParams(params, location) } targetInfoTooltip.addPara( From e7698512086672e0f52b16483cfbea69f5fef9e2 Mon Sep 17 00:00:00 2001 From: S-Numan Date: Fri, 13 Jun 2025 23:18:43 -0700 Subject: [PATCH 03/17] No map when job_show_distance = none --- .../magiclib/bounty/intel/MagicBountyInfo.kt | 147 +++++++++--------- 1 file changed, 73 insertions(+), 74 deletions(-) diff --git a/src/org/magiclib/bounty/intel/MagicBountyInfo.kt b/src/org/magiclib/bounty/intel/MagicBountyInfo.kt index 58b52ff3..9ce8e30b 100644 --- a/src/org/magiclib/bounty/intel/MagicBountyInfo.kt +++ b/src/org/magiclib/bounty/intel/MagicBountyInfo.kt @@ -494,7 +494,8 @@ open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpe } val location = getLocationIfBountyIsActive() - if (location is StarSystemAPI) { + if (location is StarSystemAPI + && bountySpec.job_show_distance != ShowDistance.None) { fun setupSystemParams(params: MapParams, location: StarSystemAPI) { params.showSystem(location) @@ -505,90 +506,88 @@ open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpe val w = targetInfoTooltip.widthSoFar val h = (w / 1.6f).roundToInt().toFloat() - if (bountySpec.job_show_distance != ShowDistance.None) { - when (bountySpec.job_show_distance) { - ShowDistance.Exact -> { - setupSystemParams(params, location) + when (bountySpec.job_show_distance) { + ShowDistance.Exact -> { + setupSystemParams(params, location) - targetInfoTooltip.addPara( - createLocationPreciseText(bounty), - 10f, - location.lightColor, - bounty.fleetSpawnLocation.starSystem.nameWithLowercaseType - ) - } + targetInfoTooltip.addPara( + createLocationPreciseText(bounty), + 10f, + location.lightColor, + bounty.fleetSpawnLocation.starSystem.nameWithLowercaseType + ) + } - ShowDistance.System -> { - setupSystemParams(params, location) + ShowDistance.System -> { + setupSystemParams(params, location) - targetInfoTooltip.addPara( - MagicTxt.getString("mb_distance_system"), - 10f, - arrayOf(Misc.getTextColor(), location.lightColor), - MagicTxt.getString("mb_distance_they"), - bounty.fleetSpawnLocation.starSystem.nameWithLowercaseType - ) - } + targetInfoTooltip.addPara( + MagicTxt.getString("mb_distance_system"), + 10f, + arrayOf(Misc.getTextColor(), location.lightColor), + MagicTxt.getString("mb_distance_they"), + bounty.fleetSpawnLocation.starSystem.nameWithLowercaseType + ) + } - /*ShowDistance.Vague -> { - params.filterData.names = false + /*ShowDistance.Vague -> { + params.filterData.names = false - val distance = bounty.fleetSpawnLocation.containingLocation.location.length() - var vague = MagicTxt.getString("mb_distance_core") - if (distance > MagicVariables.getSectorSize() * 0.6f) { - vague = MagicTxt.getString("mb_distance_far") - } else if (distance > MagicVariables.getSectorSize() * 0.33f) { - vague = MagicTxt.getString("mb_distance_close") - } - targetInfoTooltip.addPara( - MagicTxt.getString("mb_distance_vague"), - 10f, - Misc.getTextColor(), - Misc.getHighlightColor(), - vague - ) - }*///Commented out due to seeming to be a bad mechanic with the current implementation of the bounty board. Given pre-existing use of it in some mods (such as Seeker), enabling this on an update may cause issues for some users. + val distance = bounty.fleetSpawnLocation.containingLocation.location.length() + var vague = MagicTxt.getString("mb_distance_core") + if (distance > MagicVariables.getSectorSize() * 0.6f) { + vague = MagicTxt.getString("mb_distance_far") + } else if (distance > MagicVariables.getSectorSize() * 0.33f) { + vague = MagicTxt.getString("mb_distance_close") + } + targetInfoTooltip.addPara( + MagicTxt.getString("mb_distance_vague"), + 10f, + Misc.getTextColor(), + Misc.getHighlightColor(), + vague + ) + }*///Commented out due to seeming to be a bad mechanic with the current implementation of the bounty board. Given pre-existing use of it in some mods (such as Seeker), enabling this on an update may cause issues for some users. - ShowDistance.Distance -> { - params.filterData.names = false + ShowDistance.Distance -> { + params.filterData.names = false - val distance = Misc.getDistanceLY(Global.getSector().playerFleet, bounty.fleetSpawnLocation).roundToInt() - targetInfoTooltip.addPara( - MagicTxt.getString("mb_distance"), - 10f, - Misc.getTextColor(), - Misc.getHighlightColor(), - distance.toString() - ) - } + val distanceLY = Misc.getDistanceLY(Global.getSector().playerFleet, bounty.fleetSpawnLocation).roundToInt() + targetInfoTooltip.addPara( + MagicTxt.getString("mb_distance"), + 10f, + Misc.getTextColor(), + Misc.getHighlightColor(), + distanceLY.toString() + ) + } - else -> { - val constellation = location.constellation - if(constellation != null) { - //Show constellation - params.filterData.constellations = true - params.filterData.names = false - params.showConsellations = setOf(constellation) - params.smallConstellations = true - - //Point towards center of constellation - val token = createConstellationCenterToken(constellation) - if (token != null) { - params.arrows.add(IntelInfoPlugin.ArrowData(Global.getSector().playerFleet, token)) - params.markers = listOf(MarkerData(token.location, Global.getSector().hyperspace)) - } - - } else { - setupSystemParams(params, location) + else -> { + val constellation = location.constellation + if(constellation != null) { + //Show constellation + params.filterData.constellations = true + params.filterData.names = false + params.showConsellations = setOf(constellation) + params.smallConstellations = true + + //Point towards center of constellation + val token = createConstellationCenterToken(constellation) + if (token != null) { + params.arrows.add(IntelInfoPlugin.ArrowData(Global.getSector().playerFleet, token)) + params.markers = listOf(MarkerData(token.location, Global.getSector().hyperspace)) } - targetInfoTooltip.addPara( - createLocationEstimateText(bounty), - 10f, - location.lightColor, - BreadcrumbSpecial.getLocationDescription(bounty.fleetSpawnLocation, false) - ) + } else { + setupSystemParams(params, location) } + + targetInfoTooltip.addPara( + createLocationEstimateText(bounty), + 10f, + location.lightColor, + BreadcrumbSpecial.getLocationDescription(bounty.fleetSpawnLocation, false) + ) } } From d75ce7d565d776ba1b2cd925c89946dd343a3d87 Mon Sep 17 00:00:00 2001 From: S-Numan Date: Sat, 14 Feb 2026 08:21:46 -0800 Subject: [PATCH 04/17] Sorting UI less --- src/org/magiclib/bounty/intel/BountyInfo.kt | 5 ++ .../bounty/intel/BountyListPanelPlugin.kt | 50 ++++++++++++++++ .../magiclib/bounty/intel/MagicBountyInfo.kt | 57 +++++++++++++++---- 3 files changed, 102 insertions(+), 10 deletions(-) diff --git a/src/org/magiclib/bounty/intel/BountyInfo.kt b/src/org/magiclib/bounty/intel/BountyInfo.kt index 98299e4c..1d8dc6fb 100644 --- a/src/org/magiclib/bounty/intel/BountyInfo.kt +++ b/src/org/magiclib/bounty/intel/BountyInfo.kt @@ -20,7 +20,12 @@ interface BountyInfo : Filterable { fun getBountyPayout(): Int fun getJobIcon(): String? fun getLocationIfBountyIsActive(): LocationAPI? + fun getPlayerKnownDistanceIfBountyIsActive(): Float? + fun getSortIndex(): Int = 1 + fun getSortIndexOffset(): Int + fun setSortIndexOffset(value: Int) + fun addNotificationBulletpoints(info: TooltipMakerAPI) { } diff --git a/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt b/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt index 35496273..9bdbf3a4 100644 --- a/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt +++ b/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt @@ -35,7 +35,57 @@ class BountyListPanelPlugin(parentPanel: CustomPanelAPI) : FilteredListPanelPlug return listOf(item.getBountyType()) } + enum class Order { + ASCENDING, + DESCENDING, + } + private var orderBy = Order.ASCENDING + fun getOrderBy(): Order = orderBy + fun setOrderBy(value: Order) { + orderBy = value + } + + enum class SortingMethod { + ALPHABETICAL, + CREDITS, + KNOWNDISTANCE, + FIRSTCREATED, + } + private var sortBy = SortingMethod.FIRSTCREATED + fun getSortBy(): SortingMethod = sortBy + fun setSortBy(value: SortingMethod) { + sortBy = value + } + override fun sortMembers(items: List): List { + + // Sort by the selected method + var sorted = when (sortBy) { + SortingMethod.CREDITS -> + items.sortedBy { it.getBountyPayout() } + + SortingMethod.KNOWNDISTANCE -> + items.sortedWith( + compareBy(nullsLast()) { it.getPlayerKnownDistanceIfBountyIsActive() } + ) + + SortingMethod.FIRSTCREATED -> + items.sortedBy { (it as? MagicBountyInfo)?.activeBounty?.bountyCreatedTimestamp } + + SortingMethod.ALPHABETICAL -> + items.sortedBy { it.getBountyName() } + } + + // Reverse if descending + if (orderBy == Order.DESCENDING) { + sorted = sorted.reversed() + } + + // Assign sortIndexOffset + sorted.forEachIndexed { index, item -> + item.setSortIndexOffset(index) + } + return super.sortMembers(items) .sortedBy { it.getSortIndex() } } diff --git a/src/org/magiclib/bounty/intel/MagicBountyInfo.kt b/src/org/magiclib/bounty/intel/MagicBountyInfo.kt index 9ce8e30b..8c04edcf 100644 --- a/src/org/magiclib/bounty/intel/MagicBountyInfo.kt +++ b/src/org/magiclib/bounty/intel/MagicBountyInfo.kt @@ -61,18 +61,53 @@ open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpe return activeBounty?.fleetSpawnLocation?.containingLocation } + override fun getPlayerKnownDistanceIfBountyIsActive(): Float? { + getLocationIfBountyIsActive() ?: return null + val bounty = activeBounty ?: return null + val playerFleet = Global.getSector().playerFleet + + return when (bountySpec.job_show_distance) { + ShowDistance.None, + ShowDistance.Vague -> null + + ShowDistance.Distance -> + Misc.getDistanceLY(playerFleet, bounty.fleetSpawnLocation) + + ShowDistance.Exact, + ShowDistance.System -> { + val system = bounty.fleet.containingLocation as? StarSystemAPI ?: return null + val jumpPoint = Misc.getDistressJumpPoint(system) + Misc.getDistanceLY(playerFleet, jumpPoint) + } + + else -> { + val constellation = bounty.fleet.constellation ?: return null + val token = createConstellationCenterToken(constellation) ?: return null + Misc.getDistanceLY(playerFleet, token) + } + } + } + + private var sortIndexOffset: Int = 0 + override fun getSortIndexOffset(): Int = sortIndexOffset + override fun setSortIndexOffset(value: Int) { + sortIndexOffset = value + } + override fun getSortIndex(): Int { - return when (activeBounty?.stage) { + val baseIndex = when (activeBounty?.stage) { ActiveBounty.Stage.Accepted -> 0 - ActiveBounty.Stage.NotAccepted -> 1 - ActiveBounty.Stage.Succeeded -> 3 - ActiveBounty.Stage.ExpiredAfterAccepting -> 4 - ActiveBounty.Stage.ExpiredWithoutAccepting -> 4 - ActiveBounty.Stage.FailedSalvagedFlagship -> 4 - ActiveBounty.Stage.EndedWithoutPlayerInvolvement -> 4 - ActiveBounty.Stage.Dismissed -> 4 - else -> 1 + ActiveBounty.Stage.NotAccepted -> 100000 + ActiveBounty.Stage.Succeeded -> 300000 + ActiveBounty.Stage.ExpiredAfterAccepting -> 400000 + ActiveBounty.Stage.ExpiredWithoutAccepting -> 400000 + ActiveBounty.Stage.FailedSalvagedFlagship -> 400000 + ActiveBounty.Stage.EndedWithoutPlayerInvolvement -> 400000 + ActiveBounty.Stage.Dismissed -> 400000 + else -> 100000 } + + return baseIndex + sortIndexOffset } override fun notifyWhenAvailable(): Boolean { @@ -287,7 +322,9 @@ open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpe var location: SectorEntityToken? = null if(dis == ShowDistance.Exact || dis == ShowDistance.System) { - location = Misc.getDistressJumpPoint(activeBountyLocal.fleet.containingLocation as StarSystemAPI) + val system = activeBountyLocal.fleet.containingLocation as? StarSystemAPI + if(system != null) + location = Misc.getDistressJumpPoint(system) } else { val constellation = activeBountyLocal.fleet.constellation if(constellation != null) From e831daf9ba8fc023e95244a59a1573285ba0b673 Mon Sep 17 00:00:00 2001 From: S-Numan Date: Sat, 14 Feb 2026 12:07:59 -0800 Subject: [PATCH 05/17] Functioning UI --- src/org/magiclib/bounty/intel/BountyInfo.kt | 11 +- .../bounty/intel/BountyListPanelPlugin.kt | 62 +------ .../bounty/intel/filters/LocationParam.kt | 4 +- .../bounty/intel/filters/PayoutParam.kt | 4 +- .../intel/sorters/TogglePrimarySorter.kt | 160 ++++++++++++++++++ .../bounty/ui/lists/sorted/ListSort.kt | 21 +++ .../ui/lists/sorted/SortedListPanelPlugin.kt | 132 +++++++++++++++ 7 files changed, 328 insertions(+), 66 deletions(-) create mode 100644 src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt create mode 100644 src/org/magiclib/bounty/ui/lists/sorted/ListSort.kt create mode 100644 src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt diff --git a/src/org/magiclib/bounty/intel/BountyInfo.kt b/src/org/magiclib/bounty/intel/BountyInfo.kt index 1d8dc6fb..d193390f 100644 --- a/src/org/magiclib/bounty/intel/BountyInfo.kt +++ b/src/org/magiclib/bounty/intel/BountyInfo.kt @@ -8,12 +8,11 @@ import com.fs.starfarer.api.impl.campaign.ids.Tags import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.BreadcrumbSpecial import com.fs.starfarer.api.ui.TooltipMakerAPI import org.magiclib.bounty.ActiveBounty -import org.magiclib.bounty.intel.filters.LocationParam -import org.magiclib.bounty.ui.lists.filtered.Filterable -import org.magiclib.bounty.ui.lists.filtered.FilterableParam +import org.magiclib.bounty.ui.lists.sorted.Sortable +import org.magiclib.bounty.ui.lists.sorted.SortableParam import org.magiclib.util.MagicTxt -interface BountyInfo : Filterable { +interface BountyInfo : Sortable { fun getBountyId(): String fun getBountyName(): String fun getBountyType(): String @@ -54,9 +53,9 @@ interface BountyInfo : Filterable { fun layoutPanel(tooltip: TooltipMakerAPI, width: Float, height: Float) - override fun getFilterData(): List> { + override fun getSorterData(): List> { return mutableListOf( - LocationParam(this) + //LocatioParam(this) ) } diff --git a/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt b/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt index 9bdbf3a4..d4edcbb7 100644 --- a/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt +++ b/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt @@ -7,16 +7,16 @@ import com.fs.starfarer.api.ui.TooltipMakerAPI import com.fs.starfarer.api.ui.UIPanelAPI import com.fs.starfarer.api.util.Misc import org.lwjgl.opengl.GL11 -import org.magiclib.bounty.intel.filters.LocationFilter +import org.magiclib.bounty.intel.sorters.TogglePrimarySorter import org.magiclib.bounty.ui.BaseUIPanelPlugin import org.magiclib.bounty.ui.lists.ListItemUIPanelPlugin -import org.magiclib.bounty.ui.lists.filtered.FilteredListPanelPlugin -import org.magiclib.bounty.ui.lists.filtered.ListFilter +import org.magiclib.bounty.ui.lists.sorted.ListSorter +import org.magiclib.bounty.ui.lists.sorted.SortedListPanelPlugin import org.magiclib.kotlin.setAlpha import org.magiclib.util.MagicTxt import java.awt.Color -class BountyListPanelPlugin(parentPanel: CustomPanelAPI) : FilteredListPanelPlugin(parentPanel) { +class BountyListPanelPlugin(parentPanel: CustomPanelAPI) : SortedListPanelPlugin(parentPanel) { override val rowWidth get() = panelWidth - 4f override val rowHeight = 68f @@ -27,65 +27,15 @@ class BountyListPanelPlugin(parentPanel: CustomPanelAPI) : FilteredListPanelPlug private var selectedItem: BountyInfo? = null private var finalItem: BountyInfo? = null - override fun getApplicableFilters(): List> { - return listOf(LocationFilter()) + override fun getApplicableSorters(): List> { + return listOf(TogglePrimarySorter()) } override fun getFiltersFromItem(item: BountyInfo): List { return listOf(item.getBountyType()) } - enum class Order { - ASCENDING, - DESCENDING, - } - private var orderBy = Order.ASCENDING - fun getOrderBy(): Order = orderBy - fun setOrderBy(value: Order) { - orderBy = value - } - - enum class SortingMethod { - ALPHABETICAL, - CREDITS, - KNOWNDISTANCE, - FIRSTCREATED, - } - private var sortBy = SortingMethod.FIRSTCREATED - fun getSortBy(): SortingMethod = sortBy - fun setSortBy(value: SortingMethod) { - sortBy = value - } - override fun sortMembers(items: List): List { - - // Sort by the selected method - var sorted = when (sortBy) { - SortingMethod.CREDITS -> - items.sortedBy { it.getBountyPayout() } - - SortingMethod.KNOWNDISTANCE -> - items.sortedWith( - compareBy(nullsLast()) { it.getPlayerKnownDistanceIfBountyIsActive() } - ) - - SortingMethod.FIRSTCREATED -> - items.sortedBy { (it as? MagicBountyInfo)?.activeBounty?.bountyCreatedTimestamp } - - SortingMethod.ALPHABETICAL -> - items.sortedBy { it.getBountyName() } - } - - // Reverse if descending - if (orderBy == Order.DESCENDING) { - sorted = sorted.reversed() - } - - // Assign sortIndexOffset - sorted.forEachIndexed { index, item -> - item.setSortIndexOffset(index) - } - return super.sortMembers(items) .sortedBy { it.getSortIndex() } } diff --git a/src/org/magiclib/bounty/intel/filters/LocationParam.kt b/src/org/magiclib/bounty/intel/filters/LocationParam.kt index e3eab555..f5563fc4 100644 --- a/src/org/magiclib/bounty/intel/filters/LocationParam.kt +++ b/src/org/magiclib/bounty/intel/filters/LocationParam.kt @@ -1,4 +1,4 @@ -package org.magiclib.bounty.intel.filters +/*package org.magiclib.bounty.intel.filters import com.fs.starfarer.api.Global import com.fs.starfarer.api.campaign.LocationAPI @@ -191,4 +191,4 @@ class LocationFilter : ListFilter { if (ly < 0) ly = 0f return ly } -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/org/magiclib/bounty/intel/filters/PayoutParam.kt b/src/org/magiclib/bounty/intel/filters/PayoutParam.kt index ba9bd54c..30231af0 100644 --- a/src/org/magiclib/bounty/intel/filters/PayoutParam.kt +++ b/src/org/magiclib/bounty/intel/filters/PayoutParam.kt @@ -1,4 +1,4 @@ -package org.magiclib.bounty.intel.filters +/*package org.magiclib.bounty.intel.filters import com.fs.starfarer.api.Global import com.fs.starfarer.api.ui.CustomPanelAPI @@ -106,4 +106,4 @@ class PayoutFilter : ListFilter { } override fun isActive(): Boolean = payoutMinimum > -1 -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt new file mode 100644 index 00000000..408f19b5 --- /dev/null +++ b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt @@ -0,0 +1,160 @@ +package org.magiclib.bounty.intel.sorters + +import com.fs.starfarer.api.Global +import com.fs.starfarer.api.campaign.LocationAPI +import com.fs.starfarer.api.ui.ButtonAPI +import com.fs.starfarer.api.ui.CustomPanelAPI +import com.fs.starfarer.api.ui.TooltipMakerAPI +import org.magiclib.bounty.intel.BountyInfo +import org.magiclib.bounty.intel.MagicBountyInfo +import org.magiclib.bounty.ui.InteractiveUIPanelPlugin +import org.magiclib.bounty.ui.lists.sorted.ListSorter +import org.magiclib.bounty.ui.lists.sorted.Sortable + +class TogglePrimarySorter : ListSorter { + + enum class Order { + ASCENDING, + DESCENDING, + } + private var orderBy = Order.ASCENDING + fun getOrderBy(): Order = orderBy + fun setOrderBy(value: Order) { + orderBy = value + } + + enum class SortingMethod { + ALPHABETICAL, + CREDITS, + KNOWNDISTANCE, + FIRSTCREATED, + } + private var sortBy = SortingMethod.FIRSTCREATED + fun getSortBy(): SortingMethod = sortBy + fun setSortBy(value: SortingMethod) { + sortBy = value + } + + override fun createPanel( + tooltip: TooltipMakerAPI, + width: Float, + lastItems: List> + ): CustomPanelAPI { + //val validBounties = lastItems + // .map { it as BountyInfo } + + val filterPlugin = InteractiveUIPanelPlugin() + val filterPanel = Global.getSettings().createCustom(width, 64f, filterPlugin) + + //checkbox tooltip + val toggleGroupTooltip = filterPanel.createUIElement(width, 64f, false) + + + val orderTogglesData = listOf( + "Ascending" to Order.ASCENDING, + "Descending" to Order.DESCENDING + ) + + var currentOrderSelected: ButtonAPI? = null + + orderTogglesData.forEachIndexed { index, (label, order) -> + val checkbox = toggleGroupTooltip.addCheckbox(16f, 16f, label, null, ButtonAPI.UICheckboxSize.SMALL, if(index == 0) 0f else 4f) + + // Check the current order by default + if (orderBy == order) { + checkbox.isChecked = true + currentOrderSelected = checkbox + } + + filterPlugin.addCheckbox(checkbox) { checked -> + if (checked) { + currentOrderSelected?.let { if (it != checkbox) it.isChecked = false } + currentOrderSelected = checkbox + orderBy = order + } else { + currentOrderSelected?.isChecked = true + } + } + } + + toggleGroupTooltip.addSpacer(12f) + + val togglesData = listOf( + "Credits" to SortingMethod.CREDITS, + "Distance" to SortingMethod.KNOWNDISTANCE, + "Time Posted" to SortingMethod.FIRSTCREATED, + "Alphabetical" to SortingMethod.ALPHABETICAL + ) + + var currentSelected: ButtonAPI? = null + + togglesData.forEachIndexed { index, (label, method) -> + val checkbox = toggleGroupTooltip.addCheckbox(16f, 16f, label, null, ButtonAPI.UICheckboxSize.SMALL, if(index == 0) 0f else 4f) + if (sortBy == method) { + checkbox.isChecked = true + currentSelected = checkbox + } + filterPlugin.addCheckbox(checkbox) { checked -> + if (checked) { + currentSelected?.let { if (it != checkbox) it.isChecked = false } + currentSelected = checkbox + sortBy = method + } else { + currentSelected?.isChecked = true + } + } + } + + filterPanel.addUIElement(toggleGroupTooltip).inTMid(2f) + tooltip.addCustomDoNotSetPosition(filterPanel) + + return filterPanel + } + + override fun saveToPersistentData() { + Global.getSector().persistentData["MagicLib.LocationSorter.sortBy"] = sortBy + Global.getSector().persistentData["MagicLib.LocationSorter.orderBy"] = orderBy + } + + override fun loadFromPersistentData(members: List) { + if (Global.getSector().persistentData.containsKey("MagicLib.LocationSorter.sortBy")) + sortBy = Global.getSector().persistentData["MagicLib.LocationSorter.sortBy"] as SortingMethod + if (Global.getSector().persistentData.containsKey("MagicLib.LocationSorter.orderBy")) + orderBy = Global.getSector().persistentData["MagicLib.LocationSorter.orderBy"] as Order + + sortMembers(members) + } + + fun sortMembers(items: List) { + + var sorted = when (getSortBy()) { + SortingMethod.CREDITS -> + items.sortedBy { it.getBountyPayout() } + + SortingMethod.KNOWNDISTANCE -> + items.sortedWith( + compareBy(nullsLast()) { it.getPlayerKnownDistanceIfBountyIsActive() } + ) + + SortingMethod.FIRSTCREATED -> + items.sortedBy { (it as? MagicBountyInfo)?.activeBounty?.bountyCreatedTimestamp } + + SortingMethod.ALPHABETICAL -> + items.sortedBy { it.getBountyName() } + } + + // Reverse if descending + if (getOrderBy() == Order.DESCENDING) { + sorted = sorted.reversed() + } + + // Assign sortIndexOffset + sorted.forEachIndexed { index, item -> + item.setSortIndexOffset(index) + } + } + + override fun isActive(): Boolean { + return true + } +} \ No newline at end of file diff --git a/src/org/magiclib/bounty/ui/lists/sorted/ListSort.kt b/src/org/magiclib/bounty/ui/lists/sorted/ListSort.kt new file mode 100644 index 00000000..500b69da --- /dev/null +++ b/src/org/magiclib/bounty/ui/lists/sorted/ListSort.kt @@ -0,0 +1,21 @@ +package org.magiclib.bounty.ui.lists.sorted + +import com.fs.starfarer.api.ui.CustomPanelAPI +import com.fs.starfarer.api.ui.TooltipMakerAPI + +interface ListSorter, V> { + fun createPanel(tooltip: TooltipMakerAPI, width: Float, lastItems: List>): CustomPanelAPI + + fun saveToPersistentData() + fun loadFromPersistentData(members: List) + + fun isActive(): Boolean +} + +abstract class SortableParam(val item: T) { + abstract fun getData(): V? +} + +interface Sortable { + fun getSorterData(): List> +} \ No newline at end of file diff --git a/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt b/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt new file mode 100644 index 00000000..ed9e9a44 --- /dev/null +++ b/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt @@ -0,0 +1,132 @@ +package org.magiclib.bounty.ui.lists.sorted + +import com.fs.starfarer.api.ui.* +import org.magiclib.bounty.ui.ButtonHandler +import org.magiclib.bounty.ui.InteractiveUIPanelPlugin +import org.magiclib.bounty.ui.lists.ListUIPanelPlugin +import org.magiclib.util.MagicTxt + +abstract class SortedListPanelPlugin>(parentPanel: CustomPanelAPI) : + ListUIPanelPlugin(parentPanel) { + var filterButton: ButtonAPI? = null + var filterContainerPanel: CustomPanelAPI? = null + var filtersForItems: List> = getApplicableSorters() + + protected abstract fun getApplicableSorters(): List> + + override fun layoutPanels(members: List): CustomPanelAPI { + if (outerPanel != null) { + outerTooltip!!.removeComponent(innerPanel) + outerPanel!!.removeComponent(outerTooltip) + clearItems() + } + + val outerPanelLocal = outerPanel ?: parentPanel.createCustomPanel(panelWidth, panelHeight, this) + outerPanel = outerPanelLocal + + filtersForItems.forEach { it.loadFromPersistentData(members) } + var validMembers = members.filter { shouldMakePanelForItem(it) } + lastMembers = validMembers + validMembers = sortMembers(validMembers) + + val outerTooltipLocal = outerPanelLocal.createUIElement(panelWidth, panelHeight, false) + outerTooltip = outerTooltipLocal + + createListHeader(outerTooltipLocal) + + val buttonHeight = 20f + val filterButtonLocal = outerTooltipLocal.addButton( + filterButtonText(), + null, + panelWidth - 4f, + buttonHeight, + 2f + ) + filterButton = filterButtonLocal + this.buttons[filterButtonLocal] = FilterButtonHandler() + filterButtonLocal.position.inTMid(22f) + + val listHeight = panelHeight - buttonHeight - 22f + val holdingPanel = outerPanelLocal.createCustomPanel(panelWidth, listHeight, null) + innerPanel = holdingPanel + + val scrollerTooltip: TooltipMakerAPI = holdingPanel.createUIElement(panelWidth, listHeight, true) + val scrollingPanel: CustomPanelAPI = + holdingPanel.createCustomPanel(panelWidth, getListHeight(validMembers.size) + buttonHeight + 22f, null) + val tooltip: TooltipMakerAPI = + scrollingPanel.createUIElement(panelWidth, getListHeight(validMembers.size) + buttonHeight + 22f, false) + + var lastItem: UIPanelAPI? = null + validMembers + .map { it to createPanelForItem(tooltip, it) } + .filter { (_, rowPlugin) -> rowPlugin != null } + .forEach { (item, rowPlugin) -> + lastItem = placeItem(tooltip, rowPlugin!!, lastItem) + } + + scrollingPanel.addUIElement(tooltip).inTL(0f, 0f) + scrollerTooltip.addCustom(scrollingPanel, 0f).position.inTL(0f, 0f) + holdingPanel.addUIElement(scrollerTooltip).inTL(0f, 0f) + outerTooltipLocal.addCustom(holdingPanel, 0f).position.belowMid(filterButtonLocal, 2f) + outerPanelLocal.addUIElement(outerTooltipLocal).inTL(0f, 0f) + this.parentPanel.addComponent(outerPanelLocal).inTL(0f, 0f) + scroller = scrollerTooltip.externalScroller + + return outerPanelLocal + } + + protected fun createFilterPanel() { + val filterContainerPanelPlugin = InteractiveUIPanelPlugin() + filterContainerPanelPlugin.renderBackground = true + filterContainerPanelPlugin.eatAllClicks = true + + val filterContainerPanelLocal = + outerPanel!!.createCustomPanel(panelWidth, panelHeight * 0.33f, filterContainerPanelPlugin) + filterContainerPanel = filterContainerPanelLocal + + val filterContainerTooltip = filterContainerPanelLocal.createUIElement(panelWidth, panelHeight * 0.33f, true) + var lastItem: UIComponentAPI? = null + + filtersForItems.forEach { + val filterPanel = it.createPanel(filterContainerTooltip, panelWidth - 4f, lastMembers!!) + if (lastItem != null) { + filterPanel.position.belowMid(lastItem, 4f).setXAlignOffset(-3f) + } else { + filterPanel.position.inTMid(4f).setXAlignOffset(-3f) + } + lastItem = filterPanel + } + + filterContainerTooltip.addSpacer(1f) // For some reason the tooltip contents fail to show without this + filterContainerPanelLocal.addUIElement(filterContainerTooltip).inBMid(4f) + + outerPanel!!.addComponent(filterContainerPanelLocal).inTMid(46f) + } + + fun closeFilterPanel() { + filtersForItems.forEach { it.saveToPersistentData() } + outerPanel!!.removeComponent(filterContainerPanel) + filterContainerPanel = null + + layoutPanels() + } + + protected abstract fun getFiltersFromItem(item: T): List + + inner class FilterButtonHandler : ButtonHandler() { + override fun onClicked() { + filterButton!!.isChecked = false + if (this@SortedListPanelPlugin.filterContainerPanel == null) { + filterButton!!.text = MagicTxt.getString("mb_confirm") + createFilterPanel() + } else { + filterButton!!.text = + filterButtonText() + closeFilterPanel() + } + } + } + + private fun filterButtonText() = + MagicTxt.getString("mb_filters") + if (filtersForItems.any { it.isActive() }) " (${filtersForItems.count { it.isActive() }})" else "" +} \ No newline at end of file From 18fe25783539eacf89f13265a8d2275117138181 Mon Sep 17 00:00:00 2001 From: S-Numan Date: Sat, 14 Feb 2026 12:41:04 -0800 Subject: [PATCH 06/17] Patch distance --- .../magiclib/bounty/intel/MagicBountyInfo.kt | 18 ++++++------------ .../intel/sorters/TogglePrimarySorter.kt | 8 +++----- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/org/magiclib/bounty/intel/MagicBountyInfo.kt b/src/org/magiclib/bounty/intel/MagicBountyInfo.kt index 8c04edcf..43623d18 100644 --- a/src/org/magiclib/bounty/intel/MagicBountyInfo.kt +++ b/src/org/magiclib/bounty/intel/MagicBountyInfo.kt @@ -67,22 +67,16 @@ open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpe val playerFleet = Global.getSector().playerFleet return when (bountySpec.job_show_distance) { - ShowDistance.None, - ShowDistance.Vague -> null - - ShowDistance.Distance -> - Misc.getDistanceLY(playerFleet, bounty.fleetSpawnLocation) + //ShowDistance.Vague, + ShowDistance.None-> null + ShowDistance.Distance, ShowDistance.Exact, - ShowDistance.System -> { - val system = bounty.fleet.containingLocation as? StarSystemAPI ?: return null - val jumpPoint = Misc.getDistressJumpPoint(system) - Misc.getDistanceLY(playerFleet, jumpPoint) - } + ShowDistance.System -> + Misc.getDistanceLY(playerFleet, bounty.fleetSpawnLocation) else -> { - val constellation = bounty.fleet.constellation ?: return null - val token = createConstellationCenterToken(constellation) ?: return null + val token = bounty.fleet.constellation?.let { createConstellationCenterToken(it) } ?: bounty.fleetSpawnLocation Misc.getDistanceLY(playerFleet, token) } } diff --git a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt index 408f19b5..4e90de93 100644 --- a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt +++ b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt @@ -80,10 +80,10 @@ class TogglePrimarySorter : ListSorter { toggleGroupTooltip.addSpacer(12f) val togglesData = listOf( - "Credits" to SortingMethod.CREDITS, + "Alphabetical" to SortingMethod.ALPHABETICAL, "Distance" to SortingMethod.KNOWNDISTANCE, + "Credits" to SortingMethod.CREDITS, "Time Posted" to SortingMethod.FIRSTCREATED, - "Alphabetical" to SortingMethod.ALPHABETICAL ) var currentSelected: ButtonAPI? = null @@ -132,9 +132,7 @@ class TogglePrimarySorter : ListSorter { items.sortedBy { it.getBountyPayout() } SortingMethod.KNOWNDISTANCE -> - items.sortedWith( - compareBy(nullsLast()) { it.getPlayerKnownDistanceIfBountyIsActive() } - ) + items.sortedBy { it.getPlayerKnownDistanceIfBountyIsActive() ?: Float.MAX_VALUE } SortingMethod.FIRSTCREATED -> items.sortedBy { (it as? MagicBountyInfo)?.activeBounty?.bountyCreatedTimestamp } From 23c487832f2611beba12532e4ff40b30de48b5d9 Mon Sep 17 00:00:00 2001 From: S-Numan Date: Sat, 14 Feb 2026 13:50:30 -0800 Subject: [PATCH 07/17] nonEnemyToBottom --- .../intel/sorters/TogglePrimarySorter.kt | 60 ++++++++++++++++--- 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt index 4e90de93..74a2c62e 100644 --- a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt +++ b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt @@ -10,9 +10,12 @@ import org.magiclib.bounty.intel.MagicBountyInfo import org.magiclib.bounty.ui.InteractiveUIPanelPlugin import org.magiclib.bounty.ui.lists.sorted.ListSorter import org.magiclib.bounty.ui.lists.sorted.Sortable +import org.magiclib.kotlin.getMarketsInLocation class TogglePrimarySorter : ListSorter { + private var nonEnemyToBottom = true + enum class Order { ASCENDING, DESCENDING, @@ -58,7 +61,7 @@ class TogglePrimarySorter : ListSorter { var currentOrderSelected: ButtonAPI? = null orderTogglesData.forEachIndexed { index, (label, order) -> - val checkbox = toggleGroupTooltip.addCheckbox(16f, 16f, label, null, ButtonAPI.UICheckboxSize.SMALL, if(index == 0) 0f else 4f) + val checkbox = toggleGroupTooltip.addCheckbox(20f, 16f, label, null, ButtonAPI.UICheckboxSize.SMALL, if(index == 0) 0f else 4f) // Check the current order by default if (orderBy == order) { @@ -89,7 +92,7 @@ class TogglePrimarySorter : ListSorter { var currentSelected: ButtonAPI? = null togglesData.forEachIndexed { index, (label, method) -> - val checkbox = toggleGroupTooltip.addCheckbox(16f, 16f, label, null, ButtonAPI.UICheckboxSize.SMALL, if(index == 0) 0f else 4f) + val checkbox = toggleGroupTooltip.addCheckbox(20f, 16f, label, null, ButtonAPI.UICheckboxSize.SMALL, if(index == 0) 0f else 4f) if (sortBy == method) { checkbox.isChecked = true currentSelected = checkbox @@ -105,6 +108,15 @@ class TogglePrimarySorter : ListSorter { } } + + toggleGroupTooltip.addSpacer(12f) + + val nonEnemyToBottomButton = toggleGroupTooltip.addCheckbox(20f, 16f, "Send non-enemies in civilized systems to the bottom", null, ButtonAPI.UICheckboxSize.SMALL, 4f) + nonEnemyToBottomButton.isChecked = nonEnemyToBottom + filterPlugin.addCheckbox(nonEnemyToBottomButton) { checked -> + nonEnemyToBottom = checked + } + filterPanel.addUIElement(toggleGroupTooltip).inTMid(2f) tooltip.addCustomDoNotSetPosition(filterPanel) @@ -114,6 +126,7 @@ class TogglePrimarySorter : ListSorter { override fun saveToPersistentData() { Global.getSector().persistentData["MagicLib.LocationSorter.sortBy"] = sortBy Global.getSector().persistentData["MagicLib.LocationSorter.orderBy"] = orderBy + Global.getSector().persistentData["MagicLib.LocationSorter.nonEnemyToBottom"] = nonEnemyToBottom } override fun loadFromPersistentData(members: List) { @@ -121,13 +134,15 @@ class TogglePrimarySorter : ListSorter { sortBy = Global.getSector().persistentData["MagicLib.LocationSorter.sortBy"] as SortingMethod if (Global.getSector().persistentData.containsKey("MagicLib.LocationSorter.orderBy")) orderBy = Global.getSector().persistentData["MagicLib.LocationSorter.orderBy"] as Order + if (Global.getSector().persistentData.containsKey("MagicLib.LocationSorter.nonEnemyToBottom")) + nonEnemyToBottom = Global.getSector().persistentData["MagicLib.LocationSorter.nonEnemyToBottom"] as Boolean sortMembers(members) } fun sortMembers(items: List) { - var sorted = when (getSortBy()) { + val sorted = when (getSortBy()) { SortingMethod.CREDITS -> items.sortedBy { it.getBountyPayout() } @@ -135,21 +150,52 @@ class TogglePrimarySorter : ListSorter { items.sortedBy { it.getPlayerKnownDistanceIfBountyIsActive() ?: Float.MAX_VALUE } SortingMethod.FIRSTCREATED -> - items.sortedBy { (it as? MagicBountyInfo)?.activeBounty?.bountyCreatedTimestamp } + items.sortedBy { (it as? MagicBountyInfo)?.activeBounty?.bountyCreatedTimestamp }.reversed() SortingMethod.ALPHABETICAL -> items.sortedBy { it.getBountyName() } - } + }.toMutableList() // Reverse if descending if (getOrderBy() == Order.DESCENDING) { - sorted = sorted.reversed() + sorted.reverse() } - // Assign sortIndexOffset + if (nonEnemyToBottom) { + val sector = Global.getSector() + val playerFaction = sector.playerFaction + + val (keep, moveToBottom) = sorted.partition { entry -> + val bounty = (entry as? MagicBountyInfo)?.activeBounty + ?: return@partition true + + val nameee = bounty.spec.job_name + + val faction = bounty.targetFaction ?: return@partition true + val system = bounty.fleetSpawnLocation.starSystem ?: return@partition true + + val isCoreFaction = faction.isShowInIntelTab + val isNotEnemy = !faction.isHostileTo(playerFaction) + + val hasLargeMarketInSystem = system.getMarketsInLocation(faction.id)?.any { market -> + market.factionId == faction.id && market.size >= 4 + } == true + + // keep everything that does NOT match all conditions + !(isCoreFaction && isNotEnemy && hasLargeMarketInSystem) + } + + sorted.clear() + sorted.addAll(keep) + sorted.addAll(moveToBottom) + } + + + // Assign sortIndexOffset sorted.forEachIndexed { index, item -> item.setSortIndexOffset(index) } + } override fun isActive(): Boolean { From 7243aad83dd0237f7bea6b362be98e6ea13a8b9e Mon Sep 17 00:00:00 2001 From: S-Numan Date: Sat, 14 Feb 2026 13:51:53 -0800 Subject: [PATCH 08/17] remove debug --- src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt index 74a2c62e..a1154e62 100644 --- a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt +++ b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt @@ -168,9 +168,7 @@ class TogglePrimarySorter : ListSorter { val (keep, moveToBottom) = sorted.partition { entry -> val bounty = (entry as? MagicBountyInfo)?.activeBounty ?: return@partition true - - val nameee = bounty.spec.job_name - + val faction = bounty.targetFaction ?: return@partition true val system = bounty.fleetSpawnLocation.starSystem ?: return@partition true From 9af9bfa1ac530c0a7d68791e60606424d8f73065 Mon Sep 17 00:00:00 2001 From: S-Numan Date: Sat, 14 Feb 2026 15:13:48 -0800 Subject: [PATCH 09/17] Color red --- src/org/magiclib/bounty/intel/BountyInfo.kt | 3 +++ .../bounty/intel/BountyListPanelPlugin.kt | 9 ++++++--- .../magiclib/bounty/intel/MagicBountyInfo.kt | 17 +++++++++++++++++ .../bounty/intel/sorters/TogglePrimarySorter.kt | 17 ++++++++++------- 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/org/magiclib/bounty/intel/BountyInfo.kt b/src/org/magiclib/bounty/intel/BountyInfo.kt index d193390f..5ac44c48 100644 --- a/src/org/magiclib/bounty/intel/BountyInfo.kt +++ b/src/org/magiclib/bounty/intel/BountyInfo.kt @@ -25,6 +25,9 @@ interface BountyInfo : Sortable { fun getSortIndexOffset(): Int fun setSortIndexOffset(value: Int) + fun getNonEnemyToBottom(): Boolean + fun setNonEnemyToBottom(value: Boolean) + fun addNotificationBulletpoints(info: TooltipMakerAPI) { } diff --git a/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt b/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt index d4edcbb7..b3a0bb19 100644 --- a/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt +++ b/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt @@ -142,9 +142,12 @@ class BountyListPanelPlugin(parentPanel: CustomPanelAPI) : SortedListPanelPlugin ListItemUIPanelPlugin(item) { private var wasHovered: Boolean = false private var wasSelected: Boolean = false - var baseBgColor: Color = Color(255, 255, 255, 0) - var hoveredColor: Color = Misc.getBasePlayerColor().setAlpha(75) - var selectedColor: Color = Misc.getBasePlayerColor().setAlpha(125) + val defaultBgColor: Color = Color(255, 255, 255, 0) + val defaultHoveredColor: Color = Misc.getBasePlayerColor().setAlpha(75) + val defaultSelectedColor: Color = Misc.getBasePlayerColor().setAlpha(125) + var baseBgColor: Color = defaultBgColor + var hoveredColor: Color = defaultHoveredColor + var selectedColor: Color = defaultSelectedColor override var bgColor: Color = baseBgColor override fun layoutPanel(tooltip: TooltipMakerAPI): CustomPanelAPI { diff --git a/src/org/magiclib/bounty/intel/MagicBountyInfo.kt b/src/org/magiclib/bounty/intel/MagicBountyInfo.kt index 43623d18..c332ff07 100644 --- a/src/org/magiclib/bounty/intel/MagicBountyInfo.kt +++ b/src/org/magiclib/bounty/intel/MagicBountyInfo.kt @@ -18,6 +18,7 @@ import org.magiclib.bounty.MagicBountyLoader.* import org.magiclib.bounty.MagicBountySpec import org.magiclib.bounty.MagicBountyUtilsInternal import org.magiclib.bounty.ui.InteractiveUIPanelPlugin +import org.magiclib.kotlin.interpolateColor import org.magiclib.kotlin.setAlpha import org.magiclib.kotlin.ucFirst import org.magiclib.util.MagicCampaign @@ -33,6 +34,12 @@ open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpe var holdingPanel: CustomPanelAPI? = null var panelThatCanBeRemoved: CustomPanelAPI? = null + private var nonEnemyToBottom: Boolean = false + override fun getNonEnemyToBottom(): Boolean = nonEnemyToBottom + override fun setNonEnemyToBottom(value: Boolean) { + nonEnemyToBottom = value + } + override fun getBountyId(): String { return bountyKey } @@ -256,6 +263,16 @@ open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpe plugin.baseBgColor = Misc.getDarkHighlightColor().setAlpha(45) plugin.hoveredColor = Misc.getDarkHighlightColor().setAlpha(75) plugin.selectedColor = Misc.getDarkHighlightColor().setAlpha(125) + } else if (nonEnemyToBottom) { + val colRed = Color(255, 0, 0, 75) + + plugin.baseBgColor = colRed.setAlpha(40) + plugin.hoveredColor = plugin.defaultHoveredColor.interpolateColor(colRed, 0.4f) + plugin.selectedColor = plugin.defaultSelectedColor.interpolateColor(colRed, 0.4f) + } else { + plugin.baseBgColor = plugin.defaultBgColor + plugin.hoveredColor = plugin.defaultHoveredColor + plugin.selectedColor = plugin.defaultSelectedColor } } diff --git a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt index a1154e62..96c2370a 100644 --- a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt +++ b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt @@ -10,6 +10,7 @@ import org.magiclib.bounty.intel.MagicBountyInfo import org.magiclib.bounty.ui.InteractiveUIPanelPlugin import org.magiclib.bounty.ui.lists.sorted.ListSorter import org.magiclib.bounty.ui.lists.sorted.Sortable +import org.magiclib.internalextensions.addTooltip import org.magiclib.kotlin.getMarketsInLocation class TogglePrimarySorter : ListSorter { @@ -43,9 +44,6 @@ class TogglePrimarySorter : ListSorter { width: Float, lastItems: List> ): CustomPanelAPI { - //val validBounties = lastItems - // .map { it as BountyInfo } - val filterPlugin = InteractiveUIPanelPlugin() val filterPanel = Global.getSettings().createCustom(width, 64f, filterPlugin) @@ -111,7 +109,11 @@ class TogglePrimarySorter : ListSorter { toggleGroupTooltip.addSpacer(12f) - val nonEnemyToBottomButton = toggleGroupTooltip.addCheckbox(20f, 16f, "Send non-enemies in civilized systems to the bottom", null, ButtonAPI.UICheckboxSize.SMALL, 4f) + val nonEnemyToBottomButton = toggleGroupTooltip.addCheckbox(20f, 16f, "Drop non-hostiles in populated areas", null, ButtonAPI.UICheckboxSize.SMALL, 4f) + toggleGroupTooltip.addTooltip(nonEnemyToBottomButton, TooltipMakerAPI.TooltipLocation.BELOW, 600f) { + it.addPara("When enabled, non-hostile bounty targets located in systems with a size 4 or larger friendly market will be moved to the bottom of the list and colored red.", 0f) + it.addPara("E.G: If killing a bounty target would unavoidably trigger a war with a faction.", 8f) + } nonEnemyToBottomButton.isChecked = nonEnemyToBottom filterPlugin.addCheckbox(nonEnemyToBottomButton) { checked -> nonEnemyToBottom = checked @@ -161,6 +163,7 @@ class TogglePrimarySorter : ListSorter { sorted.reverse() } + sorted.forEach { it.setNonEnemyToBottom(false) } if (nonEnemyToBottom) { val sector = Global.getSector() val playerFaction = sector.playerFaction @@ -168,7 +171,7 @@ class TogglePrimarySorter : ListSorter { val (keep, moveToBottom) = sorted.partition { entry -> val bounty = (entry as? MagicBountyInfo)?.activeBounty ?: return@partition true - + val faction = bounty.targetFaction ?: return@partition true val system = bounty.fleetSpawnLocation.starSystem ?: return@partition true @@ -186,10 +189,10 @@ class TogglePrimarySorter : ListSorter { sorted.clear() sorted.addAll(keep) sorted.addAll(moveToBottom) + moveToBottom.forEach { it.setNonEnemyToBottom(true) } } - - // Assign sortIndexOffset + // Assign sortIndexOffset sorted.forEachIndexed { index, item -> item.setSortIndexOffset(index) } From 022f91dad7ce89c0f8d1e4a70626a2256d280759 Mon Sep 17 00:00:00 2001 From: S-Numan Date: Sat, 14 Feb 2026 15:22:46 -0800 Subject: [PATCH 10/17] Renaming --- .../bounty/intel/BountyListPanelPlugin.kt | 2 +- .../intel/sorters/TogglePrimarySorter.kt | 18 ++-- .../ui/lists/sorted/SortedListPanelPlugin.kt | 82 +++++++++---------- 3 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt b/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt index b3a0bb19..34716120 100644 --- a/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt +++ b/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt @@ -31,7 +31,7 @@ class BountyListPanelPlugin(parentPanel: CustomPanelAPI) : SortedListPanelPlugin return listOf(TogglePrimarySorter()) } - override fun getFiltersFromItem(item: BountyInfo): List { + override fun getSortersFromItem(item: BountyInfo): List { return listOf(item.getBountyType()) } diff --git a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt index 96c2370a..8e5cc0a3 100644 --- a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt +++ b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt @@ -44,11 +44,11 @@ class TogglePrimarySorter : ListSorter { width: Float, lastItems: List> ): CustomPanelAPI { - val filterPlugin = InteractiveUIPanelPlugin() - val filterPanel = Global.getSettings().createCustom(width, 64f, filterPlugin) + val sorterPlugin = InteractiveUIPanelPlugin() + val sorterPanel = Global.getSettings().createCustom(width, 64f, sorterPlugin) //checkbox tooltip - val toggleGroupTooltip = filterPanel.createUIElement(width, 64f, false) + val toggleGroupTooltip = sorterPanel.createUIElement(width, 64f, false) val orderTogglesData = listOf( @@ -67,7 +67,7 @@ class TogglePrimarySorter : ListSorter { currentOrderSelected = checkbox } - filterPlugin.addCheckbox(checkbox) { checked -> + sorterPlugin.addCheckbox(checkbox) { checked -> if (checked) { currentOrderSelected?.let { if (it != checkbox) it.isChecked = false } currentOrderSelected = checkbox @@ -95,7 +95,7 @@ class TogglePrimarySorter : ListSorter { checkbox.isChecked = true currentSelected = checkbox } - filterPlugin.addCheckbox(checkbox) { checked -> + sorterPlugin.addCheckbox(checkbox) { checked -> if (checked) { currentSelected?.let { if (it != checkbox) it.isChecked = false } currentSelected = checkbox @@ -115,14 +115,14 @@ class TogglePrimarySorter : ListSorter { it.addPara("E.G: If killing a bounty target would unavoidably trigger a war with a faction.", 8f) } nonEnemyToBottomButton.isChecked = nonEnemyToBottom - filterPlugin.addCheckbox(nonEnemyToBottomButton) { checked -> + sorterPlugin.addCheckbox(nonEnemyToBottomButton) { checked -> nonEnemyToBottom = checked } - filterPanel.addUIElement(toggleGroupTooltip).inTMid(2f) - tooltip.addCustomDoNotSetPosition(filterPanel) + sorterPanel.addUIElement(toggleGroupTooltip).inTMid(2f) + tooltip.addCustomDoNotSetPosition(sorterPanel) - return filterPanel + return sorterPanel } override fun saveToPersistentData() { diff --git a/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt b/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt index ed9e9a44..7ffa3c99 100644 --- a/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt +++ b/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt @@ -8,9 +8,9 @@ import org.magiclib.util.MagicTxt abstract class SortedListPanelPlugin>(parentPanel: CustomPanelAPI) : ListUIPanelPlugin(parentPanel) { - var filterButton: ButtonAPI? = null - var filterContainerPanel: CustomPanelAPI? = null - var filtersForItems: List> = getApplicableSorters() + var sorterButton: ButtonAPI? = null + var sorterContainerPanel: CustomPanelAPI? = null + var sortersForItems: List> = getApplicableSorters() protected abstract fun getApplicableSorters(): List> @@ -24,7 +24,7 @@ abstract class SortedListPanelPlugin>(parentPanel: CustomPanelAP val outerPanelLocal = outerPanel ?: parentPanel.createCustomPanel(panelWidth, panelHeight, this) outerPanel = outerPanelLocal - filtersForItems.forEach { it.loadFromPersistentData(members) } + sortersForItems.forEach { it.loadFromPersistentData(members) } var validMembers = members.filter { shouldMakePanelForItem(it) } lastMembers = validMembers validMembers = sortMembers(validMembers) @@ -35,16 +35,16 @@ abstract class SortedListPanelPlugin>(parentPanel: CustomPanelAP createListHeader(outerTooltipLocal) val buttonHeight = 20f - val filterButtonLocal = outerTooltipLocal.addButton( - filterButtonText(), + val sorterButtonLocal = outerTooltipLocal.addButton( + sorterButtonText(), null, panelWidth - 4f, buttonHeight, 2f ) - filterButton = filterButtonLocal - this.buttons[filterButtonLocal] = FilterButtonHandler() - filterButtonLocal.position.inTMid(22f) + sorterButton = sorterButtonLocal + this.buttons[sorterButtonLocal] = SorterButtonHandler() + sorterButtonLocal.position.inTMid(22f) val listHeight = panelHeight - buttonHeight - 22f val holdingPanel = outerPanelLocal.createCustomPanel(panelWidth, listHeight, null) @@ -67,7 +67,7 @@ abstract class SortedListPanelPlugin>(parentPanel: CustomPanelAP scrollingPanel.addUIElement(tooltip).inTL(0f, 0f) scrollerTooltip.addCustom(scrollingPanel, 0f).position.inTL(0f, 0f) holdingPanel.addUIElement(scrollerTooltip).inTL(0f, 0f) - outerTooltipLocal.addCustom(holdingPanel, 0f).position.belowMid(filterButtonLocal, 2f) + outerTooltipLocal.addCustom(holdingPanel, 0f).position.belowMid(sorterButtonLocal, 2f) outerPanelLocal.addUIElement(outerTooltipLocal).inTL(0f, 0f) this.parentPanel.addComponent(outerPanelLocal).inTL(0f, 0f) scroller = scrollerTooltip.externalScroller @@ -75,58 +75,58 @@ abstract class SortedListPanelPlugin>(parentPanel: CustomPanelAP return outerPanelLocal } - protected fun createFilterPanel() { - val filterContainerPanelPlugin = InteractiveUIPanelPlugin() - filterContainerPanelPlugin.renderBackground = true - filterContainerPanelPlugin.eatAllClicks = true + protected fun createSorterPanel() { + val sorterContainerPanelPlugin = InteractiveUIPanelPlugin() + sorterContainerPanelPlugin.renderBackground = true + sorterContainerPanelPlugin.eatAllClicks = true - val filterContainerPanelLocal = - outerPanel!!.createCustomPanel(panelWidth, panelHeight * 0.33f, filterContainerPanelPlugin) - filterContainerPanel = filterContainerPanelLocal + val SorterContainerPanelLocal = + outerPanel!!.createCustomPanel(panelWidth, panelHeight * 0.33f, sorterContainerPanelPlugin) + sorterContainerPanel = SorterContainerPanelLocal - val filterContainerTooltip = filterContainerPanelLocal.createUIElement(panelWidth, panelHeight * 0.33f, true) + val sorterContainerTooltip = SorterContainerPanelLocal.createUIElement(panelWidth, panelHeight * 0.33f, true) var lastItem: UIComponentAPI? = null - filtersForItems.forEach { - val filterPanel = it.createPanel(filterContainerTooltip, panelWidth - 4f, lastMembers!!) + sortersForItems.forEach { + val sorterPanel = it.createPanel(sorterContainerTooltip, panelWidth - 4f, lastMembers!!) if (lastItem != null) { - filterPanel.position.belowMid(lastItem, 4f).setXAlignOffset(-3f) + sorterPanel.position.belowMid(lastItem, 4f).setXAlignOffset(-3f) } else { - filterPanel.position.inTMid(4f).setXAlignOffset(-3f) + sorterPanel.position.inTMid(4f).setXAlignOffset(-3f) } - lastItem = filterPanel + lastItem = sorterPanel } - filterContainerTooltip.addSpacer(1f) // For some reason the tooltip contents fail to show without this - filterContainerPanelLocal.addUIElement(filterContainerTooltip).inBMid(4f) + sorterContainerTooltip.addSpacer(1f) // For some reason the tooltip contents fail to show without this + SorterContainerPanelLocal.addUIElement(sorterContainerTooltip).inBMid(4f) - outerPanel!!.addComponent(filterContainerPanelLocal).inTMid(46f) + outerPanel!!.addComponent(SorterContainerPanelLocal).inTMid(46f) } - fun closeFilterPanel() { - filtersForItems.forEach { it.saveToPersistentData() } - outerPanel!!.removeComponent(filterContainerPanel) - filterContainerPanel = null + fun closeSorterPanel() { + sortersForItems.forEach { it.saveToPersistentData() } + outerPanel!!.removeComponent(sorterContainerPanel) + sorterContainerPanel = null layoutPanels() } - protected abstract fun getFiltersFromItem(item: T): List + protected abstract fun getSortersFromItem(item: T): List - inner class FilterButtonHandler : ButtonHandler() { + inner class SorterButtonHandler : ButtonHandler() { override fun onClicked() { - filterButton!!.isChecked = false - if (this@SortedListPanelPlugin.filterContainerPanel == null) { - filterButton!!.text = MagicTxt.getString("mb_confirm") - createFilterPanel() + sorterButton!!.isChecked = false + if (this@SortedListPanelPlugin.sorterContainerPanel == null) { + sorterButton!!.text = MagicTxt.getString("mb_confirm") + createSorterPanel() } else { - filterButton!!.text = - filterButtonText() - closeFilterPanel() + sorterButton!!.text = + sorterButtonText() + closeSorterPanel() } } } - private fun filterButtonText() = - MagicTxt.getString("mb_filters") + if (filtersForItems.any { it.isActive() }) " (${filtersForItems.count { it.isActive() }})" else "" + private fun sorterButtonText() = + MagicTxt.getString("mb_sort") } \ No newline at end of file From 18236599ec1238158398771edc5cf4491e7c44b4 Mon Sep 17 00:00:00 2001 From: S-Numan Date: Mon, 16 Feb 2026 09:52:28 -0800 Subject: [PATCH 11/17] set offset to 0 on first sorter to account for others --- src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt index 8e5cc0a3..39332142 100644 --- a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt +++ b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt @@ -143,6 +143,7 @@ class TogglePrimarySorter : ListSorter { } fun sortMembers(items: List) { + items.forEach { it.setSortIndexOffset(0) } val sorted = when (getSortBy()) { SortingMethod.CREDITS -> From c74953987efb8160ff43bdd5a57ae51ee7158de7 Mon Sep 17 00:00:00 2001 From: S-Numan Date: Mon, 16 Feb 2026 09:52:39 -0800 Subject: [PATCH 12/17] variable name change --- .../bounty/ui/lists/sorted/SortedListPanelPlugin.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt b/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt index 7ffa3c99..48ce6d41 100644 --- a/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt +++ b/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt @@ -80,11 +80,11 @@ abstract class SortedListPanelPlugin>(parentPanel: CustomPanelAP sorterContainerPanelPlugin.renderBackground = true sorterContainerPanelPlugin.eatAllClicks = true - val SorterContainerPanelLocal = + val sorterContainerPanelLocal = outerPanel!!.createCustomPanel(panelWidth, panelHeight * 0.33f, sorterContainerPanelPlugin) - sorterContainerPanel = SorterContainerPanelLocal + sorterContainerPanel = sorterContainerPanelLocal - val sorterContainerTooltip = SorterContainerPanelLocal.createUIElement(panelWidth, panelHeight * 0.33f, true) + val sorterContainerTooltip = sorterContainerPanelLocal.createUIElement(panelWidth, panelHeight * 0.33f, true) var lastItem: UIComponentAPI? = null sortersForItems.forEach { @@ -98,9 +98,9 @@ abstract class SortedListPanelPlugin>(parentPanel: CustomPanelAP } sorterContainerTooltip.addSpacer(1f) // For some reason the tooltip contents fail to show without this - SorterContainerPanelLocal.addUIElement(sorterContainerTooltip).inBMid(4f) + sorterContainerPanelLocal.addUIElement(sorterContainerTooltip).inBMid(4f) - outerPanel!!.addComponent(SorterContainerPanelLocal).inTMid(46f) + outerPanel!!.addComponent(sorterContainerPanelLocal).inTMid(46f) } fun closeSorterPanel() { From 4f703718330a825e006b6721f432aa88b6a8d294 Mon Sep 17 00:00:00 2001 From: S-Numan Date: Mon, 16 Feb 2026 17:01:21 -0800 Subject: [PATCH 13/17] Improved color and sorting --- src/org/magiclib/bounty/intel/BountyInfo.kt | 9 +++------ .../magiclib/bounty/intel/MagicBountyInfo.kt | 19 +++++++++---------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/org/magiclib/bounty/intel/BountyInfo.kt b/src/org/magiclib/bounty/intel/BountyInfo.kt index 5ac44c48..72e02cbe 100644 --- a/src/org/magiclib/bounty/intel/BountyInfo.kt +++ b/src/org/magiclib/bounty/intel/BountyInfo.kt @@ -11,6 +11,7 @@ import org.magiclib.bounty.ActiveBounty import org.magiclib.bounty.ui.lists.sorted.Sortable import org.magiclib.bounty.ui.lists.sorted.SortableParam import org.magiclib.util.MagicTxt +import java.awt.Color interface BountyInfo : Sortable { fun getBountyId(): String @@ -21,12 +22,8 @@ interface BountyInfo : Sortable { fun getLocationIfBountyIsActive(): LocationAPI? fun getPlayerKnownDistanceIfBountyIsActive(): Float? - fun getSortIndex(): Int = 1 - fun getSortIndexOffset(): Int - fun setSortIndexOffset(value: Int) - - fun getNonEnemyToBottom(): Boolean - fun setNonEnemyToBottom(value: Boolean) + fun getCustomPanelColor(): Color? + fun setCustomPanelColor(value: Color?) fun addNotificationBulletpoints(info: TooltipMakerAPI) { } diff --git a/src/org/magiclib/bounty/intel/MagicBountyInfo.kt b/src/org/magiclib/bounty/intel/MagicBountyInfo.kt index c332ff07..0213db58 100644 --- a/src/org/magiclib/bounty/intel/MagicBountyInfo.kt +++ b/src/org/magiclib/bounty/intel/MagicBountyInfo.kt @@ -34,10 +34,10 @@ open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpe var holdingPanel: CustomPanelAPI? = null var panelThatCanBeRemoved: CustomPanelAPI? = null - private var nonEnemyToBottom: Boolean = false - override fun getNonEnemyToBottom(): Boolean = nonEnemyToBottom - override fun setNonEnemyToBottom(value: Boolean) { - nonEnemyToBottom = value + var customColor: Color? = Color(255, 255, 255, 0) + override fun getCustomPanelColor(): Color? = customColor + override fun setCustomPanelColor(value: Color?) { + customColor = value } override fun getBountyId(): String { @@ -263,12 +263,11 @@ open class MagicBountyInfo(val bountyKey: String, val bountySpec: MagicBountySpe plugin.baseBgColor = Misc.getDarkHighlightColor().setAlpha(45) plugin.hoveredColor = Misc.getDarkHighlightColor().setAlpha(75) plugin.selectedColor = Misc.getDarkHighlightColor().setAlpha(125) - } else if (nonEnemyToBottom) { - val colRed = Color(255, 0, 0, 75) - - plugin.baseBgColor = colRed.setAlpha(40) - plugin.hoveredColor = plugin.defaultHoveredColor.interpolateColor(colRed, 0.4f) - plugin.selectedColor = plugin.defaultSelectedColor.interpolateColor(colRed, 0.4f) + } else if (customColor != null) { + val t = customColor!!.alpha / 255f + plugin.baseBgColor = customColor!!.setAlpha(customColor!!.alpha / 2) + plugin.hoveredColor = plugin.defaultHoveredColor.interpolateColor(customColor!!, t) + plugin.selectedColor = plugin.defaultSelectedColor.interpolateColor(customColor!!, t) } else { plugin.baseBgColor = plugin.defaultBgColor plugin.hoveredColor = plugin.defaultHoveredColor From 55194ea518d7f8c7a7f8d8813a18feb17b6093cd Mon Sep 17 00:00:00 2001 From: S-Numan Date: Mon, 16 Feb 2026 17:01:40 -0800 Subject: [PATCH 14/17] Improved color and sorting* --- src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt | 5 +++-- src/org/magiclib/bounty/ui/lists/sorted/ListSort.kt | 4 ++++ .../magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt index 39332142..e793cf41 100644 --- a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt +++ b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt @@ -12,6 +12,7 @@ import org.magiclib.bounty.ui.lists.sorted.ListSorter import org.magiclib.bounty.ui.lists.sorted.Sortable import org.magiclib.internalextensions.addTooltip import org.magiclib.kotlin.getMarketsInLocation +import java.awt.Color class TogglePrimarySorter : ListSorter { @@ -164,7 +165,7 @@ class TogglePrimarySorter : ListSorter { sorted.reverse() } - sorted.forEach { it.setNonEnemyToBottom(false) } + sorted.forEach { it.setCustomPanelColor(null) } if (nonEnemyToBottom) { val sector = Global.getSector() val playerFaction = sector.playerFaction @@ -190,7 +191,7 @@ class TogglePrimarySorter : ListSorter { sorted.clear() sorted.addAll(keep) sorted.addAll(moveToBottom) - moveToBottom.forEach { it.setNonEnemyToBottom(true) } + moveToBottom.forEach { it.setCustomPanelColor(Color(255, 0, 0, 102)) } } // Assign sortIndexOffset diff --git a/src/org/magiclib/bounty/ui/lists/sorted/ListSort.kt b/src/org/magiclib/bounty/ui/lists/sorted/ListSort.kt index 500b69da..87d2abf6 100644 --- a/src/org/magiclib/bounty/ui/lists/sorted/ListSort.kt +++ b/src/org/magiclib/bounty/ui/lists/sorted/ListSort.kt @@ -18,4 +18,8 @@ abstract class SortableParam(val item: T) { interface Sortable { fun getSorterData(): List> + + fun getSortIndex(): Int = 1 + fun getSortIndexOffset(): Int + fun setSortIndexOffset(value: Int) } \ No newline at end of file diff --git a/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt b/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt index 48ce6d41..c0ec56d5 100644 --- a/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt +++ b/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt @@ -58,6 +58,7 @@ abstract class SortedListPanelPlugin>(parentPanel: CustomPanelAP var lastItem: UIPanelAPI? = null validMembers + .sortedBy { it.getSortIndex() } .map { it to createPanelForItem(tooltip, it) } .filter { (_, rowPlugin) -> rowPlugin != null } .forEach { (item, rowPlugin) -> From c584f174c74bb4f7b054802d5b8d0a50123938fb Mon Sep 17 00:00:00 2001 From: S-Numan Date: Mon, 16 Feb 2026 18:32:23 -0800 Subject: [PATCH 15/17] Fix sorting --- src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt | 2 +- .../magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt b/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt index 34716120..09434cff 100644 --- a/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt +++ b/src/org/magiclib/bounty/intel/BountyListPanelPlugin.kt @@ -55,7 +55,7 @@ class BountyListPanelPlugin(parentPanel: CustomPanelAPI) : SortedListPanelPlugin } override fun layoutPanels(members: List): CustomPanelAPI { - finalItem = members.lastOrNull() + finalItem = members.maxByOrNull { it.getSortIndex() } val outerPanelLocal = super.layoutPanels(members) diff --git a/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt b/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt index c0ec56d5..113d0b98 100644 --- a/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt +++ b/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt @@ -27,7 +27,8 @@ abstract class SortedListPanelPlugin>(parentPanel: CustomPanelAP sortersForItems.forEach { it.loadFromPersistentData(members) } var validMembers = members.filter { shouldMakePanelForItem(it) } lastMembers = validMembers - validMembers = sortMembers(validMembers) + //validMembers = sortMembers(validMembers) + validMembers = validMembers.sortedBy { it.getSortIndex() } val outerTooltipLocal = outerPanelLocal.createUIElement(panelWidth, panelHeight, false) outerTooltip = outerTooltipLocal @@ -58,7 +59,6 @@ abstract class SortedListPanelPlugin>(parentPanel: CustomPanelAP var lastItem: UIPanelAPI? = null validMembers - .sortedBy { it.getSortIndex() } .map { it to createPanelForItem(tooltip, it) } .filter { (_, rowPlugin) -> rowPlugin != null } .forEach { (item, rowPlugin) -> From 022629766f7d8d8f6d2ae9c2aa2cbf4216a01aff Mon Sep 17 00:00:00 2001 From: S-Numan Date: Mon, 16 Feb 2026 18:34:41 -0800 Subject: [PATCH 16/17] Externalize strings --- data/strings/strings.json | 13 ++++++++++++- .../intel/sorters/TogglePrimarySorter.kt | 18 +++++++++--------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/data/strings/strings.json b/data/strings/strings.json index 1253c042..fc2c9a0c 100644 --- a/data/strings/strings.json +++ b/data/strings/strings.json @@ -274,6 +274,17 @@ "mb_filters_Location_Distance": "Filter by distance to target", "mb_filters_Location_FuelRange": "Lock distance filter to your fuel range", "mb_filters_Location_SliderTitle": "Distance (LY)", + "mb_sort": "Sort", + "mb_sort_Ascending": "Ascending", + "mb_sort_Descending": "Descending", + "mb_sort_Alphabetical": "Alphabetical", + "mb_sort_Distance": "Distance", + "mb_sort_Credits": "Credits", + "mb_sort_FirstCreated": "Time Posted", + "mb_sort_DropNonHostiles": "Drop non-hostiles in populated areas", + "mb_sort_DropNonHostilesTooltip": "When enabled, non-hostile bounty targets located in systems with a size 4 or larger friendly market will be moved to the bottom of the list and colored red.\n\nE.G: If killing a bounty target would unavoidably trigger a war with a faction.", + + "mb_intelTutorial": "Select a bounty on the left to see more information.\nFilter the list by clicking \"Filters\" at the top of the list.\nIf the job terms are acceptable, click Accept in the bottom-right of the info panel.", # MagicAchievements @@ -331,6 +342,6 @@ "subsystemState_Cooldown": "", "subsystemState_OutOfRange": "OUT OF RANGE", "subsystemState_NoTarget": "NO TARGET", - "subsystemState_FluxCapped": "FLUX TOO HIGH", + "subsystemState_FluxCapped": "FLUX TOO HIGH" } } diff --git a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt index e793cf41..8f636594 100644 --- a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt +++ b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt @@ -12,6 +12,7 @@ import org.magiclib.bounty.ui.lists.sorted.ListSorter import org.magiclib.bounty.ui.lists.sorted.Sortable import org.magiclib.internalextensions.addTooltip import org.magiclib.kotlin.getMarketsInLocation +import org.magiclib.util.MagicTxt import java.awt.Color class TogglePrimarySorter : ListSorter { @@ -53,8 +54,8 @@ class TogglePrimarySorter : ListSorter { val orderTogglesData = listOf( - "Ascending" to Order.ASCENDING, - "Descending" to Order.DESCENDING + MagicTxt.getString("mb_sort_Ascending") to Order.ASCENDING, + MagicTxt.getString("mb_sort_Descending") to Order.DESCENDING ) var currentOrderSelected: ButtonAPI? = null @@ -82,10 +83,10 @@ class TogglePrimarySorter : ListSorter { toggleGroupTooltip.addSpacer(12f) val togglesData = listOf( - "Alphabetical" to SortingMethod.ALPHABETICAL, - "Distance" to SortingMethod.KNOWNDISTANCE, - "Credits" to SortingMethod.CREDITS, - "Time Posted" to SortingMethod.FIRSTCREATED, + MagicTxt.getString("mb_sort_Alphabetical") to SortingMethod.ALPHABETICAL, + MagicTxt.getString("mb_sort_Distance") to SortingMethod.KNOWNDISTANCE, + MagicTxt.getString("mb_sort_Credits") to SortingMethod.CREDITS, + MagicTxt.getString("mb_sort_FirstCreated") to SortingMethod.FIRSTCREATED, ) var currentSelected: ButtonAPI? = null @@ -110,10 +111,9 @@ class TogglePrimarySorter : ListSorter { toggleGroupTooltip.addSpacer(12f) - val nonEnemyToBottomButton = toggleGroupTooltip.addCheckbox(20f, 16f, "Drop non-hostiles in populated areas", null, ButtonAPI.UICheckboxSize.SMALL, 4f) + val nonEnemyToBottomButton = toggleGroupTooltip.addCheckbox(20f, 16f, MagicTxt.getString("mb_sort_DropNonHostiles"), null, ButtonAPI.UICheckboxSize.SMALL, 4f) toggleGroupTooltip.addTooltip(nonEnemyToBottomButton, TooltipMakerAPI.TooltipLocation.BELOW, 600f) { - it.addPara("When enabled, non-hostile bounty targets located in systems with a size 4 or larger friendly market will be moved to the bottom of the list and colored red.", 0f) - it.addPara("E.G: If killing a bounty target would unavoidably trigger a war with a faction.", 8f) + it.addPara(MagicTxt.getString("mb_sort_DropNonHostilesTooltip"), 0f) } nonEnemyToBottomButton.isChecked = nonEnemyToBottom sorterPlugin.addCheckbox(nonEnemyToBottomButton) { checked -> From 46e5c324f5cfabfbaca8e47a4f4eea7148ab0370 Mon Sep 17 00:00:00 2001 From: S-Numan Date: Mon, 16 Feb 2026 19:24:02 -0800 Subject: [PATCH 17/17] positionary --- .../magiclib/bounty/intel/sorters/TogglePrimarySorter.kt | 8 +++----- .../bounty/ui/lists/sorted/SortedListPanelPlugin.kt | 3 ++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt index 8f636594..5f6c9cf3 100644 --- a/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt +++ b/src/org/magiclib/bounty/intel/sorters/TogglePrimarySorter.kt @@ -47,10 +47,10 @@ class TogglePrimarySorter : ListSorter { lastItems: List> ): CustomPanelAPI { val sorterPlugin = InteractiveUIPanelPlugin() - val sorterPanel = Global.getSettings().createCustom(width, 64f, sorterPlugin) + val sorterPanel = Global.getSettings().createCustom(width, tooltip.heightSoFar, sorterPlugin) //checkbox tooltip - val toggleGroupTooltip = sorterPanel.createUIElement(width, 64f, false) + val toggleGroupTooltip = sorterPanel.createUIElement(width, sorterPanel.position.height, false) val orderTogglesData = listOf( @@ -109,9 +109,7 @@ class TogglePrimarySorter : ListSorter { } - toggleGroupTooltip.addSpacer(12f) - - val nonEnemyToBottomButton = toggleGroupTooltip.addCheckbox(20f, 16f, MagicTxt.getString("mb_sort_DropNonHostiles"), null, ButtonAPI.UICheckboxSize.SMALL, 4f) + val nonEnemyToBottomButton = toggleGroupTooltip.addCheckbox(20f, 16f, MagicTxt.getString("mb_sort_DropNonHostiles"), null, ButtonAPI.UICheckboxSize.SMALL, toggleGroupTooltip.heightSoFar - toggleGroupTooltip.position.height - 16f - 4f) toggleGroupTooltip.addTooltip(nonEnemyToBottomButton, TooltipMakerAPI.TooltipLocation.BELOW, 600f) { it.addPara(MagicTxt.getString("mb_sort_DropNonHostilesTooltip"), 0f) } diff --git a/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt b/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt index 113d0b98..36c4dd2d 100644 --- a/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt +++ b/src/org/magiclib/bounty/ui/lists/sorted/SortedListPanelPlugin.kt @@ -86,6 +86,8 @@ abstract class SortedListPanelPlugin>(parentPanel: CustomPanelAP sorterContainerPanel = sorterContainerPanelLocal val sorterContainerTooltip = sorterContainerPanelLocal.createUIElement(panelWidth, panelHeight * 0.33f, true) + sorterContainerTooltip.addSpacer(panelHeight * 0.33f) // sorterContainerTooltip's height is always forced to 0f for some reason which makes all contents invisible. Calling this function allows the contents to be seen and keeps track of height. + var lastItem: UIComponentAPI? = null sortersForItems.forEach { @@ -98,7 +100,6 @@ abstract class SortedListPanelPlugin>(parentPanel: CustomPanelAP lastItem = sorterPanel } - sorterContainerTooltip.addSpacer(1f) // For some reason the tooltip contents fail to show without this sorterContainerPanelLocal.addUIElement(sorterContainerTooltip).inBMid(4f) outerPanel!!.addComponent(sorterContainerPanelLocal).inTMid(46f)