Skip to content

Commit

Permalink
Merge pull request #6013 from IllianiCBT/dependents_tweaks
Browse files Browse the repository at this point in the history
Refactored Random Dependents Removal-Addition into a Seperate Class
  • Loading branch information
HammerGS authored Feb 11, 2025
2 parents 638f1a5 + 10ae705 commit 92341ca
Show file tree
Hide file tree
Showing 5 changed files with 386 additions and 174 deletions.
3 changes: 0 additions & 3 deletions MekHQ/resources/mekhq/resources/Campaign.properties
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,6 @@ turnoverPersonnelKilled.text=<html>You have personnel who have left the unit or
divorce.text=%s has divorced %s.

#### Unsorted Campaign Resources
dependentLeavesForce.text=%s %s have departed the force.
dependentLeavesForce.dependent.singular=dependent
dependentLeavesForce.dependent.plural=dependents
dependentJoinsForce.text=%s has started traveling with the force.
relativeJoinsForce.text=%s has started traveling with the force. They are %s's %s.
relativeJoinsForceSpouse.text=spouse
Expand Down
5 changes: 5 additions & 0 deletions MekHQ/resources/mekhq/resources/RandomDependents.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dependentJoinsForce.report={0} has started traveling with the force as a {0}.
dependentLeavesForce.report={0} {1} have departed the force.

dependent.singular=Dependent
dependent.plural=Dependents
174 changes: 3 additions & 171 deletions MekHQ/src/mekhq/campaign/Campaign.java
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@

import static java.lang.Math.floor;
import static java.lang.Math.max;
import static java.lang.Math.round;
import static megamek.common.Compute.d6;
import static mekhq.campaign.CampaignOptions.TRANSIT_UNIT_MONTH;
import static mekhq.campaign.CampaignOptions.TRANSIT_UNIT_WEEK;
Expand Down Expand Up @@ -312,7 +311,7 @@ public class Campaign implements ITechManager {
private BehaviorSettings autoResolveBehaviorSettings;
private List<Unit> automatedMothballUnits;

//options relating to parts in use and restock
//options relating to parts in use and restock
private boolean ignoreMothballed;
private boolean topUpWeekly;
private PartQuality ignoreSparesUnderQuality;
Expand Down Expand Up @@ -4872,7 +4871,8 @@ public boolean newDay() {
}

if ((location.isOnPlanet()) && (currentDay.getDayOfMonth() == 1)) {
processRandomDependents();
RandomDependents randomDependents = new RandomDependents(this);
randomDependents.processMonthlyRemovalAndAddition();
}

resetAstechMinutes();
Expand Down Expand Up @@ -4986,174 +4986,6 @@ public void setInitiativeMaxBonus(int bonus) {
initiativeMaxBonus = bonus;
}

/**
* Processes the random addition and removal of dependents, adjusting the active dependents
* list based on campaign options, active personnel, and unit rating modifiers.
*
* <p>This method operates in the following steps:
* <ol>
* <li>Filters active personnel into dependents and non-dependents. Dependents without a family
* (i.e., an empty genealogy) are added to the list of active dependents, while eligible non-dependents
* are counted to determine the dependent capacity.</li>
* <li>Calculates the dependent capacity as 5% of active non-dependents, with a minimum
* value of 1.</li>
* <li>Randomly removes dependents from the active list based on campaign options and a roll
* compared to the unit rating modifier.</li>
* <li>Randomly adds new dependents, if allowed, ensuring the total number of dependents does not exceed
* the dependent capacity. The addition is based on a roll relative to the unit rating modifier.</li>
* </ol>
*
* <p>The method ensures that the number of dependents is managed dynamically and reflects the
* current status of the campaign, its personnel, and relevant modifiers.
*/
private void processRandomDependents() {
int activeNonDependents = 0;
List<Person> activeDependents = new ArrayList<>();

for (Person person : getActivePersonnel()) {
if (!person.getPrisonerStatus().isFreeOrBondsman()) {
continue;
}
if (person.isChild(currentDay)) {
continue;
}
if (person.isDependent()) {
if (person.getGenealogy().familyIsEmpty()) {
activeDependents.add(person);
}
continue;
}

activeNonDependents++;
}

// Prepare the data
int dependentCapacity = max(1, (int) round(activeNonDependents * 0.05));
Collections.shuffle(activeDependents);

// roll for random removal
int dependentCount = dependentsRollForRemoval(activeDependents, dependentCapacity);

// then roll for random addition
dependentsAddNew(dependentCount, dependentCapacity);
}

/**
* Randomly removes dependents from the given list if the campaign options allow random
* dependent removal.
*
* @param dependents The list of dependents.
* @param dependentCapacity The maximum number of dependents allowed.
* @return The updated number of dependents.
*/
int dependentsRollForRemoval(List<Person> dependents, int dependentCapacity) {
List<Person> dependentsToRemove = new ArrayList<>();

if (getCampaignOptions().isUseRandomDependentRemoval()) {
for (Person dependent : dependents) {
if (!isRemovalEligible(dependent, currentDay)) {
continue;
}

int roll = Compute.randomInt(100);

if (dependents.size() > dependentCapacity) {
roll = getLowerRandomInt(roll);
}

int targetNumber = 5 - getAtBUnitRatingMod();

if (roll <= targetNumber) {
dependentsToRemove.add(dependent);

Genealogy genealogy = dependent.getGenealogy();
for (Person child : genealogy.getChildren()) {
if (child.isChild(currentDay)) {
dependentsToRemove.add(child);
}
}

Person spouse = genealogy.getSpouse();
if (spouse.isDependent()) {
dependentsToRemove.add(spouse);
}
}
}

if (!dependentsToRemove.isEmpty()) {
String pluralizer = dependentsToRemove.size() == 1
? resources.getString("dependentLeavesForce.dependent.singular")
: resources.getString("dependentLeavesForce.dependent.plural");

addReport(String.format(resources.getString("dependentLeavesForce.text"),
dependentsToRemove.size(), pluralizer));
}

for (Person dependent : dependentsToRemove) {
dependent.changeStatus(this, currentDay, PersonnelStatus.LEFT);
}
}

return dependents.size();
}

/**
* @return The lower integer value between the given input and the randomly generated integer.
*
* @param firstRoll The input integer to compare with the randomly generated integer.
*/
private int getLowerRandomInt(int firstRoll) {
int secondRoll = Compute.randomInt(100);
return Math.min(firstRoll, secondRoll);
}

/**
* Checks if a dependent is eligible for removal.
*
* @param dependent the person to check
* @param currentDate the current date
* @return {@code true} if the person is eligible for removal, {@code false} otherwise
*/
boolean isRemovalEligible(Person dependent, LocalDate currentDate) {
boolean hasNonAdultChildren = dependent.getGenealogy().hasNonAdultChildren(currentDate);
boolean hasSpouse = dependent.getGenealogy().hasSpouse();
boolean isChild = dependent.isChild(currentDate);

return !hasNonAdultChildren && !hasSpouse && !isChild;
}

/**
* Randomly adds new dependents to the campaign.
*
* @param dependentCount the current number of dependents
* @param dependentCapacity the maximum capacity for dependents
*/
void dependentsAddNew(int dependentCount, int dependentCapacity) {
if ((getCampaignOptions().isUseRandomDependentAddition()) && (dependentCount < dependentCapacity)) {
int availableCapacity = dependentCapacity - dependentCount;
int rollCount = (int) max(1, availableCapacity * 0.2);

for (int i = 0; i < rollCount; i++) {
int roll = Compute.randomInt(100);

if (dependentCount < (dependentCapacity / 2)) {
roll = getLowerRandomInt(roll);
}

if (roll <= (getAtBUnitRatingMod() * 2)) {
final Person dependent = newDependent(Gender.RANDOMIZE);

recruitPerson(dependent, PrisonerStatus.FREE, true, false);

addReport(String.format(resources.getString("dependentJoinsForce.text"),
dependent.getHyperlinkedFullTitle()));

dependentCount++;
}
}
}
}

/**
* This method iterates through the list of personnel and deletes the records of
* those who have left the unit and who match additional checks.
Expand Down
Loading

0 comments on commit 92341ca

Please sign in to comment.