Skip to content

Commit

Permalink
Merge pull request #3772 from NickAragua/manual_force_commander_assig…
Browse files Browse the repository at this point in the history
…nment

fix #3781
fix #3540
  • Loading branch information
NickAragua authored Feb 13, 2024
2 parents c00cbba + 3997226 commit 105e37f
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 52 deletions.
11 changes: 11 additions & 0 deletions MekHQ/src/mekhq/campaign/Campaign.java
Original file line number Diff line number Diff line change
Expand Up @@ -3573,6 +3573,11 @@ public void removePerson(final @Nullable Person person, final boolean log) {
return;
}

Force force = getForceFor(person);
if (force != null) {
force.updateCommander(this);
}

person.getGenealogy().clearGenealogyLinks();

final Unit unit = person.getUnit();
Expand Down Expand Up @@ -4804,6 +4809,12 @@ public void personUpdated(Person p) {
if (null != u) {
u.resetPilotAndEntity();
}

Force force = getForceFor(p);
if (force != null) {
force.updateCommander(this);
}

MekHQ.triggerEvent(new PersonChangedEvent(p));
}

Expand Down
92 changes: 68 additions & 24 deletions MekHQ/src/mekhq/campaign/force/Force.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public class Force {
private Vector<Force> subForces;
private Vector<UUID> units;
private int scenarioId;
private UUID forceCommanderID;

protected UUID techId;

Expand Down Expand Up @@ -310,6 +311,8 @@ public void addUnit(Campaign campaign, UUID uid, boolean useTransfers, Force old
}
}
}

updateCommander(campaign);
}

/**
Expand Down Expand Up @@ -338,32 +341,11 @@ public void removeUnit(Campaign campaign, UUID id, boolean log) {
}
}
}

updateCommander(campaign);
}
}

public boolean removeUnitFromAllForces(UUID id) {
int idx = 0;
boolean found = false;
for (UUID uid : getUnits()) {
if (uid.equals(id)) {
found = true;
break;
}
idx++;
}
if (found) {
units.remove(idx);
} else {
for (Force sub : getSubForces()) {
found = sub.removeUnitFromAllForces(id);
if (found) {
break;
}
}
}
return found;
}

public void clearScenarioIds(Campaign c) {
clearScenarioIds(c, true);
}
Expand Down Expand Up @@ -402,7 +384,64 @@ public int getId() {
public void setId(int i) {
this.id = i;
}


public UUID getForceCommanderID() {
return forceCommanderID;
}

public void setForceCommanderID(UUID commanderID) {
forceCommanderID = commanderID;
}

public List<UUID> getEligibleCommanders(Campaign c) {
List<UUID> people = new ArrayList<>();
Person highestRankPerson = c.getPerson(getForceCommanderID());

// safety check: if the person is no longer assigned to a unit or the force,
// then they're not really the highest ranked person in the force.
if ((highestRankPerson != null) &&
((highestRankPerson.getUnit() == null) ||
(!getUnits().contains(highestRankPerson.getUnit().getId())))) {
highestRankPerson = null;
}

for (UUID uid : getUnits()) {
Unit u = c.getUnit(uid);
if (null != u) {
Person p = u.getCommander();
if (null != p) {
// if we found someone with a higher rank, clear everything out and start again with the new highest rank person
if (p.outRanks(highestRankPerson)) {
people.clear();
people.add(p.getId());
highestRankPerson = p;
// if we are looking at someone with a lower rank, ignore them and move on
} else if ((highestRankPerson != null) && highestRankPerson.outRanks(p)) {
continue;
// someone with an equivalent rank can be commander
} else {
people.add(p.getId());
}
}
}
}

return people;
}

/**
* Automatically update the force's commander
*/
public void updateCommander(Campaign c) {
List<UUID> eligibleCommanders = getEligibleCommanders(c);

// logic: if we found someone eligible who is a higher rank, the first one of those becomes the new commander
// otherwise, the existing commander remains the commander
if (!eligibleCommanders.contains(getForceCommanderID()) && (eligibleCommanders.size() > 0)) {
forceCommanderID = eligibleCommanders.get(0);
}
}

public void removeSubForce(int id) {
int idx = 0;
boolean found = false;
Expand Down Expand Up @@ -470,6 +509,7 @@ public void writeToXML(PrintWriter pw1, int indent) {
MHQXMLUtility.writeSimpleXMLTag(pw1, indent, "combatForce", combatForce);
MHQXMLUtility.writeSimpleXMLTag(pw1, indent, "scenarioId", scenarioId);
MHQXMLUtility.writeSimpleXMLTag(pw1, indent, "techId", techId);
MHQXMLUtility.writeSimpleXMLTag(pw1, indent, "forceCommanderID", forceCommanderID);
if (!units.isEmpty()) {
MHQXMLUtility.writeSimpleXMLOpenTag(pw1, indent++, "units");
for (UUID uid : units) {
Expand Down Expand Up @@ -528,6 +568,8 @@ public void writeToXML(PrintWriter pw1, int indent) {
retVal.scenarioId = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("techId")) {
retVal.techId = UUID.fromString(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("forceCommanderID")) {
retVal.forceCommanderID = UUID.fromString(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("units")) {
processUnitNodes(retVal, wn2, version);
} else if (wn2.getNodeName().equalsIgnoreCase("subforces")) {
Expand Down Expand Up @@ -563,6 +605,8 @@ public void writeToXML(PrintWriter pw1, int indent) {
} else if (version.isLowerThan("0.49.7")) {
retVal.setForceIcon(ForceIconMigrator.migrateForceIcon0496To0497(retVal.getForceIcon()));
}

retVal.updateCommander(c);

return retVal;
}
Expand Down
18 changes: 1 addition & 17 deletions MekHQ/src/mekhq/campaign/force/Lance.java
Original file line number Diff line number Diff line change
Expand Up @@ -250,24 +250,8 @@ size > getStdLanceSize(c.getFaction()) + 2) {
}

/* Code to find unit commander from ForceViewPanel */

public static UUID findCommander(int forceId, Campaign c) {
ArrayList<Person> people = new ArrayList<>();
for (UUID uid : c.getForce(forceId).getAllUnits(false)) {
Unit u = c.getUnit(uid);
if (null != u) {
Person p = u.getCommander();
if (null != p) {
people.add(p);
}
}
}
// sort person vector by rank
people.sort((p1, p2) -> ((Comparable<Integer>) p2.getRankNumeric()).compareTo(p1.getRankNumeric()));
if (!people.isEmpty()) {
return people.get(0).getId();
}
return null;
return c.getForce(forceId).getForceCommanderID();
}

public static LocalDate getBattleDate(LocalDate today) {
Expand Down
2 changes: 2 additions & 0 deletions MekHQ/src/mekhq/gui/TOETab.java
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,13 @@ public void scenarioResolved(ScenarioResolvedEvent ev) {
@Subscribe
public void personChanged(PersonChangedEvent ev) {
orgTree.repaint();
orgRefreshScheduler.schedule();
}

@Subscribe
public void personRemoved(PersonRemovedEvent ev) {
orgTree.repaint();
orgRefreshScheduler.schedule();
}

@Subscribe
Expand Down
26 changes: 26 additions & 0 deletions MekHQ/src/mekhq/gui/adapter/TOEMouseAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ public static void connect(CampaignGUI gui, JTree tree) {

private static final String COMMAND_ADD_LANCE_TECH = "ADD_LANCE_TECH|FORCE|";
private static final String COMMAND_REMOVE_LANCE_TECH = "REMOVE_LANCE_TECH|FORCE|";

// Commander-Related
private static final String SET_LANCE_COMMANDER = "SET_LANCE_COMMANDER";
private static final String COMMAND_SET_LANCE_COMMANDER = "SET_LANCE_COMMANDER|FORCE|";

// Icons and Descriptions
private static final String CHANGE_CAMO = "CHANGE_CAMO";
Expand Down Expand Up @@ -268,6 +272,11 @@ public void actionPerformed(ActionEvent action) {

MekHQ.triggerEvent(new OrganizationChangedEvent(singleForce));
}
} else if (command.contains(TOEMouseAdapter.SET_LANCE_COMMANDER)) {
if (null != singleForce) {
singleForce.setForceCommanderID(UUID.fromString(target));
gui.getTOETab().refreshForceView();
}
} else if (command.contains(TOEMouseAdapter.ASSIGN_TO_SHIP)) {
Unit ship = gui.getCampaign().getUnit(UUID.fromString(target));
if ((!units.isEmpty()) && (ship != null)) {
Expand Down Expand Up @@ -899,6 +908,23 @@ protected Optional<JPopupMenu> createPopupMenu() {
}
JMenuHelpers.addMenuIfNonEmpty(menu, unsorted);
JMenuHelpers.addMenuIfNonEmpty(popup, menu);

// still in the multiple selection block
List<UUID> eligibleCommanders = force.getEligibleCommanders(gui.getCampaign());
if (!eligibleCommanders.isEmpty()) {
menuItem = new JScrollableMenu("setCommanderMenu", "Set Commander");

for (UUID personID : eligibleCommanders) {
Person person = gui.getCampaign().getPerson(personID);

JMenuItem commanderOption = new JMenuItem(person.getFullTitle() + " (" + person.getRoleDesc() + ")");
commanderOption.setActionCommand(COMMAND_SET_LANCE_COMMANDER + personID + "|" + forceIds);
commanderOption.addActionListener(this);
menuItem.add(commanderOption);
}

popup.add(menuItem);
}
}

menu = new JMenu("Force Icon");
Expand Down
15 changes: 4 additions & 11 deletions MekHQ/src/mekhq/gui/view/ForceViewPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,13 @@ private void fillStats() {
String lanceTech = "";
String assigned = "";
String type = null;
ArrayList<Person> people = new ArrayList<>();

Person commanderPerson = campaign.getPerson(force.getForceCommanderID());
commander = commanderPerson != null ? commanderPerson.getFullTitle() : "";

for (UUID uid : force.getAllUnits(false)) {
Unit u = campaign.getUnit(uid);
if (null != u) {
Person p = u.getCommander();
bv += u.getEntity().calculateBattleValue(true, !u.hasPilot());
cost = cost.plus(u.getEntity().getCost(true));
ton += u.getEntity().getWeight();
Expand All @@ -181,18 +183,9 @@ private void fillStats() {
} else if (!utype.equals(type)) {
type = resourceMap.getString("mixed");
}
if (null != p) {
people.add(p);
}
}
}

// sort person vector by rank
people.sort((p1, p2) -> ((Comparable<Integer>) p2.getRankNumeric()).compareTo(p1.getRankNumeric()));
if (!people.isEmpty()) {
commander = people.get(0).getFullTitle();
}

if (force.getTechID() != null) {
final Person person = campaign.getPerson(force.getTechID());
if (person != null) {
Expand Down

0 comments on commit 105e37f

Please sign in to comment.