/*
* AtBContract.java
*
* Copyright (c) 2014 Carl Spain. 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.mission;
import java.io.PrintWriter;
import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.UUID;
import megamek.client.RandomSkillsGenerator;
import megamek.client.RandomUnitGenerator;
import megamek.common.Compute;
import megamek.common.Entity;
import megamek.common.MechFileParser;
import megamek.common.MechSummary;
import megamek.common.Player;
import megamek.common.UnitType;
import megamek.common.loaders.EntityLoadingException;
import mekhq.MekHQ;
import mekhq.MekHqXmlUtil;
import mekhq.campaign.Campaign;
import mekhq.campaign.market.UnitMarket;
import mekhq.campaign.personnel.Person;
import mekhq.campaign.personnel.SkillType;
import mekhq.campaign.rating.IUnitRating;
import mekhq.campaign.unit.Unit;
import mekhq.campaign.universe.Faction;
import mekhq.campaign.universe.RandomFactionGenerator;
import mekhq.gui.view.LanceAssignmentView;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Contract class for use with Against the Bot rules
*
* @author Neoancient
*
*/
public class AtBContract extends Contract implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1491090021356604379L;
public static final int MT_GARRISONDUTY = 0;
public static final int MT_CADREDUTY = 1;
public static final int MT_SECURITYDUTY = 2;
public static final int MT_RIOTDUTY = 3;
public static final int MT_PLANETARYASSAULT = 4;
public static final int MT_RELIEFDUTY = 5;
public static final int MT_GUERRILLAWARFARE = 6;
public static final int MT_PIRATEHUNTING = 7;
public static final int MT_DIVERSIONARYRAID = 8;
public static final int MT_OBJECTIVERAID = 9;
public static final int MT_RECONRAID = 10;
public static final int MT_EXTRACTIONRAID = 11;
public static final int MT_NUM = 12;
public static final String[] missionTypeNames = {
"Garrison Duty", "Cadre Duty", "Security Duty", "Riot Duty",
"Planetary Assault", "Relief Duty", "Guerrilla Warfare",
"Pirate Hunting", "Diversionary Raid", "Objective Raid",
"Recon Raid", "Extraction Raid"
};
public static final int MORALE_ROUT = 0;
public static final int MORALE_VERYLOW = 1;
public static final int MORALE_LOW = 2;
public static final int MORALE_NORMAL = 3;
public static final int MORALE_HIGH = 4;
public static final int MORALE_INVINCIBLE = 5;
public static final int MORALE_NUM = 6;
public static final String[] moraleLevelNames = {
"Rout", "Very Low", "Low", "Normal", "High", "Invincible"
};
public static final int EVT_NOEVENT = -1;
public static final int EVT_BONUSROLL = 0;
public static final int EVT_SPECIALMISSION = 1;
public static final int EVT_CIVILDISTURBANCE = 2;
public static final int EVT_SPORADICUPRISINGS = 3;
public static final int EVT_REBELLION = 4;
public static final int EVT_BETRAYAL = 5;
public static final int EVT_TREACHERY = 6;
public static final int EVT_LOGISTICSFAILURE = 7;
public static final int EVT_REINFORCEMENTS = 8;
public static final int EVT_SPECIALEVENTS = 9;
public static final int EVT_BIGBATTLE = 10;
/* null unless subcontract */
protected AtBContract parentContract;
/* hired by another mercenary unit on contract to a third-party employer */
boolean mercSubcontract;
protected String employerCode;
protected String enemyCode;
protected int missionType;
protected int allySkill;
protected int allyQuality;
protected int enemySkill;
protected int enemyQuality;
protected String allyBotName;
protected String enemyBotName;
protected String allyCamoCategory;
protected String allyCamoFileName;
protected int allyColorIndex;
protected String enemyCamoCategory;
protected String enemyCamoFileName;
protected int enemyColorIndex;
protected int extensionLength;
protected int requiredLances;
protected int moraleLevel;
protected Date routEnd;
protected int partsAvailabilityLevel;
protected int sharesPct;
protected int playerMinorBreaches;
protected int employerMinorBreaches;
protected int moraleMod = 0;
protected int numBonusParts;
/* lasts for a month, then removed at next events roll */
protected boolean priorLogisticsFailure;
/* If the date is non-null, there will be a special mission or big battle
* on that date, but the scenario is not generated until the other battle
* rolls for the week.
*/
protected Date specialEventScenarioDate;
protected int specialEventScenarioType;
/* Lasts until end of contract */
protected int battleTypeMod;
/* Only applies to next week */
protected int nextWeekBattleTypeMod;
protected AtBContract() {
this(null);
}
public AtBContract(String name) {
super(name, "Independent");
employerCode = "IND";
enemyCode = "IND";
parentContract = null;
mercSubcontract = false;
missionType = MT_GARRISONDUTY;
allySkill = RandomSkillsGenerator.L_REG;
allyQuality = IUnitRating.DRAGOON_C;
enemySkill = RandomSkillsGenerator.L_REG;
enemyQuality = IUnitRating.DRAGOON_C;
allyBotName = "Ally";
enemyBotName = "Enemy";
allyCamoCategory = Player.NO_CAMO;
allyCamoFileName = null;
allyColorIndex = 1;
enemyCamoCategory = Player.NO_CAMO;
enemyCamoFileName = null;
enemyColorIndex = 2;
extensionLength = 0;
sharesPct = 0;
moraleLevel = MORALE_NORMAL;
routEnd = null;
numBonusParts = 0;
priorLogisticsFailure = false;
specialEventScenarioDate = null;
battleTypeMod = 0;
nextWeekBattleTypeMod = 0;
}
public void initContractDetails(Campaign campaign) {
if (parentContract != null) {
requiredLances = 1;
} else {
requiredLances = Math.max(getEffectiveNumUnits(campaign) / 6, 1);
}
if (getEffectiveNumUnits(campaign) <= 12) {
setOverheadComp(OH_FULL);
} else if (getEffectiveNumUnits(campaign) <= 48) {
setOverheadComp(OH_HALF);
} else {
setOverheadComp(OH_NONE);
}
allyBotName = getEmployerName(campaign.getEra());
enemyBotName = getEnemyName(campaign.getEra());
}
public void calculateLength(boolean variable) {
if (variable) {
calculateVariableLength();
} else {
switch (missionType) {
case AtBContract.MT_CADREDUTY:
setLength(12);
break;
case AtBContract.MT_GARRISONDUTY:
setLength(18);
break;
case AtBContract.MT_SECURITYDUTY:
case AtBContract.MT_PIRATEHUNTING:
setLength(6);
break;
case AtBContract.MT_DIVERSIONARYRAID:
case AtBContract.MT_EXTRACTIONRAID:
case AtBContract.MT_OBJECTIVERAID:
case AtBContract.MT_RECONRAID:
setLength(3);
break;
case AtBContract.MT_GUERRILLAWARFARE:
setLength(24);
break;
case AtBContract.MT_PLANETARYASSAULT:
case AtBContract.MT_RELIEFDUTY:
setLength(9);
break;
case AtBContract.MT_RIOTDUTY:
setLength(4);
break;
}
}
}
/* Variable contract lengths taken from AtB v. 2.25 */
private void calculateVariableLength() {
switch (missionType) {
case MT_CADREDUTY:
case MT_SECURITYDUTY:
setLength(4);
break;
case MT_GARRISONDUTY:
setLength(9 + Compute.d6(3));
break;
case MT_DIVERSIONARYRAID:
case MT_RECONRAID:
setLength(1);
break;
case MT_EXTRACTIONRAID:
setLength(3 + enemySkill);
break;
case MT_GUERRILLAWARFARE:
case MT_RIOTDUTY:
setLength(6);
break;
case MT_OBJECTIVERAID:
case MT_PIRATEHUNTING:
setLength(3 + Compute.randomInt(3));
break;
case MT_PLANETARYASSAULT:
case MT_RELIEFDUTY:
setLength(4 + Compute.randomInt(3));
break;
}
}
public void calculatePartsAvailabilityLevel(Campaign campaign) {
/* AtB rules apply -1 from 2950 to 3040, but MekHQ accounts
* for era variations already
*/
switch (missionType) {
case MT_GUERRILLAWARFARE:
partsAvailabilityLevel = 0;
break;
case MT_DIVERSIONARYRAID:
case MT_OBJECTIVERAID:
case MT_RECONRAID:
case MT_EXTRACTIONRAID:
partsAvailabilityLevel = 1;
break;
case MT_PLANETARYASSAULT:
case MT_RELIEFDUTY:
partsAvailabilityLevel = 2;
break;
case MT_PIRATEHUNTING:
partsAvailabilityLevel = 3;
break;
default:
partsAvailabilityLevel = 4;
}
}
public static int getEffectiveNumUnits(Campaign campaign) {
double numUnits = 0;
for (UUID uuid : campaign.getForces().getAllUnits()) {
if (null == campaign.getUnit(uuid)) {
continue;
}
switch (UnitType.determineUnitTypeCode(campaign.getUnit(uuid).getEntity())) {
case UnitType.MEK:
numUnits += 1;
break;
case UnitType.TANK:
case UnitType.VTOL:
case UnitType.NAVAL:
numUnits += campaign.getFaction().isClan()?0.5:1;
break;
case UnitType.CONV_FIGHTER:
case UnitType.AERO:
if (campaign.getCampaignOptions().getUseAero()) {
numUnits += campaign.getFaction().isClan()?0.5:1;
}
break;
case UnitType.PROTOMEK:
numUnits += 0.2;
break;
case UnitType.BATTLE_ARMOR:
case UnitType.INFANTRY:
default:
/* don't count */
}
}
return (int)numUnits;
}
public static boolean isMinorPower(String fName) {
return !RandomFactionGenerator.getInstance().isISMajorPower(fName) &&
!Faction.getFaction(fName).isClan();
}
public void calculatePaymentMultiplier(Campaign campaign) {
int unitRatingMod = campaign.getUnitRatingMod();
double multiplier = 1.0;
// IntOps reputation factor then Dragoons rating
if (campaign.getCampaignOptions().useDragoonRating()
&& campaign.getCampaignOptions().getUnitRatingMethod().equals(mekhq.campaign.rating.UnitRatingMethod.CAMPAIGN_OPS)) {
multiplier *= (unitRatingMod * .2) + .5;
} else {
if (unitRatingMod >= IUnitRating.DRAGOON_A){
multiplier *= 2.0;
}
if (unitRatingMod == IUnitRating.DRAGOON_B){
multiplier *= 1.5;
}
if (unitRatingMod == IUnitRating.DRAGOON_D){
multiplier *= 0.8;
}
if (unitRatingMod == IUnitRating.DRAGOON_F){
multiplier *= 0.5;
}
}
switch (missionType) {
case MT_CADREDUTY:
multiplier *= 0.8;
break;
case MT_SECURITYDUTY:
multiplier *= 1.2;
break;
case MT_DIVERSIONARYRAID:
multiplier *= 1.8;
break;
case MT_EXTRACTIONRAID:
multiplier *= 1.6;
break;
case MT_GUERRILLAWARFARE:
multiplier *= 2.1;
break;
case MT_OBJECTIVERAID:
multiplier *= 1.6;
break;
case MT_PLANETARYASSAULT:
multiplier *= 1.5;
break;
case MT_RECONRAID:
multiplier *= 1.6;
break;
case MT_RELIEFDUTY:
multiplier *= 1.4;
break;
}
if (RandomFactionGenerator.getInstance().isISMajorPower(employerCode)
|| Faction.getFaction(employerCode).isClan()) {
multiplier *= 1.2;
} else if (enemyCode.equals("IND") ||
enemyCode.equals("PIND")) {
multiplier *= 1.0;
} else {
multiplier *= 1.1;
}
if (enemyCode.equals("REB") ||
enemyCode.equals("PIR")) {
multiplier *= 1.1;
}
int cmdrStrategy = 0;
if (campaign.getFlaggedCommander() != null &&
campaign.getFlaggedCommander().getSkill(SkillType.S_STRATEGY) != null) {
cmdrStrategy = campaign.getFlaggedCommander().
getSkill(SkillType.S_STRATEGY).getLevel();
}
int maxDeployedLances =
campaign.getCampaignOptions().getBaseStrategyDeployment() +
campaign.getCampaignOptions().getAdditionalStrategyDeployment() *
cmdrStrategy;
int required = Math.max(getEffectiveNumUnits(campaign) / 6, 1);
if (campaign.getCampaignOptions().getAdjustPaymentForStrategy() &&
required > maxDeployedLances) {
multiplier *= (double)maxDeployedLances / (double)required;
requiredLances = maxDeployedLances;
}
setMultiplier(multiplier);
}
public void checkMorale(GregorianCalendar calendar, int dragoonRating) {
if (null != routEnd) {
if (calendar.getTime().after(routEnd)) {
moraleLevel = MORALE_NORMAL;
routEnd = null;
} else {
moraleLevel = MORALE_ROUT;
}
return;
}
int victories = 0;
int defeats = 0;
GregorianCalendar lastMonth = (GregorianCalendar)calendar.clone();
lastMonth.add(Calendar.MONTH, -1);
for (Scenario s : getScenarios()) {
if (lastMonth.after(s.getDate())) {
continue;
}
if (s.getStatus() == Scenario.S_VICTORY ||
s.getStatus() == Scenario.S_MVICTORY) {
victories++;
}
if (s.getStatus() == Scenario.S_DEFEAT ||
s.getStatus() == Scenario.S_MDEFEAT) {
defeats++;
}
}
int mod = Math.max(enemySkill - 2, -1);
mod += dragoonRating - IUnitRating.DRAGOON_C;
mod -= victories / 5;
mod += defeats / 2;
mod += moraleMod;
if (enemyCode.equals("PIR"))
mod -= 2;
else if (enemyCode.equals("REB") ||
isMinorPower(enemyCode) ||
enemyCode.equals("MERC"))
mod -= 1;
else if (Faction.getFaction(enemyCode).isClan())
mod += 2;
if (victories == 0) {
mod++;
}
if (defeats == 0) {
mod--;
}
int roll = Compute.d6(2) + mod;
if (roll < 2) moraleLevel -= 2;
else if (roll < 6) moraleLevel -= 1;
else if (roll > 12) moraleLevel += 2;
else if (roll > 8) moraleLevel += 1;
if (moraleLevel < 0) moraleLevel = 0;
if (moraleLevel > 5) moraleLevel = 5;
if (moraleLevel == 0 && missionType <= MT_RIOTDUTY) {
GregorianCalendar nextBattleRoll = (GregorianCalendar)calendar.clone();
nextBattleRoll.add(Calendar.MONTH, Math.max(1, Compute.d6() - 3));
nextBattleRoll.add(Calendar.DAY_OF_MONTH, -1);
routEnd = nextBattleRoll.getTime();
}
moraleMod = 0;
}
public int getRepairLocation(int dragoonRating) {
int retval = Unit.SITE_BAY;
if (missionType == MT_GUERRILLAWARFARE ||
missionType >= MT_DIVERSIONARYRAID) {
retval = Unit.SITE_FIELD;
} else if (missionType > MT_RIOTDUTY) {
retval = Unit.SITE_MOBILE_BASE;
}
if (dragoonRating >= IUnitRating.DRAGOON_B) {
retval++;
}
return Math.min(retval, Unit.SITE_BAY);
}
public void addMoraleMod(int mod) {
moraleMod += mod;
}
public int getRequiredLanceType() {
return getRequiredLanceType(missionType);
}
public static int getRequiredLanceType(int missionType) {
switch (missionType) {
case MT_CADREDUTY:
return LanceAssignmentView.ROLE_TRAINING;
case MT_GARRISONDUTY:
case MT_SECURITYDUTY:
case MT_RIOTDUTY:
return LanceAssignmentView.ROLE_DEFEND;
case MT_GUERRILLAWARFARE:
case MT_PIRATEHUNTING:
case MT_PLANETARYASSAULT:
case MT_RELIEFDUTY:
return LanceAssignmentView.ROLE_FIGHT;
case MT_DIVERSIONARYRAID:
case MT_EXTRACTIONRAID:
case MT_OBJECTIVERAID:
case MT_RECONRAID:
return LanceAssignmentView.ROLE_SCOUT;
}
return LanceAssignmentView.ROLE_NONE;
}
public int getScore() {
int score = employerMinorBreaches - playerMinorBreaches;
int battles = 0;
boolean earlySuccess = false;
for (Scenario s : getScenarios()) {
/* Special Missions get no points for victory and and only -1
* for defeat.
*/
if (s instanceof AtBScenario &&
((AtBScenario)s).getBattleType() >= AtBScenario.SPECIALMISSIONS &&
((AtBScenario)s).getBattleType() < AtBScenario.BIGBATTLES) {
if (s.getStatus() == Scenario.S_DEFEAT ||
s.getStatus() == Scenario.S_MDEFEAT) {
score--;
}
} else {
switch (s.getStatus()) {
case Scenario.S_VICTORY:
case Scenario.S_MVICTORY:
score++;
battles++;
break;
case Scenario.S_DEFEAT:
score -= 2;
battles++;
break;
case Scenario.S_MDEFEAT:
//special mission defeat
score--;
break;
}
}
if (s instanceof AtBScenario
&& ((AtBScenario)s).getBattleType() == AtBScenario.BASEATTACK
&& ((AtBScenario)s).isAttacker()
&& (s.getStatus() == Scenario.S_VICTORY ||
s.getStatus() == Scenario.S_MVICTORY)) {
earlySuccess = true;
}
if (missionType > MT_RIOTDUTY && moraleLevel == MORALE_ROUT) {
earlySuccess = true;
}
}
if (battles == 0) {
score++;
}
if (earlySuccess) {
score += 4;
}
return score;
}
public void doBonusRoll(Campaign c) {
int number;
String rat = null;
int roll = Compute.d6();
switch (roll) {
case 1: /* 1d6 dependents */
number = Compute.d6();
c.addReport("Bonus: " + number + " dependent" + ((number>1)?"s":""));
for (int i = 0; i < number; i++) {
Person p = c.newPerson(Person.T_ASTECH);
p.setDependent(true);
p.setId(UUID.randomUUID());
c.addPersonWithoutId(p, true);
}
break;
case 2: /* Recruit (choose) */
c.addReport("Bonus: hire one recruit of your choice.");
break;
case 3: /* 1d6 parts */
number = Compute.d6();
numBonusParts += number;
c.addReport("Bonus: " + number + " part" + ((number>1)?"s":""));
break;
case 4: /* civilian vehicle */
rat = "CivilianUnits_CivVeh";
c.addReport("Bonus: civilian vehicle");
break;
case 5: /* APC */
rat = "CivilianUnits_APC";
c.addReport("Bonus: civilian APC");
break;
case 6: /* civilian 'Mech */
rat = "CivilianUnits_PrimMech";
c.addReport("Bonus: civilian Mek");
break;
}
if (null != rat) {
Entity en = null;
RandomUnitGenerator.getInstance().setChosenRAT(rat);
ArrayList<MechSummary> msl = RandomUnitGenerator.getInstance().generate(1);
if (msl.size() > 0 && null != msl.get(0)) {
try {
en = new MechFileParser(msl.get(0).getSourceFile(), msl.get(0).getEntryName()).getEntity();
} catch (EntityLoadingException ex) {
en = null;
MekHQ.logError("Unable to load entity: " + msl.get(0).getSourceFile() + ": " + msl.get(0).getEntryName() + ": " + ex.getMessage());
MekHQ.logError(ex);
}
}
if (null != en) {
c.addUnit(en, false, 0);
} else {
c.addReport("<html><font color='red'>Could not load unit</font></html>");
}
}
}
public boolean isSubcontract() {
return parentContract != null;
}
public AtBContract getParentContract() {
return parentContract;
}
public void setParentContract(AtBContract parent) {
parentContract = parent;
}
public boolean isMercSubcontract() {
return mercSubcontract;
}
public void setMercSubcontract(boolean sub) {
mercSubcontract = sub;
}
public void checkEvents(Campaign c) {
if (c.getCalendar().get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
nextWeekBattleTypeMod = 0;
}
if (c.getCalendar().get(Calendar.DAY_OF_MONTH) == 1) {
if (priorLogisticsFailure) {
partsAvailabilityLevel++;
priorLogisticsFailure = false;
}
int event;
int roll = Compute.randomInt(20) + 1;
switch (missionType) {
case MT_DIVERSIONARYRAID:
case MT_OBJECTIVERAID:
case MT_RECONRAID:
case MT_EXTRACTIONRAID:
if (roll < 10) event = EVT_BONUSROLL;
else if (roll < 14) event = EVT_SPECIALMISSION;
else if (roll < 16) event = EVT_BETRAYAL;
else if (roll < 17) event = EVT_TREACHERY;
else if (roll < 18) event = EVT_LOGISTICSFAILURE;
else if (roll < 19) event = EVT_REINFORCEMENTS;
else if (roll < 20) event = EVT_SPECIALEVENTS;
else event = EVT_BIGBATTLE;
break;
case MT_GARRISONDUTY:
if (roll < 8) event = EVT_BONUSROLL;
else if (roll < 12) event = EVT_SPECIALMISSION;
else if (roll < 13) event = EVT_CIVILDISTURBANCE;
else if (roll < 14) event = EVT_SPORADICUPRISINGS;
else if (roll < 15) event = EVT_REBELLION;
else if (roll < 16) event = EVT_BETRAYAL;
else if (roll < 17) event = EVT_TREACHERY;
else if (roll < 18) event = EVT_LOGISTICSFAILURE;
else if (roll < 19) event = EVT_REINFORCEMENTS;
else if (roll < 20) event = EVT_SPECIALEVENTS;
else event = EVT_BIGBATTLE;
break;
case MT_RIOTDUTY:
if (roll < 8) event = EVT_BONUSROLL;
else if (roll < 11) event = EVT_SPECIALMISSION;
else if (roll < 12) event = EVT_CIVILDISTURBANCE;
else if (roll < 13) event = EVT_SPORADICUPRISINGS;
else if (roll < 15) event = EVT_REBELLION;
else if (roll < 16) event = EVT_BETRAYAL;
else if (roll < 17) event = EVT_TREACHERY;
else if (roll < 18) event = EVT_LOGISTICSFAILURE;
else if (roll < 19) event = EVT_REINFORCEMENTS;
else if (roll < 20) event = EVT_SPECIALEVENTS;
else event = EVT_BIGBATTLE;
break;
case MT_PIRATEHUNTING:
if (roll < 10) event = EVT_BONUSROLL;
else if (roll < 14) event = EVT_SPECIALMISSION;
else if (roll < 15) event = EVT_CIVILDISTURBANCE;
else if (roll < 16) event = EVT_BETRAYAL;
else if (roll < 17) event = EVT_TREACHERY;
else if (roll < 18) event = EVT_LOGISTICSFAILURE;
else if (roll < 19) event = EVT_REINFORCEMENTS;
else if (roll < 20) event = EVT_SPECIALEVENTS;
else event = EVT_BIGBATTLE;
break;
default:
if (roll < 10) event = EVT_BONUSROLL;
else if (roll < 15) event = EVT_SPECIALMISSION;
else if (roll < 16) event = EVT_BETRAYAL;
else if (roll < 17) event = EVT_TREACHERY;
else if (roll < 18) event = EVT_LOGISTICSFAILURE;
else if (roll < 19) event = EVT_REINFORCEMENTS;
else if (roll < 20) event = EVT_SPECIALEVENTS;
else event = EVT_BIGBATTLE;
}
switch (event) {
case EVT_BONUSROLL:
c.addReport("<b>Special Event:</b> ");
doBonusRoll(c);
break;
case EVT_SPECIALMISSION:
c.addReport("<b>Special Event:</b> Special mission this month");
specialEventScenarioDate = getRandomDayOfMonth(c.getCalendar());
specialEventScenarioType = findSpecialMissionType();
break;
case EVT_CIVILDISTURBANCE:
c.addReport("<b>Special Event:</b> Civil disturbance<br />Next enemy morale roll gets +1 modifier");
moraleMod++;
break;
case EVT_SPORADICUPRISINGS:
c.addReport("<b>Special Event:</b> Sporadic uprisings<br />+2 to next enemy morale roll");
moraleMod += 2;
break;
case EVT_REBELLION:
c.addReport("<b>Special Event:</b> Rebellion<br />+2 to next enemy morale roll");
specialEventScenarioDate = getRandomDayOfMonth(c.getCalendar());
specialEventScenarioType = AtBScenario.CIVILIANRIOT;
break;
case EVT_BETRAYAL:
String text = "<b>Special Event:</b> Betrayal (employer minor breach)<br />";
switch (Compute.d6()) {
case 1:
text += "Major logistics problem: parts availability level for the rest of the contract becomes one level lower.";
partsAvailabilityLevel--;
break;
case 2:
text += "Transport: Player is abandoned in the field by employer transports; if he loses a Base Attack battle he loses all Meks on repair.";
break;
case 3:
text += "Diversion: All Battle Type rolls for the rest of the contract get a -5 modifier.";
battleTypeMod -= 5;
break;
case 4:
text += "False Intelligence: Next week Battle Type rolls get a -10 modifier.";
nextWeekBattleTypeMod -= 10;
break;
case 5:
text += "The Company Store: All equipment/supply prices are increased by 100% until the end of the contract.";
break;
case 6:
text += "False Alarm: No betrayal, but the employer still gets a minor breach.";
}
employerMinorBreaches++;
c.addReport(text);
break;
case EVT_TREACHERY:
c.addReport("<b>Special Event:</b> Treachery<br />Bad information from employer. Next Enemy Morale roll gets +1. Employer minor breach.");
moraleMod++;
employerMinorBreaches++;
break;
case EVT_LOGISTICSFAILURE:
c.addReport("<b>Special Event:</b> Logistics Failure<br />Parts availability for the next month are one level lower.");
partsAvailabilityLevel--;
priorLogisticsFailure = true;
break;
case EVT_REINFORCEMENTS:
c.addReport("<b>Special Event:</b> Reinforcements<br />The next Enemy Morale roll gets a -1.");
moraleMod--;
break;
case EVT_SPECIALEVENTS:
text = new String ("<b>Special Event:</b> ");
switch (Compute.d6()) {
case 1:
text += "Change of Alliance: Next Enemy Morale roll gets a +1 modifier.";
moraleMod++;
break;
case 2:
text += "Internal Dissension";
specialEventScenarioDate = getRandomDayOfMonth(c.getCalendar());
specialEventScenarioType = AtBScenario.AMBUSH;
break;
case 3:
text += "ComStar Interdict: Base availability level decreases one level for the rest of the contract.";
partsAvailabilityLevel--;
break;
case 4:
text += "Defectors: Next Enemy Morale roll gets a -1 modifier.";
moraleMod--;
break;
case 5:
text += "Free Trader: Base availability level increases one level for the rest of the contract.";
partsAvailabilityLevel++;
break;
case 6:
String unit =
c.getUnitMarket().addSingleUnit(c, UnitMarket.MARKET_EMPLOYER,
UnitType.MEK, getEmployerCode(),
IUnitRating.DRAGOON_F, 50) +
" offered by employer on the <a href='UNIT_MARKET'>unit market</a>";
if (unit != null) {
text += "Surplus Sale: " + unit;
}
}
c.addReport(text);
break;
case EVT_BIGBATTLE:
c.addReport("<b>Special Event:</b> Big battle this month");
specialEventScenarioDate = getRandomDayOfMonth(c.getCalendar());
specialEventScenarioType = findBigBattleType();
break;
}
}
/* If the campaign somehow gets past the scheduled date (such as by
* changing the date in the campaign options), ignore it rather
* than generating a new scenario in the past. The event will still be
* available (if the campaign date is restored) until another special mission
* or big battle event is rolled.
*/
if (null != specialEventScenarioDate
&& !specialEventScenarioDate.before(c.getDate())) {
GregorianCalendar nextMonday = (GregorianCalendar)c.getCalendar().clone();
/* value of Calendar.MONDAY depends on locale */
if (c.getCalendar().get(Calendar.DAY_OF_WEEK) >= Calendar.MONDAY) {
nextMonday.add(Calendar.DAY_OF_WEEK, 7);
}
nextMonday.add(Calendar.DAY_OF_WEEK, Calendar.MONDAY - c.getCalendar().get(Calendar.DAY_OF_WEEK));
if (specialEventScenarioDate.before(nextMonday.getTime())) {
AtBScenario s = new AtBScenario(c, null,
specialEventScenarioType, false,
specialEventScenarioDate);
c.addScenario(s, this);
if (c.getCampaignOptions().getUsePlanetaryConditions()) {
s.setPlanetaryConditions(this, c);
}
s.setForces(c);
specialEventScenarioDate = null;
}
}
}
public Date getRandomDayOfMonth(GregorianCalendar cal) {
GregorianCalendar calendar = (GregorianCalendar)cal.clone();
calendar.set(Calendar.DAY_OF_MONTH, Compute.randomInt(calendar.getActualMaximum(Calendar.DAY_OF_MONTH)) + 1);
return calendar.getTime();
}
public int findSpecialMissionType() {
int roll = Compute.randomInt(20) + 1;
if (missionType >= MT_DIVERSIONARYRAID) {
if (roll <= 1) return AtBScenario.OFFICERDUEL;
if (roll <= 2) return AtBScenario.ACEDUEL;
if (roll <= 6) return AtBScenario.AMBUSH;
if (roll <= 7) return AtBScenario.CIVILIANHELP;
if (roll <= 8) return AtBScenario.ALLIEDTRAITORS;
if (roll <= 12) return AtBScenario.PRISONBREAK;
if (roll <= 16) return AtBScenario.STARLEAGUECACHE1;
return AtBScenario.STARLEAGUECACHE2;
} else if (missionType == MT_GARRISONDUTY) {
if (roll <= 2) return AtBScenario.OFFICERDUEL;
if (roll <= 4) return AtBScenario.ACEDUEL;
if (roll <= 6) return AtBScenario.AMBUSH;
if (roll <= 10) return AtBScenario.CIVILIANHELP;
if (roll <= 12) return AtBScenario.ALLIEDTRAITORS;
if (roll <= 16) return AtBScenario.STARLEAGUECACHE1;
return AtBScenario.STARLEAGUECACHE2;
} else if (missionType == MT_RIOTDUTY) {
if (roll <= 1) return AtBScenario.OFFICERDUEL;
if (roll <= 3) return AtBScenario.ACEDUEL;
if (roll <= 7) return AtBScenario.AMBUSH;
if (roll <= 8) return AtBScenario.CIVILIANHELP;
if (roll <= 12) return AtBScenario.ALLIEDTRAITORS;
if (roll <= 16) return AtBScenario.STARLEAGUECACHE1;
return AtBScenario.STARLEAGUECACHE2;
} else if (missionType == MT_PIRATEHUNTING) {
if (roll <= 1) return AtBScenario.OFFICERDUEL;
if (roll <= 4) return AtBScenario.ACEDUEL;
if (roll <= 7) return AtBScenario.AMBUSH;
if (roll <= 11) return AtBScenario.CIVILIANHELP;
if (roll <= 12) return AtBScenario.ALLIEDTRAITORS;
if (roll <= 16) return AtBScenario.STARLEAGUECACHE1;
return AtBScenario.STARLEAGUECACHE2;
} else {
if (roll <= 2) return AtBScenario.OFFICERDUEL;
if (roll <= 4) return AtBScenario.ACEDUEL;
if (roll <= 6) return AtBScenario.AMBUSH;
if (roll <= 8) return AtBScenario.CIVILIANHELP;
if (roll <= 10) return AtBScenario.ALLIEDTRAITORS;
if (roll <= 12) return AtBScenario.PRISONBREAK;
if (roll <= 16) return AtBScenario.STARLEAGUECACHE1;
return AtBScenario.STARLEAGUECACHE2;
}
}
public int findBigBattleType() {
int roll = Compute.d6();
if (missionType >= MT_DIVERSIONARYRAID) {
if (roll <= 1) return AtBScenario.ALLYRESCUE;
if (roll <= 2) return AtBScenario.CONVOYRESCUE;
if (roll <= 5) return AtBScenario.CONVOYATTACK;
return AtBScenario.PIRATEFREEFORALL;
} else if (missionType == MT_GARRISONDUTY) {
if (roll <= 2) return AtBScenario.ALLYRESCUE;
if (roll <= 3) return AtBScenario.CIVILIANRIOT;
if (roll <= 5) return AtBScenario.CONVOYRESCUE;
return AtBScenario.PIRATEFREEFORALL;
} else if (missionType == MT_RIOTDUTY) {
if (roll <= 1) return AtBScenario.ALLYRESCUE;
if (roll <= 4) return AtBScenario.CIVILIANRIOT;
if (roll <= 5) return AtBScenario.CONVOYRESCUE;
return AtBScenario.PIRATEFREEFORALL;
} else if (missionType == MT_PIRATEHUNTING) {
if (roll <= 1) return AtBScenario.ALLYRESCUE;
if (roll <= 3) return AtBScenario.CONVOYRESCUE;
if (roll <= 4) return AtBScenario.CONVOYATTACK;
return AtBScenario.PIRATEFREEFORALL;
} else {
if (roll <= 2) return AtBScenario.ALLYRESCUE;
if (roll <= 3) return AtBScenario.CIVILIANRIOT;
if (roll <= 4) return AtBScenario.CONVOYRESCUE;
if (roll <= 5) return AtBScenario.CONVOYATTACK;
return AtBScenario.PIRATEFREEFORALL;
}
}
public boolean contractExtended (Campaign campaign) {
if (getMissionType() != MT_PIRATEHUNTING &&
getMissionType() != MT_RIOTDUTY) {
String warName = RandomFactionGenerator.getInstance().getCurrentWar(getEmployerCode(),
getEnemyCode(), campaign.getDate());
if (null != warName) {
int extension = 0;
int roll = Compute.d6();
if (roll == 1) {
extension = Math.max(1, getLength() / 2);
}
if (roll == 2) {
extension = 1;
}
if (extension > 0) {
campaign.addReport("Due to the " + warName +
" crisis your employer has invoked the emergency clause and extended the contract " +
extension + ((extension == 1)?" month":" months"));
GregorianCalendar newEndDate = new GregorianCalendar();
newEndDate.setTime(getEndingDate());
newEndDate.add(Calendar.MONTH, extension);
getEndingDate().setTime(newEndDate.getTimeInMillis());
extensionLength += extension;
return true;
}
}
}
return false;
}
@Override
public long getMonthlyPayOut() {
if (extensionLength == 0) {
return super.getMonthlyPayOut();
}
/* The tranport clause and the advance monies have already been
* accounted for over the original length of the contract. The extension
* uses the base monthly amounts for support and overhead, with a
* 50% bonus to the base amount.
*/
return (long)((getBaseAmount() * 1.5 + getSupportAmount()
+ getOverheadAmount()) / getLength());
}
public void checkForFollowup(Campaign campaign) {
if ((getMissionType() == AtBContract.MT_DIVERSIONARYRAID ||
getMissionType() == AtBContract.MT_RECONRAID ||
getMissionType() == AtBContract.MT_RIOTDUTY)) {
int roll = Compute.d6();
if (roll == 6) {
campaign.getContractMarket().addFollowup(campaign, this);
campaign.addReport("Your employer has offered a follow-up contract (available on the <a href=\"CONTRACT_MARKET\">contract market</a>).");
}
}
}
protected void writeToXmlBegin(PrintWriter pw1, int indent) {
super.writeToXmlBegin(pw1, indent);
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<employerCode>"
+employerCode
+"</employerCode>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<enemyCode>"
+enemyCode
+"</enemyCode>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<missionType>"
+missionType
+"</missionType>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<allySkill>"
+allySkill
+"</allySkill>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<allyQuality>"
+allyQuality
+"</allyQuality>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<enemySkill>"
+enemySkill
+"</enemySkill>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<enemyQuality>"
+enemyQuality
+"</enemyQuality>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<allyBotName>"
+allyBotName
+"</allyBotName>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<enemyBotName>"
+enemyBotName
+"</enemyBotName>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<allyCamoCategory>"
+allyCamoCategory
+"</allyCamoCategory>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<allyCamoFileName>"
+allyCamoFileName
+"</allyCamoFileName>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<allyColorIndex>"
+allyColorIndex
+"</allyColorIndex>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<enemyCamoCategory>"
+enemyCamoCategory
+"</enemyCamoCategory>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<enemyCamoFileName>"
+enemyCamoFileName
+"</enemyCamoFileName>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<enemyColorIndex>"
+enemyColorIndex
+"</enemyColorIndex>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<requiredLances>"
+requiredLances
+"</requiredLances>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<moraleLevel>"
+moraleLevel
+"</moraleLevel>");
if (null != routEnd) {
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<routEnd>"
+ new SimpleDateFormat("yyyy-MM-dd").format(routEnd)
+"</routEnd>");
}
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<numBonusParts>"
+numBonusParts
+"</numBonusParts>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<partsAvailabilityLevel>"
+partsAvailabilityLevel
+"</partsAvailabilityLevel>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<extensionLength>"
+extensionLength
+"</extensionLength>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<sharesPct>"
+sharesPct
+"</sharesPct>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<playerMinorBreaches>"
+playerMinorBreaches
+"</playerMinorBreaches>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<employerMinorBreaches>"
+employerMinorBreaches
+"</employerMinorBreaches>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<priorLogisticsFailure>"
+priorLogisticsFailure
+"</priorLogisticsFailure>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<battleTypeMod>"
+battleTypeMod
+"</battleTypeMod>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<nextWeekBattleTypeMod>"
+nextWeekBattleTypeMod
+"</nextWeekBattleTypeMod>");
if (null != specialEventScenarioDate) {
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<specialEventScenarioDate>"
+ new SimpleDateFormat("yyyy-MM-dd").format(specialEventScenarioDate)
+"</specialEventScenarioDate>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<specialEventScenarioType>"
+ specialEventScenarioType
+"</specialEventScenarioType>");
}
}
public void loadFieldsFromXmlNode(Node wn) throws ParseException {
super.loadFieldsFromXmlNode(wn);
NodeList nl = wn.getChildNodes();
for (int x=0; x<nl.getLength(); x++) {
Node wn2 = nl.item(x);
if (wn2.getNodeName().equalsIgnoreCase("employerCode")) {
employerCode = wn2.getTextContent();
} else if (wn2.getNodeName().equalsIgnoreCase("enemyCode")) {
enemyCode = wn2.getTextContent();
} else if (wn2.getNodeName().equalsIgnoreCase("missionType")) {
missionType = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("allySkill")) {
allySkill = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("allyQuality")) {
allyQuality = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("enemySkill")) {
enemySkill = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("enemyQuality")) {
enemyQuality = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("allyBotName")) {
allyBotName = wn2.getTextContent();
} else if (wn2.getNodeName().equalsIgnoreCase("enemyBotName")) {
enemyBotName = wn2.getTextContent();
} else if (wn2.getNodeName().equalsIgnoreCase("allyCamoCategory")) {
allyCamoCategory = wn2.getTextContent();
} else if (wn2.getNodeName().equalsIgnoreCase("allyCamoFileName")) {
allyCamoFileName = wn2.getTextContent();
} else if (wn2.getNodeName().equalsIgnoreCase("allyColorIndex")) {
allyColorIndex = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("enemyCamoCategory")) {
enemyCamoCategory = wn2.getTextContent();
} else if (wn2.getNodeName().equalsIgnoreCase("enemyCamoFileName")) {
enemyCamoFileName = wn2.getTextContent();
} else if (wn2.getNodeName().equalsIgnoreCase("enemyColorIndex")) {
enemyColorIndex = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("requiredLances")) {
requiredLances = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("moraleLevel")) {
moraleLevel = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("routEnd")) {
routEnd = new SimpleDateFormat("yyyy-MM-dd").parse(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("partsAvailabilityLevel")) {
partsAvailabilityLevel = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("extensionLength")) {
extensionLength = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("sharesPct")) {
sharesPct = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("numBonusParts")) {
numBonusParts = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("playerMinorBreaches")) {
playerMinorBreaches = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("employerMinorBreaches")) {
employerMinorBreaches = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("priorLogisticsFailure")) {
priorLogisticsFailure = Boolean.parseBoolean(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("battleTypeMod")) {
battleTypeMod = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("nextWeekBattleTypeMod")) {
nextWeekBattleTypeMod = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("specialEventScenarioDate")) {
specialEventScenarioDate = new SimpleDateFormat("yyyy-MM-dd").parse(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("specialEventScenarioType")) {
specialEventScenarioType = Integer.parseInt(wn2.getTextContent());
}
}
}
public String getEmployerCode() {
return employerCode;
}
public void setEmployerCode(String code, int era) {
employerCode = code;
setEmployer(getEmployerName(era));
}
public String getEmployerName(int era) {
if (mercSubcontract) {
return "Mercenary (" +
Faction.getFaction(employerCode).getFullName(era) + ")";
}
return Faction.getFaction(employerCode).getFullName(era);
}
public String getEnemyCode() {
return enemyCode;
}
public String getEnemyName(int era) {
return Faction.getFaction(enemyCode).getFullName(era);
}
public void setEnemyCode(String enemyCode) {
this.enemyCode = enemyCode;
}
public int getMissionType() {
return missionType;
}
public void setMissionType(int missionType) {
this.missionType = missionType;
setType(missionTypeNames[missionType]);
}
public String getMissionTypeName() {
return missionTypeNames[missionType];
}
public int getAllySkill() {
return allySkill;
}
public void setAllySkill(int allySkill) {
this.allySkill = allySkill;
}
public int getEnemySkill() {
return enemySkill;
}
public void setEnemySkill(int enemySkill) {
this.enemySkill = enemySkill;
}
public int getAllyQuality() {
return allyQuality;
}
public void setAllyQuality(int allyQuality) {
this.allyQuality = allyQuality;
}
public int getEnemyQuality() {
return enemyQuality;
}
public void setEnemyQuality(int enemyQuality) {
this.enemyQuality = enemyQuality;
}
public String getAllyBotName() {
return allyBotName;
}
public void setAllyBotName(String name) {
allyBotName = name;
}
public String getEnemyBotName() {
return enemyBotName;
}
public void setEnemyBotName(String name) {
enemyBotName = name;
}
public String getAllyCamoCategory() {
return allyCamoCategory;
}
public void setAllyCamoCategory(String category) {
allyCamoCategory = category;
}
public String getAllyCamoFileName() {
return allyCamoFileName;
}
public void setAllyCamoFileName(String fileName) {
allyCamoFileName = fileName;
}
public int getAllyColorIndex() {
return allyColorIndex;
}
public void setAllyColorIndex(int index) {
allyColorIndex = index;
}
public String getEnemyCamoCategory() {
return enemyCamoCategory;
}
public void setEnemyCamoCategory(String category) {
enemyCamoCategory = category;
}
public String getEnemyCamoFileName() {
return enemyCamoFileName;
}
public void setEnemyCamoFileName(String fileName) {
enemyCamoFileName = fileName;
}
public int getEnemyColorIndex() {
return enemyColorIndex;
}
public void setEnemyColorIndex(int index) {
enemyColorIndex = index;
}
public int getRequiredLances() {
return requiredLances;
}
public void setRequiredLances(int required) {
requiredLances = required;
}
public int getPartsAvailabilityLevel() {
return partsAvailabilityLevel;
}
public void adjustPartsAvailabilityLevel(int mod) {
partsAvailabilityLevel += mod;
}
public int getMoraleLevel() {
return moraleLevel;
}
public void setMoraleLevel(int level) {
moraleLevel = level;
}
public String getMoraleLevelName() {
return moraleLevelNames[moraleLevel];
}
public int getSharesPct() {
return sharesPct;
}
public void setSharesPct(int pct) {
sharesPct = pct;
}
public void addPlayerMinorBreach() {
playerMinorBreaches++;
}
public void addPlayerMinorBreaches(int num) {
playerMinorBreaches += num;
}
public void addEmployerMinorBreach() {
employerMinorBreaches++;
}
public void addEmployerMinorBreaches(int num) {
employerMinorBreaches += num;
}
public int getNumBonusParts() {
return numBonusParts;
}
public void addBonusParts(int num) {
numBonusParts += num;
}
public void useBonusPart() {
numBonusParts--;
}
public int getBattleTypeMod() {
return battleTypeMod + nextWeekBattleTypeMod;
}
public AtBContract(Contract c, Campaign campaign) {
this(c.getName());
setType(c.getType());
setPlanetName(c.getPlanetName());
setDesc(c.getDescription());
setStatus(c.getStatus());
for (Scenario s : c.getScenarios()) {
addScenario(s);
}
setId(c.getId());
setLength(c.getLength());
setStartDate(c.getStartDate());
/*Set ending date; the other calculated values will be replaced
* from the original contract */
calculateContract(campaign);
setMultiplier(c.getMultiplier());
setTransportComp(c.getTransportComp());
setStraightSupport(c.getStraightSupport());
setOverheadComp(c.getOverheadComp());
setCommandRights(c.getCommandRights());
setBattleLossComp(c.getBattleLossComp());
setSalvagePct(c.getSalvagePct());
setSalvageExchange(c.isSalvageExchange());
setSalvagedByUnit(c.getSalvagedByUnit());
setSalvagedByEmployer(c.getSalvagedByEmployer());
setSigningBonusPct(c.getSigningBonusPct());
setAdvancePct(c.getAdvancePct());
setMRBCFee(c.payMRBCFee());
setAdvanceAmount(c.getAdvanceAmount());
setFeeAmount(c.getFeeAmount());
setBaseAmount(c.getBaseAmount());
setOverheadAmount(c.getOverheadAmount());
setSupportAmount(c.getSupportAmount());
setTransportAmount(c.getTransportAmount());
setSigningBonusAmount(c.getSigningBonusAmount());
/* Guess at AtBContract values */
missionType = -1;
for (int i = 0; i < MT_NUM; i++) {
if (c.getType().equalsIgnoreCase(missionTypeNames[i])) {
missionType = i;
break;
}
}
/* Make a rough guess */
if (missionType < 0) {
if (c.getLength() <= 3) {
missionType = MT_OBJECTIVERAID;
} else if (c.getLength() >= 12) {
missionType = MT_GARRISONDUTY;
} else {
missionType = MT_PLANETARYASSAULT;
}
}
Faction f = Faction.getFactionFromFullNameAndEra(c.getEmployer(), campaign.getEra());
if (null == f) {
employerCode = "IND";
} else {
employerCode = f.getShortName();
}
if (missionType == MT_PIRATEHUNTING) {
enemyCode = "PIR";
}
if (missionType == MT_RIOTDUTY) {
enemyCode = "REB";
}
requiredLances = Math.max(getEffectiveNumUnits(campaign) / 6, 1);
calculatePartsAvailabilityLevel(campaign);
allyBotName = getEmployerName(campaign.getEra());
enemyBotName = getEnemyName(campaign.getEra());
}
public static AtBContract getContractExtension(AtBContract c, int length, Campaign campaign) {
AtBContract retVal = new AtBContract(c.getName() + " (Ext)");
retVal.setType(c.getType());
retVal.setPlanetName(c.getPlanetName());
retVal.setDesc(c.getDescription());
retVal.setStatus(Mission.S_ACTIVE);
retVal.setLength(length);
retVal.setStartDate(campaign.getDate());
/*Set ending date; the other calculated values will be replaced
* from the original contract */
retVal.calculateContract(campaign);
retVal.setMultiplier(c.getMultiplier() * 1.5);
retVal.setTransportComp(c.getTransportComp());
retVal.setStraightSupport(c.getStraightSupport());
retVal.setOverheadComp(c.getOverheadComp());
retVal.setCommandRights(c.getCommandRights());
retVal.setBattleLossComp(c.getBattleLossComp());
retVal.setSalvagePct(c.getSalvagePct());
retVal.setSalvageExchange(c.isSalvageExchange());
retVal.setSalvagedByUnit(c.getSalvagedByUnit());
retVal.setSalvagedByEmployer(c.getSalvagedByEmployer());
retVal.setSigningBonusPct(c.getSigningBonusPct());
retVal.setAdvancePct(c.getAdvancePct());
retVal.setMRBCFee(c.payMRBCFee());
retVal.setMissionType(c.getMissionType());
retVal.setEmployerCode(c.getEmployerCode(), campaign.getEra());
retVal.setEnemyCode(c.getEnemyCode());
retVal.requiredLances = c.getRequiredLances();
retVal.calculatePartsAvailabilityLevel(campaign);
retVal.setAllyBotName(c.getAllyBotName());
retVal.setEnemyBotName(c.getEnemyBotName());
return retVal;
}
}