• We have updated our Community Code of Conduct. Please read through the new rules for the forum that are an integral part of Paradox Interactive’s User Agreement.

anonynamja

Second Lieutenant
Oct 31, 2016
100
0
Looking for some feedback on my salvage mod, Proportional Mech Salvage.

The aim is to make the amount of salvaged mech parts proportional to the extent of damage done. Also, to make mech salvage symmetrical between player and nonplayer mechs.

For reference, the vanilla behavior is that player mechs are only destroyed IF you make it possible AND you fail the roll AND your mech is CT'd, and if destroyed you get 0 salvaged parts. For enemies, you get 1 part if the mech is CT'd, 2 if legged, and 3 if headshot OR pilot incapacitated, in order of precedence. That is, you can get 3 parts even if you've blown off a leg and both side torsos and then get a lucky headshot, but if you snipe through the CT alone you just get one part.

My proposed changes:

- Player mechs are destroyed IF you make it possible AND you fail the roll AND your mech is CT'd/legged/headshot. (pilot incap doesn't count)
- You salvage 3 parts if you destroyed 1 or fewer sections, 2 parts if you destroyed 2-3 sections, 1 part if you destroyed 4-5 sections, and 0 parts if you destroyed 6-8 sections.

This is intended to be played with default mech part settings (3 parts make a mech) and default contract salvage (2 base priority), since doing otherwise would require rebalancing all the other areas of gameplay, which is beyond the scope of this mod. Also intended to be played with no free loadout.

The relevant code change to BattleTech.Contract.GenerateSalvage:
for (int i = 0; i < lostUnits.Count; i++)
{
MechDef mech = lostUnits[ i].mech;
float num = simulation.NetworkRandom.Float(0f, 1f);
bool flag = mech.IsDestroyed;
Contract.logger.LogWarning(string.Format("Player Unit {0}: {1} was destroyed in combat? {2}. If true, attempting to recover.", i, mech.Description.Name, flag));
Contract.logger.LogWarning(string.Format("Rolled a recovery roll of {0}, attempting to roll below {1}", num, constants.Salvage.DestroyedMechRecoveryChance));
if (!flag || num <= constants.Salvage.DestroyedMechRecoveryChance)
{
Contract.logger.LogWarning("Recovery Succeeded");
lostUnits[ i].mechLost = false;
}
else
{
Contract.logger.LogWarning("Recovery Failed, Unit Lost");
lostUnits[ i].mechLost = true;
if ((mech.IsLocationDestroyed(ChassisLocations.Head) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.CenterTorso) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.LeftTorso) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.RightTorso) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.LeftArm) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.RightArm) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.LeftLeg) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.RightLeg) ? 1 : 0) <= 1)
{
Contract.logger.LogWarning("3 parts salvaged");
this.SalvageResults.Add(this.CreateMechPart(constants, mech));
this.SalvageResults.Add(this.CreateMechPart(constants, mech));
this.SalvageResults.Add(this.CreateMechPart(constants, mech));
}
else if ((mech.IsLocationDestroyed(ChassisLocations.Head) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.CenterTorso) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.LeftTorso) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.RightTorso) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.LeftArm) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.RightArm) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.LeftLeg) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.RightLeg) ? 1 : 0) <= 3)
{
Contract.logger.LogWarning("2 parts salvaged");
this.SalvageResults.Add(this.CreateMechPart(constants, mech));
this.SalvageResults.Add(this.CreateMechPart(constants, mech));
}
else if ((mech.IsLocationDestroyed(ChassisLocations.Head) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.CenterTorso) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.LeftTorso) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.RightTorso) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.LeftArm) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.RightArm) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.LeftLeg) ? 1 : 0) + (mech.IsLocationDestroyed(ChassisLocations.RightLeg) ? 1 : 0) <= 5)
{
Contract.logger.LogWarning("1 part salvaged");
this.SalvageResults.Add(this.CreateMechPart(constants, mech));
}
foreach (MechComponentRef mechComponentRef in mech.Inventory)
{
if (!mech.IsLocationDestroyed(mechComponentRef.MountedLocation) && mechComponentRef.DamageLevel != ComponentDamageLevel.Destroyed)
{
this.AddToFinalSalvage(new SalvageDef
{
MechComponentDef = mechComponentRef.Def,
Description = new DescriptionDef(mechComponentRef.Def.Description),
RewardID = this.GenerateRewardUID(),
Type = SalvageDef.SalvageType.COMPONENT,
ComponentType = mechComponentRef.Def.ComponentType,
Damaged = false,
Count = 1
});
}
}
}
}
int j = 0;
while (j < enemyMechs.Count)
{
MechDef mech2 = enemyMechs[j].mech;
Pilot pilot = enemyMechs[j].pilot;
SalvageDef salvageDef = null;
bool flag2 = false;
bool flag3 = false;
if ((mech2.IsLocationDestroyed(ChassisLocations.Head) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.CenterTorso) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.LeftTorso) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.RightTorso) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.LeftArm) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.RightArm) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.LeftLeg) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.RightLeg) ? 1 : 0) <= 1)
{
this.CreateAndAddMechPart(constants, mech2, 3, this.finalPotentialSalvage);
goto IL_623;
}
if ((mech2.IsLocationDestroyed(ChassisLocations.Head) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.CenterTorso) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.LeftTorso) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.RightTorso) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.LeftArm) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.RightArm) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.LeftLeg) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.RightLeg) ? 1 : 0) <= 3)
{
this.CreateAndAddMechPart(constants, mech2, 2, this.finalPotentialSalvage);
goto IL_623;
}
if ((mech2.IsLocationDestroyed(ChassisLocations.Head) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.CenterTorso) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.LeftTorso) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.RightTorso) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.LeftArm) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.RightArm) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.LeftLeg) ? 1 : 0) + (mech2.IsLocationDestroyed(ChassisLocations.RightLeg) ? 1 : 0) <= 5)
{
this.CreateAndAddMechPart(constants, mech2, 1, this.finalPotentialSalvage);
goto IL_623;
}
(paradox forum doesn't support formatting?)

Would you play with these changes? Do they make sense? Any feedback is welcome and appreciated.
 
Last edited:
They sound interesting to me - I may give it a try in the next campaign I start.
 
My ideal mech salvage mod is probably not achievable with the way the game is currently set up. Probably best way to do it now is make it 6 pieces of salvage, -1 for each non head part destroyed -4 for a destroyed core. When mech salvage is put into your repair bay all parts are destroyed and must be repaired to be used. Mechs cannot be stored until they are repaired. All mechs sell for full price on the open market. or Maybe 1/2 price. Would have to test prices probably.
 
Feel free to make specific suggestions.

Imo if you core an enemy mech it should always be 0 salvage, I don't care about anything but this:

CT blows up = 0 parts... ALWAYS

Players that go for easy CT focus should not be rewarded with a part. Surgical removal of mech parts should yield salvage.
 
Imo if you core an enemy mech it should always be 0 salvage, I don't care about anything but this:

CT blows up = 0 parts... ALWAYS

Players that go for easy CT focus should not be rewarded with a part. Surgical removal of mech parts should yield salvage.

Thanks for your input. That's an easy change to make. However, my concern is that it would i) incentivize legging strategies too much and further exacerbate the OP knockdown - calledshot issue and ii) fail to distinguish between coring w/ 7 intact limbs vs. coring w/ 3 intact limbs. I'd like to hear people's thoughts not just about lore but also about balance and non-degenerate gameplay. Keep in mind that my proposal is not just about enemy mechs, its about symmetry with player mechs as well, with mech permadeath implied. Reducing the flow of part salvage compared to HBS vanilla is probably reasonable, but the capacity of the player to sustain and come back from inevitable losses, that needs consideration.
 
Last edited:
Thanks for your input. That's an easy change to make. However, my concern is that it would i) incentivize legging strategies too much and further exacerbate the OP knockdown - calledshot issue and ii) fail to distinguish between coring w/ 7 intact limbs vs. coring w/ 3 intact limbs. I'd like to hear people's thoughts not just about lore but also about balance and non-degenerate gameplay. Keep in mind that my proposal is not just about enemy mechs, its about symmetry with player mechs as well, with mech permadeath implied. Reducing the flow of part salvage compared to HBS vanilla is probably reasonable, but the capacity of the player to sustain and come back from inevitable losses, that needs consideration.

You can fix the legging issue by making it less likely to hit legs, only the most skilled Pilots could make called leg shots etc. (maybe from the Tactician skill-tree) basically, if you want full salvage, you should be rewarded by surgically removing mech parts not just CT and in terms of legging it should be very hard for an unskilled pilot to do it. I think currently frontal called shot on a leg is 14 or 15%? Reducing that to 9 or 10% would make legging very hard, if your pilot has called shot bonus it could climb back to 15% for example.

Imo the RT, CT and LT should get attacked 80% of the time since a Pilot is aiming at the center mass of the mech which is the CT. Arms and Legs should be around 5-10%. In order to remove arms and legs the player that FLANKS should be more likely to do it, but not as guaranteed as it is currently in-game. I think a side called shot is 48%!!! to hit the leg, way too much it should be 24%.