From 1a312f4e822034d188916cbe8ece4672a76c5f6d Mon Sep 17 00:00:00 2001 From: T9knauf Date: Sun, 10 May 2026 18:45:48 -0400 Subject: [PATCH] Add Sentinel group leader map tracking --- .../com/deeme/modules/SentinelModule.java | 129 +++++++++++++----- .../deeme/types/config/SentinelConfig.java | 5 +- .../com/deeme/lang/strings_en.properties | 2 + .../com/deeme/lang/strings_tr.properties | 2 + 4 files changed, 104 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/deeme/modules/SentinelModule.java b/src/main/java/com/deeme/modules/SentinelModule.java index 3d5e86c6..d6fea7f6 100644 --- a/src/main/java/com/deeme/modules/SentinelModule.java +++ b/src/main/java/com/deeme/modules/SentinelModule.java @@ -23,6 +23,7 @@ import eu.darkbot.api.game.entities.Player; import eu.darkbot.api.game.entities.Portal; import eu.darkbot.api.game.entities.Ship; +import eu.darkbot.api.game.group.GroupMember; import eu.darkbot.api.game.items.SelectableItem.Formation; import eu.darkbot.api.game.items.SelectableItem.Special; import eu.darkbot.api.game.other.GameMap; @@ -104,13 +105,15 @@ public class SentinelModule implements Module, Configurable, Ins private JLabel label = new JLabel("Sentinel Module
" + "It's important that the main ship is in a group
" + "Following priority: Master ID > Tag > Group Leader
" + - "If a \"Sentinel Tag\" is not defined, it will follow the group leader "); + "If a \"Sentinel Tag\" is not defined, it will follow the group leader
" + + "Enable map-only mode to travel to the group leader map without following coordinates "); private enum State { INIT("Init"), WAIT("Waiting for group invitation"), WAIT_GROUP_LOADING("Waiting while loading the group"), TRAVELLING_TO_MASTER("Travelling to the master's map"), + TRACKING_LEADER_MAP("Tracking group leader map"), FOLLOWING_MASTER("Following the master"), HELPING_MASTER("Helping the master"), TRAVELING_TO_WORKING_MAP("Travelling to the working map to wait"); @@ -222,9 +225,13 @@ public JComponent instructionsComponent() { public void onTickModule() { pet.setEnabled(true); if ((sConfig.ignoreSecurity || safety.tick()) && (!sConfig.collectorActive || collectorModule.canRefresh())) { + updateGroupLeaderId(); if (hasSentinel()) { updateLastMap(); - if (isAttacking()) { + if (isGroupLeaderMapOnlyActive()) { + currentStatus = State.TRACKING_LEADER_MAP; + trackLeaderMapOnly(); + } else if (isAttacking()) { currentStatus = State.HELPING_MASTER; attackLogic(); } else if (sentinel.isValid()) { @@ -330,6 +337,13 @@ private boolean followByPortals() { return false; } + private void trackLeaderMapOnly() { + setMode(configRoam.getValue()); + if (sConfig.collectorActive) { + collectorModule.onTickModule(); + } + } + private void moveToMaster() { if (sentinel != null) { if (sConfig.goToMasterDestination) { @@ -502,38 +516,87 @@ private boolean isTaggedSentinel(Player ship) { } private void goToGroup() { + GroupMember member = getGroupMaster(); + if (member == null || heroapi.getMap() == null) { + return; + } + + if (member.isLeader()) { + groupLeaderID = member.getId(); + } + masterID = member.getId(); + + if (member.getMapId() == heroapi.getMap().getId()) { + lastSentinelLocation = member.getLocation(); + if (isGroupLeaderMapOnlyActive(member)) { + currentStatus = State.TRACKING_LEADER_MAP; + trackLeaderMapOnly(); + } else { + movement.moveTo(member.getLocation()); + currentStatus = State.FOLLOWING_MASTER; + } + } else { + GameMap map = starSystem.findMap(member.getMapId()).orElse(null); + if (map != null) { + this.bot.setModule(api.requireInstance(MapModule.class)) + .setTarget(map); + currentStatus = State.TRAVELLING_TO_MASTER; + } + } + } + + private GroupMember getGroupMaster() { + GroupMember configuredMaster = group.getMembers().stream() + .filter(this::isLivingGroupMember) + .filter(m -> sConfig.MASTER_ID != 0 && m.getId() == sConfig.MASTER_ID) + .findFirst().orElse(null); + if (configuredMaster != null) { + return configuredMaster; + } + + GroupMember taggedMaster = group.getMembers().stream() + .filter(this::isLivingGroupMember) + .filter(m -> sConfig.SENTINEL_TAG != null + && sConfig.SENTINEL_TAG.has(main.config.PLAYER_INFOS.get(m.getId()))) + .findFirst().orElse(null); + if (taggedMaster != null) { + return taggedMaster; + } + + if (!sConfig.followGroupLeader) { + return null; + } + + return group.getMembers().stream() + .filter(this::isLivingGroupMember) + .filter(GroupMember::isLeader) + .findFirst().orElse(null); + } + + private boolean isLivingGroupMember(GroupMember member) { + return member != null && !member.isDead() && member.getId() != heroapi.getId(); + } + + private void updateGroupLeaderId() { + if (!group.hasGroup()) { + return; + } + group.getMembers().stream() - .filter(this::isGroupMemberValid) - .forEach(m -> { - if (m.isLeader()) { - groupLeaderID = m.getId(); - } - masterID = m.getId(); - - if (heroapi.getMap() != null && m.getMapId() == heroapi.getMap().getId()) { - lastSentinelLocation = m.getLocation(); - } - if (m.getMapId() == heroapi.getMap().getId()) { - movement.moveTo(m.getLocation()); - currentStatus = State.FOLLOWING_MASTER; - } else { - GameMap map = starSystem.findMap(m.getMapId()).orElse(null); - if (map != null) { - this.bot.setModule(api.requireInstance(MapModule.class)) - .setTarget(map); - currentStatus = State.TRAVELLING_TO_MASTER; - } - } - }); - } - - private boolean isGroupMemberValid(eu.darkbot.api.game.group.GroupMember m) { - return !m.isDead() && m.getId() != heroapi.getId() - && ((sConfig.MASTER_ID != 0 && m.getId() == sConfig.MASTER_ID) || - (sConfig.SENTINEL_TAG != null - && sConfig.SENTINEL_TAG.has(main.config.PLAYER_INFOS.get(m.getId()))) - || - (sConfig.followGroupLeader && m.isLeader())); + .filter(this::isLivingGroupMember) + .filter(GroupMember::isLeader) + .findFirst() + .ifPresent(member -> groupLeaderID = member.getId()); + } + + private boolean isGroupLeaderMapOnlyActive() { + return sentinel != null && sConfig.groupLeaderMapOnly && sConfig.followGroupLeader + && groupLeaderID != 0 && sentinel.getId() == groupLeaderID; + } + + private boolean isGroupLeaderMapOnlyActive(GroupMember member) { + return member != null && sConfig.groupLeaderMapOnly && sConfig.followGroupLeader + && member.isLeader(); } private void acceptGroupSentinel() { diff --git a/src/main/java/com/deeme/types/config/SentinelConfig.java b/src/main/java/com/deeme/types/config/SentinelConfig.java index 2cbae934..f83ecb5d 100644 --- a/src/main/java/com/deeme/types/config/SentinelConfig.java +++ b/src/main/java/com/deeme/types/config/SentinelConfig.java @@ -25,6 +25,9 @@ public class SentinelConfig { @Option("sentinel.follow_group") public boolean followGroupLeader = true; + @Option("sentinel.group_leader_map_only") + public boolean groupLeaderMapOnly = false; + @Option("sentinel.ignore_safety") public boolean ignoreSecurity = false; @@ -64,4 +67,4 @@ public class SentinelConfig { @Option("humanizer") public Humanizer humanizer = new Humanizer(); -} \ No newline at end of file +} diff --git a/src/main/resources/com/deeme/lang/strings_en.properties b/src/main/resources/com/deeme/lang/strings_en.properties index 74be6541..8ed95e59 100644 --- a/src/main/resources/com/deeme/lang/strings_en.properties +++ b/src/main/resources/com/deeme/lang/strings_en.properties @@ -114,6 +114,8 @@ sentinel.tag=Master Tag sentinel.tag.desc=Medium priority. He'll follow every ship with that tag sentinel.follow_group=Follow group leader sentinel.follow_group.desc=Last priority. Follow the leader of the group +sentinel.group_leader_map_only=Track leader map only +sentinel.group_leader_map_only.desc=Travel to the group leader's map without following the leader's exact position or attacks. sentinel.ignore_safety=Ignore safety sentinel.ignore_safety.desc=Ignore the safety config, when enabled, the ship will follow you to death. sentinel.range_to_leader=Range towards the leader diff --git a/src/main/resources/com/deeme/lang/strings_tr.properties b/src/main/resources/com/deeme/lang/strings_tr.properties index f6d07fda..f9d01202 100644 --- a/src/main/resources/com/deeme/lang/strings_tr.properties +++ b/src/main/resources/com/deeme/lang/strings_tr.properties @@ -114,6 +114,8 @@ sentinel.tag=Master Etiketi sentinel.tag.desc=Orta öncelik. Etiket'e sahip her gemiyi takip eder sentinel.follow_group=Grup liderini takip et sentinel.follow_group.desc=Son öncelik. Grup liderini takip eder +sentinel.group_leader_map_only=Yalnızca lider haritasını takip et +sentinel.group_leader_map_only.desc=Grup liderinin tam konumunu veya saldırılarını takip etmeden liderin haritasına gider. sentinel.ignore_safety=Güvenliği yok say sentinel.ignore_safety.desc=Etkinleştirildiğinde güvenlik yapılandırmasını yok sayar, gemi seni ölümüne takip eder. sentinel.range_to_leader=Lidere olan mesafe