Unstable 1.2.4.0

This commit is contained in:
Markus Isberg
2023-11-30 13:53:00 +02:00
parent 8a2e2ea0ae
commit fb5ea537bf
210 changed files with 4201 additions and 1283 deletions
@@ -104,7 +104,7 @@ namespace Barotrauma.Items.Components
// doesn't quite work properly, remaining time changes if tinkering stops
float deconstructionSpeedModifier = userDeconstructorSpeedMultiplier * (1f + tinkeringStrength * TinkeringSpeedIncrease);
float deconstructionSpeed = item.StatManager.GetAdjustedValue(ItemTalentStats.DeconstructorSpeed, DeconstructionSpeed);
float deconstructionSpeed = item.StatManager.GetAdjustedValueMultiplicative(ItemTalentStats.DeconstructorSpeed, DeconstructionSpeed);
if (DeconstructItemsSimultaneously)
{
@@ -149,13 +149,13 @@ namespace Barotrauma.Items.Components
{
forceMultiplier *= MathHelper.Lerp(0.5f, 2.0f, (float)Math.Sqrt(User.GetSkillLevel("helm") / 100));
}
currForce *= item.StatManager.GetAdjustedValue(ItemTalentStats.EngineMaxSpeed, MaxForce) * forceMultiplier;
currForce *= item.StatManager.GetAdjustedValueMultiplicative(ItemTalentStats.EngineMaxSpeed, MaxForce) * forceMultiplier;
if (item.GetComponent<Repairable>() is { IsTinkering: true } repairable)
{
currForce *= 1f + repairable.TinkeringStrength * TinkeringForceIncrease;
}
currForce = item.StatManager.GetAdjustedValue(ItemTalentStats.EngineSpeed, currForce);
currForce = item.StatManager.GetAdjustedValueMultiplicative(ItemTalentStats.EngineSpeed, currForce);
//less effective when in a bad condition
currForce *= MathHelper.Lerp(0.5f, 2.0f, condition);
@@ -469,7 +469,7 @@ namespace Barotrauma.Items.Components
character.CheckTalents(AbilityEffectType.OnAllyItemFabricatedAmount, fabricationitemAmount);
}
user.CheckTalents(AbilityEffectType.OnItemFabricatedAmount, fabricationitemAmount);
quality = GetFabricatedItemQuality(fabricatedItem, user);
quality = GetFabricatedItemQuality(fabricatedItem, user).RollQuality();
}
int amount = (int)fabricationitemAmount.Value;
@@ -534,12 +534,10 @@ namespace Barotrauma.Items.Components
{
foreach (Skill skill in fabricatedItem.RequiredSkills)
{
float userSkill = user.GetSkillLevel(skill.Identifier);
float addedSkill = skill.Level * SkillSettings.Current.SkillIncreasePerFabricatorRequiredSkill / Math.Max(userSkill, 1.0f);
float addedSkill = skill.Level * SkillSettings.Current.SkillIncreasePerFabricatorRequiredSkill;
var addedSkillValue = new AbilityFabricatorSkillGain(skill.Identifier, addedSkill);
user.CheckTalents(AbilityEffectType.OnItemFabricationSkillGain, addedSkillValue);
user.Info.IncreaseSkillLevel(
user.Info.ApplySkillGain(
skill.Identifier,
addedSkillValue.Value);
}
@@ -576,10 +574,52 @@ namespace Barotrauma.Items.Components
return currPowerConsumption;
}
private static int GetFabricatedItemQuality(FabricationRecipe fabricatedItem, Character user)
public static float CalculateBonusRollPercentage(float skillLevel, float target)
=> Math.Clamp((skillLevel - target) / (100f - target) * 100f, min: 0, max: 100);
public readonly record struct QualityResult(int Quality, float PlusOnePercentage, float PlusTwoPercentage)
{
if (user?.Info == null) { return 0; }
if (fabricatedItem.TargetItem.ConfigElement.GetChildElement("Quality") == null) { return 0; }
public static readonly QualityResult Empty = new QualityResult(0, 0, 0);
public bool HasRandomQualityRollChance => PlusOnePercentage > 0f || PlusTwoPercentage > 0f;
// The total real world percentage for a roll to succeed, taking into account that +1 needs to succeed for +2 to be attempted and
// that the chance for only +1 goes down as +2 increases since some of the +1's will turn into +2s
public float TotalPlusOnePercentage => Math.Clamp(PlusOnePercentage * (100f - PlusTwoPercentage) / 100f, min: 0, max: 100);
public float TotalPlusTwoPercentage => Math.Clamp(PlusOnePercentage * PlusTwoPercentage / 100f, min: 0, max: 100);
public int RollQuality()
{
int additionalQuality = 0;
if (Roll(PlusOnePercentage))
{
additionalQuality++;
if (Roll(PlusTwoPercentage))
{
additionalQuality++;
}
}
return Quality + additionalQuality;
static bool Roll(float percentage)
=> percentage >= Rand.Range(0, 100, Rand.RandSync.Unsynced);
}
}
public const int PlusOneQualityBonusThreshold = 50,
PlusTwoQualityBonusThreshold = 75;
public const int PlusOneTarget = 100,
PlusTwoTarget = 125;
public const float PlusOneLerp = 0.2f,
PlusTwoLerp = 0.4f;
private static QualityResult GetFabricatedItemQuality(FabricationRecipe fabricatedItem, Character user)
{
if (user?.Info == null) { return QualityResult.Empty; }
if (fabricatedItem.TargetItem.ConfigElement.GetChildElement("Quality") == null) { return QualityResult.Empty; }
int quality = 0;
float floatQuality = 0.0f;
floatQuality += user.GetStatValue(StatTypes.IncreaseFabricationQuality, includeSaved: false);
@@ -593,34 +633,63 @@ namespace Barotrauma.Items.Components
}
quality = (int)floatQuality;
const int MaxCraftingSkill = 100;
// Use Option here instead of 0 because we want the lowest value and a value of 0 would always be lower than any other chance
Option<float> plusOne = Option.None,
plusTwo = Option.None;
//having a higher-than-100 skill (e.g. due to talents) gives +1 quality
quality += fabricatedItem.RequiredSkills.All(s => user.GetSkillLevel(s.Identifier) >= MaxCraftingSkill) ? 1 : 0;
foreach (var skill in fabricatedItem.RequiredSkills)
{
//+1 quality if the character's skill level is >20% from the min requirement towards max skill
//e.g. if the skill requirement is 10 -> 28
//40 -> 52
//90 -> 92
float skillRequirement = MathHelper.Lerp(skill.Level, MaxCraftingSkill, 0.2f);
if (user.GetSkillLevel(skill.Identifier) > skillRequirement)
float skillLevel = user.GetSkillLevel(skill.Identifier);
if (skillLevel >= PlusOneQualityBonusThreshold)
{
quality += 1;
//+1 quality chance if the character's skill level is >20% from the min requirement towards max skill as well as higher than 50
//e.g. if the skill requirement is 10 -> 28 (but minimum 50 threshold)
//40 -> 52
//90 -> 92
var bonusChance1 = CalculateBonusRollPercentage(skillLevel, MathHelper.Lerp(skill.Level, PlusOneTarget, PlusOneLerp));
plusOne = OverrideChanceIfLess(plusOne, bonusChance1);
if (skillLevel >= PlusTwoQualityBonusThreshold)
{
var bonusChance2 = CalculateBonusRollPercentage(skillLevel, MathHelper.Lerp(skill.Level, PlusTwoTarget, PlusTwoLerp));
plusTwo = OverrideChanceIfLess(plusTwo, bonusChance2);
}
else
{
break;
}
}
else
{
break;
}
static Option<float> OverrideChanceIfLess(Option<float> original, float bonusChance)
{
if (original.TryUnwrap(out var originalChance))
{
return originalChance > bonusChance ? Option.Some(bonusChance) : original;
}
return Option.Some(bonusChance);
}
}
return quality;
return new QualityResult(quality,
PlusOnePercentage: plusOne.Match(some: static f => f, none: static () => 0f),
PlusTwoPercentage: plusTwo.Match(some: static f => f, none: static () => 0f));
}
partial void UpdateRequiredTimeProjSpecific();
private static bool AnyOneHasRecipeForItem(Character user, ItemPrefab item)
{
return
return
(user != null && user.HasRecipeForItem(item.Identifier)) ||
GameSession.GetSessionCrewCharacters(CharacterType.Bot).Any(c => c.HasRecipeForItem(item.Identifier));
}
private bool CanBeFabricated(FabricationRecipe fabricableItem, IReadOnlyDictionary<Identifier, List<Item>> availableIngredients, Character character)
{
if (fabricableItem == null) { return false; }
@@ -698,7 +767,7 @@ namespace Barotrauma.Items.Components
//fabricating takes 100 times longer if degree of success is close to 0
//characters with a higher skill than required can fabricate up to 100% faster
float time = fabricableItem.RequiredTime / item.StatManager.GetAdjustedValue(ItemTalentStats.FabricationSpeed, FabricationSpeed) / MathHelper.Clamp(t, 0.01f, 2.0f);
float time = fabricableItem.RequiredTime / item.StatManager.GetAdjustedValueMultiplicative(ItemTalentStats.FabricationSpeed, FabricationSpeed) / MathHelper.Clamp(t, 0.01f, 2.0f);
if (user?.Info is { } info && fabricableItem.TargetItem is { } it)
{
@@ -138,14 +138,14 @@ namespace Barotrauma.Items.Components
float powerFactor = Math.Min(currPowerConsumption <= 0.0f || MinVoltage <= 0.0f ? 1.0f : Voltage, MaxOverVoltageFactor);
currFlow = flowPercentage / 100.0f * item.StatManager.GetAdjustedValue(ItemTalentStats.PumpMaxFlow, MaxFlow) * powerFactor;
currFlow = flowPercentage / 100.0f * item.StatManager.GetAdjustedValueMultiplicative(ItemTalentStats.PumpMaxFlow, MaxFlow) * powerFactor;
if (item.GetComponent<Repairable>() is { IsTinkering: true } repairable)
{
currFlow *= 1f + repairable.TinkeringStrength * TinkeringSpeedIncrease;
}
currFlow = item.StatManager.GetAdjustedValue(ItemTalentStats.PumpSpeed, currFlow);
currFlow = item.StatManager.GetAdjustedValueMultiplicative(ItemTalentStats.PumpSpeed, currFlow);
//less effective when in a bad condition
currFlow *= MathHelper.Lerp(0.5f, 1.0f, item.Condition / item.MaxCondition);
@@ -875,7 +875,7 @@ namespace Barotrauma.Items.Components
}
}
private float GetMaxOutput() => item.StatManager.GetAdjustedValue(ItemTalentStats.ReactorMaxOutput, MaxPowerOutput);
private float GetFuelConsumption() => item.StatManager.GetAdjustedValue(ItemTalentStats.ReactorFuelConsumption, fuelConsumptionRate);
private float GetMaxOutput() => item.StatManager.GetAdjustedValueMultiplicative(ItemTalentStats.ReactorMaxOutput, MaxPowerOutput);
private float GetFuelConsumption() => item.StatManager.GetAdjustedValueMultiplicative(ItemTalentStats.ReactorFuelConsumption, fuelConsumptionRate);
}
}
@@ -336,8 +336,7 @@ namespace Barotrauma.Items.Components
{
showIceSpireWarning = false;
if (user != null && user.Info != null &&
user.SelectedItem == item &&
controlledSub != null && controlledSub.Velocity.LengthSquared() > 0.01f)
user.SelectedItem == item)
{
IncreaseSkillLevel(user, deltaTime);
}
@@ -402,14 +401,15 @@ namespace Barotrauma.Items.Components
private void IncreaseSkillLevel(Character user, float deltaTime)
{
if (controlledSub == null) { return; }
if (controlledSub.Velocity.LengthSquared() < 0.01f) { return; }
if (user?.Info == null) { return; }
// Do not increase the helm skill when "steering" the sub while docked into something static (e.g. outpost or wreck)
if (GameMain.GameSession?.Campaign != null && controlledSub != null && controlledSub.DockedTo.Any(d => d.PhysicsBody.BodyType == BodyType.Static)) { return; }
if (GameMain.GameSession?.Campaign != null&& controlledSub.DockedTo.Any(d => d.PhysicsBody.BodyType == BodyType.Static)) { return; }
float userSkill = Math.Max(user.GetSkillLevel("helm"), 1.0f) / 100.0f;
user.Info.IncreaseSkillLevel(
"helm".ToIdentifier(),
SkillSettings.Current.SkillIncreasePerSecondWhenSteering / userSkill * deltaTime);
float speedMultiplier = MathHelper.Clamp(TargetVelocity.Length() / 100.0f, 0.0f, 1.0f);
user.Info.ApplySkillGain(Tags.HelmSkill,
SkillSettings.Current.SkillIncreasePerSecondWhenSteering * speedMultiplier * deltaTime);
}
private void UpdateAutoPilot(float deltaTime)