Skip to content

Commit

Permalink
Merge pull request #5253 from Scoppio/fix-activate-large-vessel
Browse files Browse the repository at this point in the history
allows to select a previous engineer or new crew member to activate large vessels
  • Loading branch information
HammerGS authored Nov 29, 2024
2 parents 0f0c41b + e9da4f6 commit af1d231
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 19 deletions.
16 changes: 13 additions & 3 deletions MekHQ/src/mekhq/campaign/Campaign.java
Original file line number Diff line number Diff line change
Expand Up @@ -2451,19 +2451,29 @@ public List<Person> getTechs(final boolean noZeroMinute) {
return getTechs(noZeroMinute, false);
}

public List<Person> getTechsExpanded() {
return getTechsExpanded(false, false, true);
}

public List<Person> getTechs(final boolean noZeroMinute, final boolean eliteFirst) {
return getTechsExpanded(noZeroMinute, eliteFirst, false);
}

/**
* Returns a list of active technicians.
*
* @param noZeroMinute If TRUE, then techs with no time remaining will be
* excluded from the list.
* @param eliteFirst If TRUE and sorted also TRUE, then return the list sorted
* from best to worst
* @param expanded If TRUE, then include techs with expanded roles (e.g. Tech/Vessel skill)
* @return The list of active {@link Person}s who qualify as technicians
* ({@link Person#isTech()}).
* ({@link Person#isTech()}), or who qualify as expanded technicians ({@link Person#isTechExpanded()}).
*/
public List<Person> getTechs(final boolean noZeroMinute, final boolean eliteFirst) {
public List<Person> getTechsExpanded(final boolean noZeroMinute, final boolean eliteFirst, final boolean expanded) {
final List<Person> techs = getActivePersonnel().stream()
.filter(person -> person.isTech() && (!noZeroMinute || (person.getMinutesLeft() > 0)))
.filter(person -> (expanded ? person.isTechExpanded() : person.isTech())
&& (!noZeroMinute || (person.getMinutesLeft() > 0)))
.collect(Collectors.toList());

// also need to loop through and collect engineers on self-crewed vessels
Expand Down
44 changes: 36 additions & 8 deletions MekHQ/src/mekhq/campaign/personnel/Person.java
Original file line number Diff line number Diff line change
Expand Up @@ -3753,8 +3753,13 @@ public boolean canGun(final Entity entity) {
}

public boolean canTech(final Entity entity) {
if (entity == null) {
return false;
}
if ((entity instanceof Mek) || (entity instanceof ProtoMek)) {
return hasSkill(SkillType.S_TECH_MEK);
} else if (entity instanceof Dropship || entity instanceof Jumpship) {
return hasSkill(SkillType.S_TECH_VESSEL);
} else if (entity instanceof Aero) {
return hasSkill(SkillType.S_TECH_AERO);
} else if (entity instanceof BattleArmor) {
Expand Down Expand Up @@ -3845,24 +3850,34 @@ public int getMinutesLeft() {
public void setMinutesLeft(final int minutesLeft) {
this.minutesLeft = minutesLeft;
if (engineer && (getUnit() != null)) {
// set minutes for all crewmembers
for (Person p : getUnit().getActiveCrew()) {
p.setMinutesLeft(minutesLeft);
}
// set minutes for all crew members, except the engineer to not cause infinite recursion.
getUnit().getActiveCrew()
.stream()
.filter(this::isNotSelf)
.forEach(p -> p.setMinutesLeft(minutesLeft));
}
}

/**
* Checks if the other person is not the same person as this person, easy right?
* @param p Person to check against
* @return true if the person is not the same person as this person
*/
private boolean isNotSelf(Person p) {
return !this.equals(p);
}

public int getOvertimeLeft() {
return overtimeLeft;
}

public void setOvertimeLeft(final int overtimeLeft) {
this.overtimeLeft = overtimeLeft;
if (engineer && (getUnit() != null)) {
// set minutes for all crewmembers
for (Person p : getUnit().getActiveCrew()) {
p.setMinutesLeft(overtimeLeft);
}
getUnit().getActiveCrew()
.stream()
.filter(this::isNotSelf)
.forEach(p -> p.setOvertimeLeft(overtimeLeft));
}
}

Expand Down Expand Up @@ -3901,6 +3916,19 @@ public boolean isTech() {
return isTechMek() || isTechAero() || isTechMechanic() || isTechBA();
}

/**
* Checks if the person is a tech, includes mektek, mechanic, aerotek, BAtek and the non-cannon "large vessel tek"
* @return true if the person is a tech
*/
public boolean isTechExpanded() {
return isTechMek() || isTechAero() || isTechMechanic() || isTechBA() || isTechLargeVessel();
}

public boolean isTechLargeVessel() {
boolean hasSkill = hasSkill(SkillType.S_TECH_VESSEL);
return hasSkill && (getPrimaryRole().isVesselCrew() || getSecondaryRole().isVesselCrew());
}

public boolean isTechMek() {
boolean hasSkill = hasSkill(SkillType.S_TECH_MEK);
return hasSkill && (getPrimaryRole().isMekTech() || getSecondaryRole().isMekTech());
Expand Down
16 changes: 12 additions & 4 deletions MekHQ/src/mekhq/campaign/unit/MothballInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
* This class is used to store information about a particular unit that is
* lost when a unit is mothballed, so that it may be restored to as close to
* its prior state as possible when the unit is reactivated.
*
*
* @author NickAragua
*/
public class MothballInfo {
Expand All @@ -61,9 +61,17 @@ private MothballInfo() {
vesselCrew = new ArrayList<>();
}

/**
* Who was the original tech of this vessel?
* @return The original tech
*/
public Person getTech() {
return tech;
}

/**
* Creates a set of mothball info for a given unit
*
*
* @param unit The unit to work with
*/
public MothballInfo(Unit unit) {
Expand All @@ -78,7 +86,7 @@ public MothballInfo(Unit unit) {

/**
* Restore a unit's pilot, assigned tech and force, to the best of our ability
*
*
* @param unit The unit to restore
* @param campaign The campaign in which this is happening
*/
Expand Down Expand Up @@ -158,7 +166,7 @@ public void writeToXML(final PrintWriter pw, int indent) {

/**
* Deserializer method implemented in standard MekHQ pattern.
*
*
* @return Instance of MothballInfo
*/
public static MothballInfo generateInstanceFromXML(Node wn, Version version) {
Expand Down
42 changes: 41 additions & 1 deletion MekHQ/src/mekhq/campaign/unit/Unit.java
Original file line number Diff line number Diff line change
Expand Up @@ -4821,6 +4821,29 @@ public void startMothballing(@Nullable Person mothballTech, boolean isGM) {
}
}

/**
* Returns the engineer responsible for the mothballing or activation of this unit.
* @return Person the previous engineer that worked on this vessel, or an empty object.
*/
public Optional<Person> engineerResponsible() {
// if it is NOT self crewed or it is NOT mothballed, just get the tech
if (!isMothballed() || !isSelfCrewed()) {
return Optional.ofNullable(getTech());
} else {
// if it is self crewed AND is mothballed and has a mothball info, get the tech
if (isSelfCrewed() && isMothballed() && (this.mothballInfo != null)) {
var previousTech = this.mothballInfo.getTech();
var previousTechExists = previousTech != null;
var previousTechIsActive = previousTechExists && previousTech.getStatus().isActive();
if (previousTechIsActive) {
return Optional.of(previousTech);
}
}
}

return Optional.empty();
}

/**
* Completes the mothballing of a unit.
*/
Expand Down Expand Up @@ -4858,8 +4881,25 @@ public void startActivating(@Nullable Person activationTech, boolean isGM) {
// set this person as tech
if (!isSelfCrewed() && (tech != null) && !tech.equals(activationTech)) {
remove(tech, true);
tech = activationTech;
} else if (!isSelfCrewed() && (null == tech)) {
tech = activationTech;
}

if (isSelfCrewed() && !isConventionalInfantry()) {
if (engineerResponsible().isPresent() && engineerResponsible().get().getStatus().isActive()) {
var assignedEngineer = engineerResponsible().get();
addVesselCrew(assignedEngineer);
} else if (activationTech != null && activationTech.isTechLargeVessel()) {
addVesselCrew(activationTech);
} else {
// In this case there is nothing to be done, we cant activate this unit.
return;
}
resetEngineer();
} else {
tech = activationTech;
}
tech = activationTech;

if (!isGM) {
setMothballTime(getMothballOrActivationTime());
Expand Down
2 changes: 1 addition & 1 deletion MekHQ/src/mekhq/gui/CampaignGUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -1734,7 +1734,7 @@ public void refitUnit(Refit r, boolean selectModelName) {
public @Nullable UUID selectTech(Unit u, String desc, boolean ignoreMaintenance) {
String name;
Map<String, Person> techHash = new LinkedHashMap<>();
for (Person tech : getCampaign().getTechs()) {
for (Person tech : getCampaign().getTechsExpanded()) {
if (!tech.isMothballing() && tech.canTech(u.getEntity())) {
int time = tech.getMinutesLeft();
if (!ignoreMaintenance) {
Expand Down
8 changes: 6 additions & 2 deletions MekHQ/src/mekhq/gui/adapter/UnitTableMouseAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ public void actionPerformed(ActionEvent action) {
String quality = (String) JOptionPane.showInputDialog(gui.getFrame(), "Choose the new quality level",
"Set Quality", JOptionPane.PLAIN_MESSAGE, null, possibilities,
PartQuality.QUALITY_D.toName(reverse));

PartQuality q = PartQuality.fromName(quality, reverse);
for (Unit unit : units) {
if (null != unit) {
Expand Down Expand Up @@ -526,7 +526,7 @@ public void actionPerformed(ActionEvent action) {

private @Nullable Person pickTechForMothballOrActivation(Unit unit, String description) {
Person tech = null;
if (!unit.isSelfCrewed()) {
if (!unit.isSelfCrewed() || isSelfCrewedButHasNoTech(unit)) {
UUID id = gui.selectTech(unit, description, true);
if (null != id) {
tech = gui.getCampaign().getPerson(id);
Expand All @@ -544,6 +544,10 @@ public void actionPerformed(ActionEvent action) {
return tech;
}

private boolean isSelfCrewedButHasNoTech(Unit unit) {
return unit.isSelfCrewed() && unit.engineerResponsible().isEmpty();
}

@Override
protected Optional<JPopupMenu> createPopupMenu() {
if (unitTable.getSelectedRowCount() == 0) {
Expand Down
1 change: 1 addition & 0 deletions MekHQ/unittests/mekhq/campaign/CampaignTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ void testGetTechs() {
when(testCampaign.getTechs()).thenCallRealMethod();
when(testCampaign.getTechs(anyBoolean())).thenCallRealMethod();
when(testCampaign.getTechs(anyBoolean(), anyBoolean())).thenCallRealMethod();
when(testCampaign.getTechsExpanded(anyBoolean(), anyBoolean(), anyBoolean())).thenCallRealMethod();

// Test just getting the list of active techs.
List<Person> expected = new ArrayList<>(3);
Expand Down

0 comments on commit af1d231

Please sign in to comment.