Skip to content

Commit

Permalink
Merge pull request #4139 from IllianiCBT/education_WashoutOptions
Browse files Browse the repository at this point in the history
Added Second Chance Caste to the Education Module for Warrior Caste Washouts
  • Loading branch information
SJuliez authored Jun 8, 2024
2 parents d2c561a + b9c5243 commit c523ce4
Show file tree
Hide file tree
Showing 8 changed files with 251 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,8 @@ lblOtherCasteAccidents.text=Other Caste Training Accidents Die Sides
lblOtherCasteAccidents.toolTip=The number of sides on the die used to determine random weekly (potentially fatal) accidents. A fatal accident occurs on a roll of 1. Setting this to 0 disables random accidents.
chkLiveFireBlooding.text=Live Fire Trial of Position
chkLiveFireBlooding.toolTip=Warrior Caste graduating Trials of Position are conducted under live fire conditions.
lblSecondChanceCaste.text=Second Chance Caste
lblSecondChanceCaste.toolTip=Which sub-caste should Warrior Caste aspirants wash into?
## End Life Paths Tab

## Finances Tab
Expand Down
7 changes: 7 additions & 0 deletions MekHQ/resources/mekhq/resources/Education.properties
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ graduatedWarriorThreeKillsLog.text=three kills
washout.text=has washed out of the %s Caste%s
washoutLabor.text=, and has no further place in Clan society.
graduatedWarrior.text=Warrior
graduatedWarriorMechWarrior.text=Warrior (MechWarrior)
graduatedWarriorProtoMech.text=Warrior (ProtoMech)
graduatedWarriorAerospace.text=Warrior (Aerospace)
graduatedWarriorSpace.text=Warrior (Space)
graduatedWarriorBa.text=Warrior (Battle Armor)
graduatedWarriorInfantry.text=Warrior (Infantry)
graduatedWarriorVehicle.text=Warrior (Vehicle)
graduatedScientist.text=Science
graduatedMerchant.text=Merchant
graduatedTechnician.text=Technician
Expand Down
10 changes: 10 additions & 0 deletions MekHQ/resources/mekhq/resources/Personnel.properties
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,16 @@ TimeInDisplayFormat.MONTHS_YEARS.displayFormat=%d month(s) and %d year(s)
TimeInDisplayFormat.YEARS.text=Year(s)
TimeInDisplayFormat.YEARS.displayFormat=%d year(s)

# SecondChanceCaste Enum
SecondChanceCaste.NONE.text=None
SecondChanceCaste.NONE.toolTipText=Warrior Caste washouts are not given a second chance.
SecondChanceCaste.BA.text=Battle Armor
SecondChanceCaste.BA.toolTipText=Warrior Caste washouts are given a second chance in a Battle Armor Sibko.
SecondChanceCaste.INFANTRY.text=Conventional Infantry
SecondChanceCaste.INFANTRY.toolTipText=Warrior Caste washouts are given a second chance in a Conventional Infantry Sibko.
SecondChanceCaste.VEHICLE.text=Vehicle
SecondChanceCaste.VEHICLE.toolTipText=Warrior Caste washouts are given a second chance in a Vehicle Sibko.



## Marriage
Expand Down
13 changes: 13 additions & 0 deletions MekHQ/src/mekhq/campaign/CampaignOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ public static String getTransitUnitName(final int unit) {
private Integer warriorCasteAccidents;
private Integer otherCasteAccidents;
private boolean liveFireBlooding;
private SecondChanceCaste secondChanceCaste;
private Integer fallbackScientist;
private Integer fallbackMerchant;
private Integer fallbackTechnician;
Expand Down Expand Up @@ -916,6 +917,7 @@ public CampaignOptions() {
setWarriorCasteAccidents(250);
setOtherCasteAccidents(5000);
setLiveFireBlooding(true);
setSecondChanceCaste(SecondChanceCaste.NONE);
setFallbackScientist(6);
setFallbackMerchant(12);
setFallbackTechnician(5);
Expand Down Expand Up @@ -2852,6 +2854,14 @@ public void setLiveFireBlooding(boolean liveFireBlooding) {
this.liveFireBlooding = liveFireBlooding;
}

public SecondChanceCaste getSecondChanceCaste() {
return secondChanceCaste;
}

public void setSecondChanceCaste(final SecondChanceCaste secondChanceCaste) {
this.secondChanceCaste = secondChanceCaste;
}

public Integer getFallbackScientist() {
return fallbackScientist;
}
Expand Down Expand Up @@ -4759,6 +4769,7 @@ public void writeToXml(final PrintWriter pw, int indent) {
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "warriorCasteAccidents", getWarriorCasteAccidents());
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "otherCasteAccidents", getOtherCasteAccidents());
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "liveFireBlooding", isLiveFireBlooding());
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "secondChanceCaste", getSecondChanceCaste().name());
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "fallbackScientist", getFallbackScientist());
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "fallbackMerchant", getFallbackMerchant());
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "fallbackTechnician", getFallbackTechnician());
Expand Down Expand Up @@ -5531,6 +5542,8 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve
retVal.setOtherCasteAccidents(Integer.parseInt(wn2.getTextContent().trim()));
} else if (wn2.getNodeName().equalsIgnoreCase("liveFireBlooding")) {
retVal.setLiveFireBlooding(Boolean.parseBoolean(wn2.getTextContent().trim()));
} else if (wn2.getNodeName().equalsIgnoreCase("secondChanceCaste")) {
retVal.setSecondChanceCaste(SecondChanceCaste.valueOf(wn2.getTextContent().trim()));
} else if (wn2.getNodeName().equalsIgnoreCase("fallbackScientist")) {
retVal.setFallbackScientist(Integer.parseInt(wn2.getTextContent().trim()));
} else if (wn2.getNodeName().equalsIgnoreCase("fallbackMerchant")) {
Expand Down
119 changes: 108 additions & 11 deletions MekHQ/src/mekhq/campaign/personnel/education/EducationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ private static String generateClanEducationCode(Campaign campaign, Person person
case 4:
case 5:
case 6:
caste = resources.getString("graduatedWarrior.text");
caste = resources.getString(getWarriorCasteSubCasteString(person.getEduCourseIndex()));
break;
case 7:
caste = resources.getString("graduatedScientist.text");
Expand Down Expand Up @@ -216,6 +216,44 @@ private static String generateClanEducationCode(Campaign campaign, Person person
}
}

/**
* Returns the sub-caste string corresponding to the given course index.
*
* @param courseIndex the index of the course
* @return the sub-caste string
*/
private static String getWarriorCasteSubCasteString(int courseIndex) {
String originCaste;

switch (courseIndex) {
case 0:
originCaste = "graduatedWarriorMechWarrior.text";
break;
case 1:
originCaste = "graduatedWarriorProtoMech.text";
break;
case 2:
originCaste = "graduatedWarriorAerospace.text";
break;
case 3:
originCaste = "graduatedWarriorSpace.text";
break;
case 4:
originCaste = "graduatedWarriorBa.text";
break;
case 5:
originCaste = "graduatedWarriorInfantry.text";
break;
case 6:
originCaste = "graduatedWarriorVehicle.text";
break;
default:
originCaste = "graduatedWarrior.text";
break;
}
return originCaste;
}

/**
* Generates a military academy prefix randomly selected from the resource bundle.
*
Expand Down Expand Up @@ -341,7 +379,6 @@ public static boolean processNewDay(Campaign campaign, Person person, boolean ag
* @param campaign The campaign the person is part of.
* @param person The person for whom the journey is being processed.
* @param resources The resource bundle containing localized strings.
* @return True if the person's journey to campus was processed, false otherwise.
*/
private static void journeyToAcademy(Campaign campaign, Person person, ResourceBundle resources) {
int daysOfTravelTo = person.getEduDaysOfTravelToAcademy();
Expand Down Expand Up @@ -437,10 +474,7 @@ private static void graduationPicker(Campaign campaign, Person person, Academy a
*
* @param campaign The campaign the person is part of.
* @param person The person for whom the journey is being processed.
* @param daysOfEducation the number education days the person has remaining
* @param resources the resource bundle for localization
* @return the number of travel days from the academy, or null if the person has no education days and no
* previous travel days
*/
private static void beginJourneyHome(Campaign campaign, Person person, Academy academy, ResourceBundle resources) {
int travelTime = 0;
Expand Down Expand Up @@ -905,8 +939,50 @@ private static boolean checkForAcademyDestruction(Campaign campaign, Academy aca
* @param resources the resource bundle containing the necessary text resources
*/
private static void processWarriorCasteWashout(Campaign campaign, Person person, ResourceBundle resources) {
ServiceLogger.eduClanWashout(person, campaign.getLocalDate(), resources.getString("graduatedWarrior.text"));
// log washout
String originCaste = getWarriorCasteSubCasteString(person.getEduCourseIndex());

ServiceLogger.eduClanWashout(person, campaign.getLocalDate(), resources.getString(originCaste));

// check for second chance caste
if (!campaign.getCampaignOptions().getSecondChanceCaste().isNone()) {
int secondChanceCasteIndex = getSecondChanceCasteIndex(campaign);

// a secondChanceCasteIndex of -1 means second chance caste is set to 'NONE', so we can skip the switch
if ((secondChanceCasteIndex != -1) && (person.getEduCourseIndex() != secondChanceCasteIndex)) {
switch (campaign.getCampaignOptions().getSecondChanceCaste()) {
case BA:
campaign.addReport(person.getHyperlinkedName() + ' ' + String.format(resources.getString("washout.text"),
resources.getString(originCaste),
resources.getString("graduatedWarriorBa.text")));
person.setEduCourseIndex(4);
person.setEduAcademyName(generateClanEducationCode(campaign, person, 4, resources));

return;
case INFANTRY:
campaign.addReport(person.getHyperlinkedName() + ' ' + String.format(resources.getString("washout.text"),
resources.getString(originCaste),
resources.getString("graduatedWarriorInfantry.text")));
person.setEduCourseIndex(5);
person.setEduAcademyName(generateClanEducationCode(campaign, person, 5, resources));

return;
case VEHICLE:
campaign.addReport(person.getHyperlinkedName() + ' ' + String.format(resources.getString("washout.text"),
resources.getString(originCaste),
resources.getString("graduatedWarriorVehicle.text")));
person.setEduCourseIndex(6);
person.setEduAcademyName(generateClanEducationCode(campaign, person, 6, resources));

return;
default:
throw new IllegalStateException("Unexpected value in mekhq/campaign/personnel/education/EducationController.java/processWarriorCasteWashout: "
+ campaign.getCampaignOptions().getSecondChanceCaste());
}
}
}

// otherwise, process washout into a civilian caste
int fallbackScientist = campaign.getCampaignOptions().getFallbackScientist();
int fallbackMerchant = campaign.getCampaignOptions().getFallbackMerchant() + fallbackScientist;
int fallbackTechnician = campaign.getCampaignOptions().getFallbackTechnician() + fallbackMerchant;
Expand All @@ -917,7 +993,7 @@ private static void processWarriorCasteWashout(Campaign campaign, Person person,
if (roll < fallbackScientist) {

campaign.addReport(person.getHyperlinkedName() + ' ' + String.format(resources.getString("washout.text"),
resources.getString("graduatedWarrior.text"),
resources.getString(originCaste),
resources.getString("graduatedWarriorScientist.text")));
person.setEduCourseIndex(7);
person.setEduAcademyName(generateClanEducationCode(campaign, person, 7, resources));
Expand All @@ -928,7 +1004,7 @@ private static void processWarriorCasteWashout(Campaign campaign, Person person,
if (roll < fallbackMerchant) {

campaign.addReport(person.getHyperlinkedName() + ' ' + String.format(resources.getString("washout.text"),
resources.getString("graduatedWarrior.text"),
resources.getString(originCaste),
resources.getString("graduatedWarriorMerchant.text")));
person.setEduCourseIndex(8);
person.setEduAcademyName(generateClanEducationCode(campaign, person, 8, resources));
Expand All @@ -939,7 +1015,7 @@ private static void processWarriorCasteWashout(Campaign campaign, Person person,
if (roll < fallbackTechnician) {

campaign.addReport(person.getHyperlinkedName() + ' ' + String.format(resources.getString("washout.text"),
resources.getString("graduatedWarrior.text"),
resources.getString(originCaste),
resources.getString("graduatedWarriorTechnician.text")));
person.setEduCourseIndex(9);
person.setEduAcademyName(generateClanEducationCode(campaign, person, 9, resources));
Expand All @@ -950,7 +1026,7 @@ private static void processWarriorCasteWashout(Campaign campaign, Person person,
// Labor

campaign.addReport(person.getHyperlinkedName() + ' ' + String.format(resources.getString("washout.text"),
resources.getString("graduatedWarrior.text"),
resources.getString(originCaste),
resources.getString("graduatedWarriorLabor.text")));
person.setEduCourseIndex(10);
person.setEduAcademyName(generateClanEducationCode(campaign, person, 10, resources));
Expand Down Expand Up @@ -1134,7 +1210,7 @@ private static void graduateClanCreche(Campaign campaign, Person person, Academy
*/
private static void graduateClanSibko(Campaign campaign, Person person, Academy academy, ResourceBundle resources) {
// Warrior Caste
// [0]MechWarrior, [1]ProtoMech, [2]AreoSpace, [3]Space, [4]BA, [5]CI, [6]Vehicle
// [0]MechWarrior, [1]ProtoMech, [2]Aerospace, [3]Space, [4]BA, [5]CI, [6]Vehicle
if (person.getEduCourseIndex() <= 6) {
graduateWarriorCaste(campaign, person, academy, resources);

Expand Down Expand Up @@ -1611,6 +1687,27 @@ private static String graduationEventPicker() {
return graduationEventTable.get(Compute.randomInt(graduationEventTable.size()));
}

/**
* Retrieves the course index value associated with the SecondChanceCaste assigned in campaign options.
*
* @return The course index of the chosen SecondChanceCaste.
* Returns -1 if NONE; 4 if BA; 5 if INFANTRY; 6 if VEHICLE.
*/
private static int getSecondChanceCasteIndex(Campaign campaign) {
switch (campaign.getCampaignOptions().getSecondChanceCaste()) {
case NONE:
return -1;
case BA:
return 4;
case INFANTRY:
return 5;
case VEHICLE:
return 6;
}

return -1;
}

/**
* Returns a list of graduation event table entries. The list contains various graduation event table entries such as addresses, admirer
* messages, events, gifts, pet costumes, recognitions, speeches, and surprises.
Expand Down
75 changes: 75 additions & 0 deletions MekHQ/src/mekhq/campaign/personnel/enums/SecondChanceCaste.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2020-2022 - The MegaMek Team. All Rights Reserved.
*
* This file is part of MekHQ.
*
* MekHQ is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MekHQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MekHQ. If not, see <http://www.gnu.org/licenses/>.
*/
package mekhq.campaign.personnel.enums;

import mekhq.MekHQ;

import java.util.ResourceBundle;

public enum SecondChanceCaste {
//region Enum Declarations
NONE("SecondChanceCaste.NONE.text", "SecondChanceCaste.NONE.toolTipText"),
BA("SecondChanceCaste.BA.text", "SecondChanceCaste.BA.toolTipText"),
INFANTRY("SecondChanceCaste.INFANTRY.text", "SecondChanceCaste.INFANTRY.toolTipText"),
VEHICLE("SecondChanceCaste.VEHICLE.text", "SecondChanceCaste.VEHICLE.toolTipText");
//endregion Enum Declarations

//region Variable Declarations
private final String name;
private final String toolTipText;
//endregion Variable Declarations

//region Constructors
SecondChanceCaste(final String name, final String toolTipText) {
final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel",
MekHQ.getMHQOptions().getLocale());
this.name = resources.getString(name);
this.toolTipText = resources.getString(toolTipText);
}
//endregion Constructors

//region Getters
public String getToolTipText() {
return toolTipText;
}
//endregion Getters

//region Boolean Comparison Methods
public boolean isNone() {
return this == NONE;
}

public boolean isBa() {
return this == BA;
}

public boolean isInfantry() {
return this == INFANTRY;
}

public boolean isVehicle() {
return this == VEHICLE;
}
//endregion Boolean Comparison Methods

@Override
public String toString() {
return name;
}
}
Loading

0 comments on commit c523ce4

Please sign in to comment.