Unstable v0.19.1.0
This commit is contained in:
@@ -203,7 +203,7 @@ namespace Barotrauma.Items.Components
|
||||
foreach ((Character character, Node node) in charactersInRange)
|
||||
{
|
||||
if (character == null || character.Removed) { continue; }
|
||||
character.ApplyAttack(null, node.WorldPosition, attack, 1.0f);
|
||||
character.ApplyAttack(null, node.WorldPosition, attack, MathHelper.Clamp(Voltage, 1.0f, MaxOverVoltageFactor));
|
||||
}
|
||||
}
|
||||
DischargeProjSpecific();
|
||||
|
||||
@@ -295,12 +295,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (attachable)
|
||||
{
|
||||
DeattachFromWall();
|
||||
|
||||
if (body != null)
|
||||
{
|
||||
item.body = body;
|
||||
}
|
||||
DeattachFromWall();
|
||||
}
|
||||
|
||||
if (Pusher != null) { Pusher.Enabled = false; }
|
||||
@@ -619,6 +618,10 @@ namespace Barotrauma.Items.Components
|
||||
#if CLIENT
|
||||
item.DrawDepthOffset = SpriteDepthWhenDropped - item.SpriteDepth;
|
||||
#endif
|
||||
foreach (LightComponent light in item.GetComponents<LightComponent>())
|
||||
{
|
||||
light.CheckIfNeedsUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
public override void ParseMsg()
|
||||
|
||||
@@ -165,31 +165,32 @@ namespace Barotrauma.Items.Components
|
||||
pickTimer = 0.0f;
|
||||
while (pickTimer < requiredTime && Screen.Selected != GameMain.SubEditorScreen)
|
||||
{
|
||||
//cancel if the item is currently selected
|
||||
//attempting to pick does not select the item, so if it is selected at this point, another ItemComponent
|
||||
//must have been selected and we should not keep deattaching (happens when for example interacting with
|
||||
//an electrical component while holding both a screwdriver and a wrench).
|
||||
if (picker.IsAnySelectedItem(item)||
|
||||
picker.IsKeyDown(InputType.Aim) ||
|
||||
!picker.CanInteractWith(item) ||
|
||||
item.Removed || item.ParentInventory != null)
|
||||
if (!CoroutineManager.Paused)
|
||||
{
|
||||
StopPicking(picker);
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
//cancel if the item is currently selected
|
||||
//attempting to pick does not select the item, so if it is selected at this point, another ItemComponent
|
||||
//must have been selected and we should not keep deattaching (happens when for example interacting with
|
||||
//an electrical component while holding both a screwdriver and a wrench).
|
||||
if (picker.IsAnySelectedItem(item) ||
|
||||
picker.IsKeyDown(InputType.Aim) ||
|
||||
!picker.CanInteractWith(item) ||
|
||||
item.Removed || item.ParentInventory != null)
|
||||
{
|
||||
StopPicking(picker);
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
Character.Controlled?.UpdateHUDProgressBar(
|
||||
this,
|
||||
item.WorldPosition,
|
||||
pickTimer / requiredTime,
|
||||
GUIStyle.Red, GUIStyle.Green,
|
||||
!string.IsNullOrWhiteSpace(PickingMsg) ? PickingMsg : this is Door ? "progressbar.opening" : "progressbar.deattaching");
|
||||
Character.Controlled?.UpdateHUDProgressBar(
|
||||
this,
|
||||
item.WorldPosition,
|
||||
pickTimer / requiredTime,
|
||||
GUIStyle.Red, GUIStyle.Green,
|
||||
!string.IsNullOrWhiteSpace(PickingMsg) ? PickingMsg : this is Door ? "progressbar.opening" : "progressbar.deattaching");
|
||||
#endif
|
||||
|
||||
picker.AnimController.UpdateUseItem(!picker.IsClimbing, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f));
|
||||
pickTimer += CoroutineManager.DeltaTime;
|
||||
|
||||
picker.AnimController.UpdateUseItem(!picker.IsClimbing, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f));
|
||||
pickTimer += CoroutineManager.DeltaTime;
|
||||
}
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
|
||||
|
||||
progressTimer += deltaTime * Math.Min(powerConsumption <= 0.0f ? 1 : Voltage, 1.0f);
|
||||
progressTimer += deltaTime * Math.Min(powerConsumption <= 0.0f ? 1 : Voltage, MaxOverVoltageFactor);
|
||||
|
||||
float tinkeringStrength = 0f;
|
||||
if (repairable.IsTinkering)
|
||||
@@ -205,18 +205,18 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
foreach (DeconstructItem deconstructProduct in products)
|
||||
{
|
||||
CreateDeconstructProduct(deconstructProduct, inputItems, amountMultiplier);
|
||||
CreateDeconstructProduct(deconstructProduct, inputItems, (int)(amountMultiplier * deconstructProduct.Amount));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (DeconstructItem deconstructProduct in validDeconstructItems)
|
||||
{
|
||||
CreateDeconstructProduct(deconstructProduct, inputItems, amountMultiplier);
|
||||
CreateDeconstructProduct(deconstructProduct, inputItems, (int)(amountMultiplier * deconstructProduct.Amount));
|
||||
}
|
||||
}
|
||||
|
||||
void CreateDeconstructProduct(DeconstructItem deconstructProduct, IEnumerable<Item> inputItems, float amountMultiplier)
|
||||
void CreateDeconstructProduct(DeconstructItem deconstructProduct, IEnumerable<Item> inputItems, int amount)
|
||||
{
|
||||
float percentageHealth = targetItem.Condition / targetItem.MaxCondition;
|
||||
|
||||
@@ -284,7 +284,6 @@ namespace Barotrauma.Items.Components
|
||||
user.CheckTalents(AbilityEffectType.OnItemDeconstructedInventory, itemDeconstructedInventory);
|
||||
}
|
||||
|
||||
int amount = (int)amountMultiplier;
|
||||
for (int i = 0; i < amount; i++)
|
||||
{
|
||||
Entity.Spawner.AddItemToSpawnQueue(itemPrefab, outputContainer.Inventory, condition, onSpawned: (Item spawnedItem) =>
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace Barotrauma.Items.Components
|
||||
Force = MathHelper.Lerp(force, (Voltage < MinVoltage) ? 0.0f : targetForce, deltaTime * 10.0f);
|
||||
if (Math.Abs(Force) > 1.0f)
|
||||
{
|
||||
float voltageFactor = MinVoltage <= 0.0f ? 1.0f : Math.Min(Voltage, 1.0f);
|
||||
float voltageFactor = MinVoltage <= 0.0f ? 1.0f : Math.Min(Voltage, MaxOverVoltageFactor);
|
||||
float currForce = force * voltageFactor;
|
||||
float condition = item.Condition / item.MaxCondition;
|
||||
// Broken engine makes more noise.
|
||||
|
||||
@@ -305,7 +305,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
float fabricationSpeedIncrease = 1f + tinkeringStrength * TinkeringSpeedIncrease;
|
||||
|
||||
timeUntilReady -= deltaTime * fabricationSpeedIncrease * Math.Min(powerConsumption <= 0 ? 1 : Voltage, 1.0f);
|
||||
timeUntilReady -= deltaTime * fabricationSpeedIncrease * Math.Min(powerConsumption <= 0 ? 1 : Voltage, MaxOverVoltageFactor);
|
||||
|
||||
UpdateRequiredTimeProjSpecific();
|
||||
|
||||
@@ -371,8 +371,7 @@ namespace Barotrauma.Items.Components
|
||||
var availableItems = availableIngredients[requiredPrefab.Identifier];
|
||||
var availableItem = availableItems.FirstOrDefault(potentialPrefab =>
|
||||
{
|
||||
return potentialPrefab.ConditionPercentage >= requiredItem.MinCondition * 100.0f &&
|
||||
potentialPrefab.ConditionPercentage <= requiredItem.MaxCondition * 100.0f;
|
||||
return requiredItem.IsConditionSuitable(potentialPrefab.ConditionPercentage);
|
||||
});
|
||||
|
||||
if (availableItem == null) { continue; }
|
||||
@@ -616,8 +615,7 @@ namespace Barotrauma.Items.Components
|
||||
var availablePrefabs = availableIngredients[requiredPrefab.Identifier];
|
||||
foreach (Item availablePrefab in availablePrefabs)
|
||||
{
|
||||
if (availablePrefab.ConditionPercentage / 100.0f >= requiredItem.MinCondition &&
|
||||
availablePrefab.ConditionPercentage / 100.0f <= requiredItem.MaxCondition)
|
||||
if (requiredItem.IsConditionSuitable(availablePrefab.ConditionPercentage))
|
||||
{
|
||||
availablePrefabsAmount++;
|
||||
}
|
||||
@@ -732,9 +730,7 @@ namespace Barotrauma.Items.Components
|
||||
var availablePrefabs = availableIngredients[requiredPrefab.Identifier];
|
||||
var availablePrefab = availablePrefabs.FirstOrDefault(potentialPrefab =>
|
||||
{
|
||||
return !usedItems.Contains(potentialPrefab) &&
|
||||
potentialPrefab.ConditionPercentage >= requiredItem.MinCondition * 100.0f &&
|
||||
potentialPrefab.ConditionPercentage <= requiredItem.MaxCondition * 100.0f;
|
||||
return !usedItems.Contains(potentialPrefab) && requiredItem.IsConditionSuitable(potentialPrefab.ConditionPercentage);
|
||||
});
|
||||
if (availablePrefab == null) { continue; }
|
||||
|
||||
|
||||
+1
-2
@@ -2,7 +2,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -52,7 +51,7 @@ namespace Barotrauma.Items.Components
|
||||
return;
|
||||
}
|
||||
|
||||
CurrFlow = Math.Min(PowerConsumption > 0 ? Voltage : 1.0f, 1.0f) * generatedAmount * 100.0f;
|
||||
CurrFlow = Math.Min(PowerConsumption > 0 ? Voltage : 1.0f, MaxOverVoltageFactor) * generatedAmount * 100.0f;
|
||||
float conditionMult = item.Condition / item.MaxCondition;
|
||||
//100% condition = 100% oxygen
|
||||
//50% condition = 25% oxygen
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (item.CurrentHull == null) { return; }
|
||||
|
||||
float powerFactor = Math.Min(currPowerConsumption <= 0.0f || MinVoltage <= 0.0f ? 1.0f : Voltage, 1.0f);
|
||||
float powerFactor = Math.Min(currPowerConsumption <= 0.0f || MinVoltage <= 0.0f ? 1.0f : Voltage, MaxOverVoltageFactor);
|
||||
|
||||
currFlow = flowPercentage / 100.0f * maxFlow * powerFactor;
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
const float NetworkUpdateIntervalHigh = 0.5f;
|
||||
|
||||
const float TemperatureBoostAmount = 20;
|
||||
|
||||
//the rate at which the reactor is being run on (higher rate -> higher temperature)
|
||||
private float fissionRate;
|
||||
|
||||
@@ -46,6 +48,8 @@ namespace Barotrauma.Items.Components
|
||||
private Vector2 optimalFissionRate, allowedFissionRate;
|
||||
private Vector2 optimalTurbineOutput, allowedTurbineOutput;
|
||||
|
||||
private float temperatureBoost;
|
||||
|
||||
private bool _powerOn;
|
||||
|
||||
[Serialize(defaultValue: false, isSaveable: IsPropertySaveable.Yes)]
|
||||
@@ -241,6 +245,34 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
#endif
|
||||
|
||||
if (signalControlledTargetFissionRate.HasValue && Math.Abs(signalControlledTargetFissionRate.Value - TargetFissionRate) > 1.0f)
|
||||
{
|
||||
TargetFissionRate = adjustValueWithoutOverShooting(TargetFissionRate, signalControlledTargetFissionRate.Value, deltaTime * 5.0f);
|
||||
#if CLIENT
|
||||
FissionRateScrollBar.BarScroll = TargetFissionRate / 100.0f;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
signalControlledTargetFissionRate = null;
|
||||
}
|
||||
if (signalControlledTargetTurbineOutput.HasValue && Math.Abs(signalControlledTargetTurbineOutput.Value - TargetTurbineOutput) > 1.0f)
|
||||
{
|
||||
TargetTurbineOutput = adjustValueWithoutOverShooting(TargetTurbineOutput, signalControlledTargetTurbineOutput.Value, deltaTime * 5.0f);
|
||||
#if CLIENT
|
||||
TurbineOutputScrollBar.BarScroll = TargetTurbineOutput / 100.0f;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
signalControlledTargetTurbineOutput = null;
|
||||
}
|
||||
|
||||
static float adjustValueWithoutOverShooting(float current, float target, float speed)
|
||||
{
|
||||
return target < current ? Math.Max(target, current - speed) : Math.Min(target, current + speed);
|
||||
}
|
||||
|
||||
prevAvailableFuel = AvailableFuel;
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
|
||||
|
||||
@@ -270,7 +302,10 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
float temperatureDiff = (heatAmount - turbineOutput) - Temperature;
|
||||
Temperature += MathHelper.Clamp(Math.Sign(temperatureDiff) * 10.0f * deltaTime, -Math.Abs(temperatureDiff), Math.Abs(temperatureDiff));
|
||||
//if (item.InWater && AvailableFuel < 100.0f) Temperature -= 12.0f * deltaTime;
|
||||
temperatureBoost = adjustValueWithoutOverShooting(temperatureBoost, 0.0f, deltaTime);
|
||||
#if CLIENT
|
||||
temperatureBoostUpButton.Enabled = temperatureBoostDownButton.Enabled = Math.Abs(temperatureBoost) < TemperatureBoostAmount * 0.9f;
|
||||
#endif
|
||||
|
||||
FissionRate = MathHelper.Lerp(fissionRate, Math.Min(TargetFissionRate, AvailableFuel), deltaTime);
|
||||
|
||||
@@ -438,7 +473,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private float GetGeneratedHeat(float fissionRate)
|
||||
{
|
||||
return fissionRate * (prevAvailableFuel / 100.0f) * 2.0f;
|
||||
return fissionRate * (prevAvailableFuel / 100.0f) * 2.0f + temperatureBoost;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -486,13 +521,15 @@ namespace Barotrauma.Items.Components
|
||||
if (temperature > allowedTemperature.Y)
|
||||
{
|
||||
item.SendSignal("1", "meltdown_warning");
|
||||
//faster meltdown if the item is in a bad condition
|
||||
meltDownTimer += MathHelper.Lerp(deltaTime * 2.0f, deltaTime, item.Condition / item.MaxCondition);
|
||||
|
||||
if (meltDownTimer > MeltdownDelay)
|
||||
if (!item.InvulnerableToDamage)
|
||||
{
|
||||
MeltDown();
|
||||
return;
|
||||
//faster meltdown if the item is in a bad condition
|
||||
meltDownTimer += MathHelper.Lerp(deltaTime * 2.0f, deltaTime, item.Condition / item.MaxCondition);
|
||||
if (meltDownTimer > MeltdownDelay)
|
||||
{
|
||||
MeltDown();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -797,30 +834,31 @@ namespace Barotrauma.Items.Components
|
||||
AutoTemp = false;
|
||||
TargetFissionRate = 0.0f;
|
||||
TargetTurbineOutput = 0.0f;
|
||||
if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; }
|
||||
registerUnsentChanges();
|
||||
}
|
||||
break;
|
||||
case "set_fissionrate":
|
||||
if (PowerOn && float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newFissionRate))
|
||||
{
|
||||
TargetFissionRate = MathHelper.Clamp(newFissionRate, 0.0f, 100.0f);
|
||||
if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; }
|
||||
#if CLIENT
|
||||
FissionRateScrollBar.BarScroll = TargetFissionRate / 100.0f;
|
||||
#endif
|
||||
signalControlledTargetFissionRate = MathHelper.Clamp(newFissionRate, 0.0f, 100.0f);
|
||||
registerUnsentChanges();
|
||||
}
|
||||
break;
|
||||
case "set_turbineoutput":
|
||||
if (PowerOn && float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newTurbineOutput))
|
||||
{
|
||||
TargetTurbineOutput = MathHelper.Clamp(newTurbineOutput, 0.0f, 100.0f);
|
||||
if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; }
|
||||
#if CLIENT
|
||||
TurbineOutputScrollBar.BarScroll = TargetTurbineOutput / 100.0f;
|
||||
#endif
|
||||
signalControlledTargetTurbineOutput = MathHelper.Clamp(newTurbineOutput, 0.0f, 100.0f);
|
||||
registerUnsentChanges();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
void registerUnsentChanges()
|
||||
{
|
||||
if (GameMain.NetworkMember is { IsServer: true }) { unsentChanges = true; }
|
||||
}
|
||||
}
|
||||
|
||||
private float? signalControlledTargetFissionRate, signalControlledTargetTurbineOutput;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace Barotrauma.Items.Components
|
||||
set { maxRechargeSpeed = Math.Max(value, 1.0f); }
|
||||
}
|
||||
|
||||
[Editable, Serialize(10.0f, IsPropertySaveable.Yes, description: "The current recharge speed of the device.")]
|
||||
[Editable, Serialize(0.0f, IsPropertySaveable.Yes, description: "The current recharge speed of the device.")]
|
||||
public float RechargeSpeed
|
||||
{
|
||||
get { return rechargeSpeed; }
|
||||
|
||||
@@ -243,8 +243,13 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
//damage the item if voltage is too high (except if running as a client)
|
||||
float prevCondition = item.Condition;
|
||||
item.Condition -= deltaTime * 10.0f;
|
||||
|
||||
//some randomness to prevent all junction boxes from breaking at the same time
|
||||
if (Rand.Range(0.0f, 1.0f) < 0.01f)
|
||||
{
|
||||
//damaged boxes are more sensitive to overvoltage (also preventing all boxes from breaking at the same time)
|
||||
float conditionFactor = MathHelper.Lerp(5.0f, 1.0f, item.Condition / item.MaxCondition);
|
||||
item.Condition -= deltaTime * Rand.Range(10.0f, 500.0f) * conditionFactor;
|
||||
}
|
||||
if (item.Condition <= 0.0f && prevCondition > 0.0f)
|
||||
{
|
||||
overloadCooldownTimer = OverloadCooldown;
|
||||
|
||||
@@ -94,6 +94,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
protected Connection powerIn, powerOut;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum voltage factor when the device is being overvolted. I.e. how many times more effectively the device can function when it's being overvolted
|
||||
/// </summary>
|
||||
protected const float MaxOverVoltageFactor = 2.0f;
|
||||
|
||||
protected virtual PowerPriority Priority { get { return PowerPriority.Default; } }
|
||||
|
||||
[Editable, Serialize(0.5f, IsPropertySaveable.Yes, description: "The minimum voltage required for the device to function. " +
|
||||
|
||||
@@ -244,6 +244,13 @@ namespace Barotrauma.Items.Components
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No)]
|
||||
public bool DamageDoors
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool IsStuckToTarget => StickTarget != null;
|
||||
|
||||
private Category originalCollisionCategories;
|
||||
@@ -288,7 +295,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private void Launch(Character user, Vector2 simPosition, float rotation, float damageMultiplier = 1f)
|
||||
private void Launch(Character user, Vector2 simPosition, float rotation, float damageMultiplier = 1f, float launchImpulseModifier = 0f)
|
||||
{
|
||||
Item.body.ResetDynamics();
|
||||
Item.SetTransform(simPosition, rotation);
|
||||
@@ -299,7 +306,7 @@ namespace Barotrauma.Items.Components
|
||||
// Set user for hitscan projectiles to work properly.
|
||||
User = user;
|
||||
// Need to set null for non-characterusable items.
|
||||
Use(character: null);
|
||||
Use(character: null, launchImpulseModifier);
|
||||
// Set user for normal projectiles to work properly.
|
||||
User = user;
|
||||
if (Item.Removed) { return; }
|
||||
@@ -312,7 +319,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public void Shoot(Character user, Vector2 weaponPos, Vector2 spawnPos, float rotation, List<Body> ignoredBodies, bool createNetworkEvent, float damageMultiplier = 1f)
|
||||
public void Shoot(Character user, Vector2 weaponPos, Vector2 spawnPos, float rotation, List<Body> ignoredBodies, bool createNetworkEvent, float damageMultiplier = 1f, float launchImpulseModifier = 0f)
|
||||
{
|
||||
//add the limbs of the shooter to the list of bodies to be ignored
|
||||
//so that the player can't shoot himself
|
||||
@@ -320,7 +327,7 @@ namespace Barotrauma.Items.Components
|
||||
Vector2 projectilePos = weaponPos;
|
||||
//make sure there's no obstacles between the base of the weapon (or the shoulder of the character) and the end of the barrel
|
||||
if (Submarine.PickBody(weaponPos, spawnPos, IgnoredBodies, Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionItemBlocking,
|
||||
customPredicate: (Fixture f) => { return !IgnoredBodies.Contains(f.Body); }) == null)
|
||||
customPredicate: (Fixture f) => { return IgnoredBodies == null || !IgnoredBodies.Contains(f.Body); }) == null)
|
||||
{
|
||||
//no obstacles -> we can spawn the projectile at the barrel
|
||||
projectilePos = spawnPos;
|
||||
@@ -334,7 +341,7 @@ namespace Barotrauma.Items.Components
|
||||
projectilePos = newPos;
|
||||
}
|
||||
}
|
||||
Launch(user, projectilePos, rotation, damageMultiplier);
|
||||
Launch(user, projectilePos, rotation, damageMultiplier, launchImpulseModifier);
|
||||
if (createNetworkEvent && !Item.Removed && GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
#if SERVER
|
||||
@@ -344,7 +351,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public bool Use(Character character = null)
|
||||
public bool Use(Character character = null, float launchImpulseModifier = 0f)
|
||||
{
|
||||
if (character != null && !characterUsable) { return false; }
|
||||
|
||||
@@ -379,7 +386,7 @@ namespace Barotrauma.Items.Components
|
||||
else
|
||||
{
|
||||
item.body.SetTransform(item.body.SimPosition, launchAngle);
|
||||
float modifiedLaunchImpulse = LaunchImpulse * (1 + Rand.Range(-ImpulseSpread, ImpulseSpread));
|
||||
float modifiedLaunchImpulse = (LaunchImpulse + launchImpulseModifier) * (1 + Rand.Range(-ImpulseSpread, ImpulseSpread));
|
||||
DoLaunch(launchDir * modifiedLaunchImpulse * item.body.Mass);
|
||||
System.Diagnostics.Debug.WriteLine("launch: " + modifiedLaunchImpulse + " - " + item.body.LinearVelocity);
|
||||
}
|
||||
@@ -723,7 +730,7 @@ namespace Barotrauma.Items.Components
|
||||
private bool OnProjectileCollision(Fixture f1, Fixture target, Contact contact)
|
||||
{
|
||||
if (User != null && User.Removed) { User = null; return false; }
|
||||
if (IgnoredBodies.Contains(target.Body)) { return false; }
|
||||
if (IgnoredBodies != null && IgnoredBodies.Contains(target.Body)) { return false; }
|
||||
//ignore character colliders (the projectile only hits limbs)
|
||||
if (target.CollisionCategories == Physics.CollisionCharacter && target.Body.UserData is Character)
|
||||
{
|
||||
@@ -828,7 +835,7 @@ namespace Barotrauma.Items.Components
|
||||
private bool HandleProjectileCollision(Fixture target, Vector2 collisionNormal, Vector2 velocity)
|
||||
{
|
||||
if (User != null && User.Removed) { User = null; }
|
||||
if (IgnoredBodies.Contains(target.Body)) { return false; }
|
||||
if (IgnoredBodies != null && IgnoredBodies.Contains(target.Body)) { return false; }
|
||||
//ignore character colliders (the projectile only hits limbs)
|
||||
if (target.CollisionCategories == Physics.CollisionCharacter && target.Body.UserData is Character)
|
||||
{
|
||||
@@ -870,7 +877,7 @@ namespace Barotrauma.Items.Components
|
||||
else if ((target.Body.UserData as Item ?? (target.Body.UserData as ItemComponent)?.Item) is Item targetItem)
|
||||
{
|
||||
if (targetItem.Removed) { return false; }
|
||||
if (Attack != null && targetItem.Prefab.DamagedByProjectiles && targetItem.Condition > 0)
|
||||
if (Attack != null && (targetItem.Prefab.DamagedByProjectiles || DamageDoors && targetItem.GetComponent<Door>() != null) && targetItem.Condition > 0)
|
||||
{
|
||||
attackResult = Attack.DoDamage(User ?? Attacker, targetItem, item.WorldPosition, 1.0f);
|
||||
#if CLIENT
|
||||
@@ -1067,7 +1074,7 @@ namespace Barotrauma.Items.Components
|
||||
item.body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel;
|
||||
}
|
||||
}
|
||||
IgnoredBodies.Clear();
|
||||
IgnoredBodies?.Clear();
|
||||
}
|
||||
|
||||
private void StickToTarget(Body targetBody, Vector2 axis)
|
||||
|
||||
@@ -23,6 +23,9 @@ namespace Barotrauma.Items.Components
|
||||
private readonly HashSet<Wire> wires;
|
||||
public IReadOnlyCollection<Wire> Wires => wires;
|
||||
|
||||
private bool enumeratingWires;
|
||||
private readonly HashSet<Wire> removedWires = new HashSet<Wire>();
|
||||
|
||||
private readonly Item item;
|
||||
|
||||
public readonly bool IsOutput;
|
||||
@@ -239,7 +242,14 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
prevOtherConnection.recipientsDirty = true;
|
||||
}
|
||||
wires.Remove(wire);
|
||||
if (enumeratingWires)
|
||||
{
|
||||
removedWires.Add(wire);
|
||||
}
|
||||
else
|
||||
{
|
||||
wires.Remove(wire);
|
||||
}
|
||||
recipientsDirty = true;
|
||||
}
|
||||
|
||||
@@ -278,6 +288,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void SendSignal(Signal signal)
|
||||
{
|
||||
enumeratingWires = true;
|
||||
foreach (var wire in wires)
|
||||
{
|
||||
Connection recipient = wire.OtherConnection(this);
|
||||
@@ -301,6 +312,12 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
enumeratingWires = false;
|
||||
foreach (var removedWire in removedWires)
|
||||
{
|
||||
wires.Remove(removedWire);
|
||||
}
|
||||
removedWires.Clear();
|
||||
}
|
||||
|
||||
public void ClearConnections()
|
||||
@@ -313,13 +330,23 @@ namespace Barotrauma.Items.Components
|
||||
Powered.ChangedConnections.Add(c);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var wire in wires)
|
||||
{
|
||||
wire.RemoveConnection(this);
|
||||
recipientsDirty = true;
|
||||
}
|
||||
wires.Clear();
|
||||
|
||||
if (enumeratingWires)
|
||||
{
|
||||
foreach (var wire in wires)
|
||||
{
|
||||
removedWires.Add(wire);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wires.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void InitializeFromLoaded()
|
||||
|
||||
@@ -247,9 +247,14 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
public override void OnMapLoaded()
|
||||
{
|
||||
CheckIfNeedsUpdate();
|
||||
}
|
||||
|
||||
public void CheckIfNeedsUpdate()
|
||||
{
|
||||
if (item.body == null && powerConsumption <= 0.0f && Parent == null && turret == null && IsOn &&
|
||||
(statusEffectLists == null || !statusEffectLists.ContainsKey(ActionType.OnActive)) &&
|
||||
(statusEffectLists == null || !statusEffectLists.ContainsKey(ActionType.OnActive)) &&
|
||||
(IsActiveConditionals == null || IsActiveConditionals.Count == 0))
|
||||
{
|
||||
lightBrightness = 1.0f;
|
||||
@@ -261,6 +266,10 @@ namespace Barotrauma.Items.Components
|
||||
Light.ParentSub = item.Submarine;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
IsActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
|
||||
@@ -21,12 +21,15 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private float rotation, targetRotation;
|
||||
|
||||
private float reload, reloadTime;
|
||||
private float reload, reloadTime, delayBetweenBurst;
|
||||
private int shotsPerBurst, shotCounter;
|
||||
|
||||
private float minRotation, maxRotation;
|
||||
|
||||
private float launchImpulse;
|
||||
|
||||
private float damageMultiplier;
|
||||
|
||||
private Camera cam;
|
||||
|
||||
private float angularVelocity;
|
||||
@@ -94,6 +97,16 @@ namespace Barotrauma.Items.Components
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool flipFiringOffset;
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No, description: "If enabled, the firing offset will alternate from left to right (i.e. flipping the x-component of the offset each shot.)")]
|
||||
public bool AlternatingFiringOffset
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Vector2 TransformedBarrelPos
|
||||
{
|
||||
get
|
||||
@@ -116,6 +129,20 @@ namespace Barotrauma.Items.Components
|
||||
set { reloadTime = value; }
|
||||
}
|
||||
|
||||
[Editable(1, 100), Serialize(1, IsPropertySaveable.No, description: "How many projectiles needs to be shot before we add an extra break? Think of the double coilgun.")]
|
||||
public int ShotsPerBurst
|
||||
{
|
||||
get { return shotsPerBurst; }
|
||||
set { shotsPerBurst = value; }
|
||||
}
|
||||
|
||||
[Editable(0.0f, 1000.0f, decimals: 3), Serialize(0.0f, IsPropertySaveable.No, description: "An extra delay between the bursts. Added to the reload.")]
|
||||
public float DelayBetweenBursts
|
||||
{
|
||||
get { return delayBetweenBurst; }
|
||||
set { delayBetweenBurst = value; }
|
||||
}
|
||||
|
||||
[Editable(0.1f, 10f), Serialize(1.0f, IsPropertySaveable.No, description: "Modifies the duration of retraction of the barrell after recoil to get back to the original position after shooting. Reload time affects this too.")]
|
||||
public float RetractionDurationMultiplier
|
||||
{
|
||||
@@ -137,6 +164,13 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.No, description: "Multiplies the damage the turret deals by this amount.")]
|
||||
public float DamageMultiplier
|
||||
{
|
||||
get { return damageMultiplier; }
|
||||
set { damageMultiplier = value; }
|
||||
}
|
||||
|
||||
[Serialize(1, IsPropertySaveable.No, description: "How many projectiles the weapon launches when fired once.")]
|
||||
public int ProjectileCount
|
||||
{
|
||||
@@ -602,9 +636,9 @@ namespace Barotrauma.Items.Components
|
||||
if (projectiles.Any())
|
||||
{
|
||||
ItemContainer projectileContainer = projectiles.First().Item.Container?.GetComponent<ItemContainer>();
|
||||
if (projectileContainer != null && projectileContainer.Item != item)
|
||||
{
|
||||
projectileContainer?.Item.Use(deltaTime, null);
|
||||
if (projectileContainer != null && projectileContainer.Item != item)
|
||||
{
|
||||
projectileContainer?.Item.Use(deltaTime, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -764,6 +798,15 @@ namespace Barotrauma.Items.Components
|
||||
private void Launch(Item projectile, Character user = null, float? launchRotation = null, float tinkeringStrength = 0f)
|
||||
{
|
||||
reload = reloadTime;
|
||||
if (ShotsPerBurst > 1)
|
||||
{
|
||||
shotCounter++;
|
||||
if (shotCounter >= ShotsPerBurst)
|
||||
{
|
||||
reload += DelayBetweenBursts;
|
||||
shotCounter = 0;
|
||||
}
|
||||
}
|
||||
reload /= 1f + (tinkeringStrength * TinkeringReloadDecrease);
|
||||
|
||||
if (user != null)
|
||||
@@ -773,6 +816,10 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (projectile != null)
|
||||
{
|
||||
if (AlternatingFiringOffset)
|
||||
{
|
||||
flipFiringOffset = !flipFiringOffset;
|
||||
}
|
||||
activeProjectiles.Add(projectile);
|
||||
projectile.Drop(null, setTransform: false);
|
||||
if (projectile.body != null)
|
||||
@@ -796,9 +843,9 @@ namespace Barotrauma.Items.Components
|
||||
projectileComponent.Attacker = projectileComponent.User = user;
|
||||
if (projectileComponent.Attack != null)
|
||||
{
|
||||
projectileComponent.Attack.DamageMultiplier = 1f + (TinkeringDamageIncrease * tinkeringStrength);
|
||||
projectileComponent.Attack.DamageMultiplier = (1f * DamageMultiplier) + (TinkeringDamageIncrease * tinkeringStrength);
|
||||
}
|
||||
projectileComponent.Use();
|
||||
projectileComponent.Use(null, LaunchImpulse);
|
||||
projectile.GetComponent<Rope>()?.Attach(item, projectile);
|
||||
projectileComponent.User = user;
|
||||
|
||||
@@ -1452,7 +1499,9 @@ namespace Barotrauma.Items.Components
|
||||
Vector2 transformedFiringOffset = Vector2.Zero;
|
||||
if (useOffset)
|
||||
{
|
||||
transformedFiringOffset = MathUtils.RotatePoint(new Vector2(-FiringOffset.Y, -FiringOffset.X) * item.Scale, -rotation);
|
||||
Vector2 currOffSet = FiringOffset;
|
||||
if (flipFiringOffset) { currOffSet.X = -currOffSet.X; }
|
||||
transformedFiringOffset = MathUtils.RotatePoint(new Vector2(-currOffSet.Y, -currOffSet.X) * item.Scale, -rotation);
|
||||
}
|
||||
return new Vector2(item.WorldRect.X + transformedBarrelPos.X + transformedFiringOffset.X, item.WorldRect.Y - transformedBarrelPos.Y + transformedFiringOffset.Y);
|
||||
}
|
||||
|
||||
@@ -99,6 +99,7 @@ namespace Barotrauma
|
||||
private bool hasComponentsToDraw;
|
||||
|
||||
public PhysicsBody body;
|
||||
private float waterDragCoefficient;
|
||||
|
||||
public readonly XElement StaticBodyConfig;
|
||||
|
||||
@@ -860,12 +861,14 @@ namespace Barotrauma
|
||||
|
||||
SetActiveSprite();
|
||||
|
||||
ContentXElement bodyElement = null;
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "body":
|
||||
float density = subElement.GetAttributeFloat("density", 10.0f);
|
||||
bodyElement = subElement;
|
||||
float density = subElement.GetAttributeFloat("density", Physics.NeutralDensity);
|
||||
float minDensity = subElement.GetAttributeFloat("mindensity", density);
|
||||
float maxDensity = subElement.GetAttributeFloat("maxdensity", density);
|
||||
if (minDensity < maxDensity)
|
||||
@@ -905,6 +908,7 @@ namespace Barotrauma
|
||||
body = new PhysicsBody(subElement, ConvertUnits.ToSimUnits(Position), Scale, density, collisionCategory, collidesWith, findNewContacts: false);
|
||||
body.FarseerBody.AngularDamping = subElement.GetAttributeFloat("angulardamping", 0.2f);
|
||||
body.FarseerBody.LinearDamping = subElement.GetAttributeFloat("lineardamping", 0.1f);
|
||||
body.FarseerBody.LinearDamping = subElement.GetAttributeFloat("lineardamping", 0.1f);
|
||||
body.UserData = this;
|
||||
break;
|
||||
case "trigger":
|
||||
@@ -994,6 +998,8 @@ namespace Barotrauma
|
||||
if (body != null)
|
||||
{
|
||||
body.Submarine = submarine;
|
||||
waterDragCoefficient = bodyElement.GetAttributeFloat("waterdragcoefficient",
|
||||
GetComponent<Projectile>() != null || GetComponent<Throwable>() != null ? 0.1f : 1.0f);
|
||||
}
|
||||
|
||||
//cache connections into a dictionary for faster lookups
|
||||
@@ -1898,10 +1904,19 @@ namespace Barotrauma
|
||||
|
||||
if (needsWaterCheck)
|
||||
{
|
||||
bool wasInWater = inWater;
|
||||
inWater = IsInWater();
|
||||
bool waterProof = WaterProof;
|
||||
if (inWater)
|
||||
{
|
||||
//the item has gone through the surface of the water
|
||||
if (!wasInWater && CurrentHull != null && body != null && body.LinearVelocity.Y < -1.0f)
|
||||
{
|
||||
Splash();
|
||||
//slow the item down (not physically accurate, but looks good enough)
|
||||
body.LinearVelocity *= 0.2f;
|
||||
}
|
||||
|
||||
Item container = this.Container;
|
||||
while (!waterProof && container != null)
|
||||
{
|
||||
@@ -1929,7 +1944,8 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
partial void Splash();
|
||||
|
||||
public void UpdateTransform()
|
||||
{
|
||||
if (body == null) { return; }
|
||||
@@ -2017,23 +2033,47 @@ namespace Barotrauma
|
||||
{
|
||||
float floor = CurrentHull.Rect.Y - CurrentHull.Rect.Height;
|
||||
float waterLevel = floor + CurrentHull.WaterVolume / CurrentHull.Rect.Width;
|
||||
|
||||
//forceFactor is 1.0f if the item is completely submerged,
|
||||
//and goes to 0.0f as the item goes through the surface
|
||||
forceFactor = Math.Min((waterLevel - Position.Y) / rect.Height, 1.0f);
|
||||
if (forceFactor <= 0.0f) return;
|
||||
if (forceFactor <= 0.0f) { return; }
|
||||
}
|
||||
|
||||
bool moving = body.LinearVelocity.LengthSquared() > 0.001f;
|
||||
float volume = body.Mass / body.Density;
|
||||
if (moving)
|
||||
{
|
||||
//measure velocity from the velocity of the front of the item and apply the drag to the other end to get the drag to turn the item the "pointy end first"
|
||||
|
||||
var uplift = -GameMain.World.Gravity * forceFactor * volume;
|
||||
//a more "proper" (but more expensive) way to do this would be to e.g. calculate the drag separately for each edge of the fixture
|
||||
//but since we define the "front" as the "pointy end", we can cheat a bit by using that, and actually even make the drag appear more realistic in some cases
|
||||
//(e.g. a bullet with a rectangular fixture would be just as "aerodynamic" travelling backwards, but with this method we get it to turn the correct way)
|
||||
Vector2 localFront = body.GetLocalFront();
|
||||
Vector2 frontVel = body.FarseerBody.GetLinearVelocityFromLocalPoint(localFront);
|
||||
|
||||
Vector2 drag = body.LinearVelocity * volume;
|
||||
float speed = frontVel.Length();
|
||||
float drag = speed * speed * waterDragCoefficient * volume * Physics.NeutralDensity;
|
||||
//very small drag on active projectiles to prevent affecting their trajectories much
|
||||
if (body.FarseerBody.IsBullet) { drag *= 0.1f; }
|
||||
Vector2 dragVec = -frontVel / speed * drag;
|
||||
|
||||
body.ApplyForce((uplift - drag) * 10.0f);
|
||||
//apply the force slightly towards the back of the item to make it turn the front first
|
||||
Vector2 back = body.FarseerBody.GetWorldPoint(-localFront * 0.01f);
|
||||
body.ApplyForce(dragVec, back);
|
||||
}
|
||||
|
||||
//no need to apply buoyancy if the item is still and not light enough to float
|
||||
if (moving || body.Density < 10.0f)
|
||||
{
|
||||
Vector2 buoyancy = -GameMain.World.Gravity * forceFactor * volume * Physics.NeutralDensity;
|
||||
body.ApplyForce(buoyancy);
|
||||
}
|
||||
|
||||
//apply simple angular drag
|
||||
body.ApplyTorque(body.AngularVelocity * volume * -0.05f);
|
||||
if (Math.Abs(body.AngularVelocity) > 0.0001f)
|
||||
{
|
||||
body.ApplyTorque(body.AngularVelocity * volume * -0.1f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3270,7 +3310,7 @@ namespace Barotrauma
|
||||
relativeOrigin = MathUtils.RotatePoint(relativeOrigin, -item.RotationRad);
|
||||
Vector2 origin = new Vector2(rect.X + rect.Width / 2, rect.Y - rect.Height / 2) + relativeOrigin;
|
||||
|
||||
item.rect.Location -= ((origin - oldOrigin) * scaleRelativeToPrefab).ToPoint();
|
||||
item.rect.Location -= (origin - oldOrigin).ToPoint();
|
||||
}
|
||||
|
||||
if (item.PurchasedNewSwap && !string.IsNullOrEmpty(appliedSwap.SwappableItem?.SpawnWithId))
|
||||
|
||||
@@ -14,6 +14,8 @@ namespace Barotrauma
|
||||
readonly struct DeconstructItem
|
||||
{
|
||||
public readonly Identifier ItemIdentifier;
|
||||
//number of items to output
|
||||
public readonly int Amount;
|
||||
//minCondition does <= check, meaning that below or equal to min condition will be skipped.
|
||||
public readonly float MinCondition;
|
||||
//maxCondition does > check, meaning that above this max the deconstruct item will be skipped.
|
||||
@@ -37,6 +39,7 @@ namespace Barotrauma
|
||||
public DeconstructItem(XElement element, Identifier parentDebugName)
|
||||
{
|
||||
ItemIdentifier = element.GetAttributeIdentifier("identifier", "");
|
||||
Amount = element.GetAttributeInt("amount", 1);
|
||||
MinCondition = element.GetAttributeFloat("mincondition", -0.1f);
|
||||
MaxCondition = element.GetAttributeFloat("maxcondition", 1.0f);
|
||||
OutConditionMin = element.GetAttributeFloat("outconditionmin", element.GetAttributeFloat("outcondition", 1.0f));
|
||||
@@ -70,6 +73,20 @@ namespace Barotrauma
|
||||
public readonly float MinCondition;
|
||||
public readonly float MaxCondition;
|
||||
public readonly bool UseCondition;
|
||||
|
||||
public bool IsConditionSuitable(float conditionPercentage)
|
||||
{
|
||||
float normalizedCondition = conditionPercentage / 100.0f;
|
||||
if (MathUtils.NearlyEqual(normalizedCondition, MinCondition) || MathUtils.NearlyEqual(normalizedCondition, MaxCondition))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (normalizedCondition >= MinCondition && normalizedCondition <= MaxCondition)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class RequiredItemByIdentifier : RequiredItem
|
||||
@@ -393,12 +410,106 @@ namespace Barotrauma
|
||||
private set;
|
||||
}
|
||||
|
||||
public readonly struct CommonnessInfo
|
||||
{
|
||||
public float Commonness
|
||||
{
|
||||
get
|
||||
{
|
||||
return commonness;
|
||||
}
|
||||
}
|
||||
public float AbyssCommonness
|
||||
{
|
||||
get
|
||||
{
|
||||
return abyssCommonness ?? 0.0f;
|
||||
}
|
||||
}
|
||||
public float CaveCommonness
|
||||
{
|
||||
get
|
||||
{
|
||||
return caveCommonness ?? Commonness;
|
||||
}
|
||||
}
|
||||
public bool CanAppear
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Commonness > 0.0f) { return true; }
|
||||
if (AbyssCommonness > 0.0f) { return true; }
|
||||
if (CaveCommonness > 0.0f) { return true; }
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly float commonness;
|
||||
public readonly float? abyssCommonness;
|
||||
public readonly float? caveCommonness;
|
||||
|
||||
public CommonnessInfo(XElement element)
|
||||
{
|
||||
this.commonness = Math.Max(element?.GetAttributeFloat("commonness", 0.0f) ?? 0.0f, 0.0f);
|
||||
|
||||
float? abyssCommonness = null;
|
||||
XAttribute abyssCommonnessAttribute = element?.GetAttribute("abysscommonness") ?? element?.GetAttribute("abyss");
|
||||
if (abyssCommonnessAttribute != null)
|
||||
{
|
||||
abyssCommonness = Math.Max(abyssCommonnessAttribute.GetAttributeFloat(0.0f), 0.0f);
|
||||
}
|
||||
this.abyssCommonness = abyssCommonness;
|
||||
|
||||
float? caveCommonness = null;
|
||||
XAttribute caveCommonnessAttribute = element?.GetAttribute("cavecommonness") ?? element?.GetAttribute("cave");
|
||||
if (caveCommonnessAttribute != null)
|
||||
{
|
||||
caveCommonness = Math.Max(caveCommonnessAttribute.GetAttributeFloat(0.0f), 0.0f);
|
||||
}
|
||||
this.caveCommonness = caveCommonness;
|
||||
}
|
||||
|
||||
public CommonnessInfo(float commonness, float? abyssCommonness, float? caveCommonness)
|
||||
{
|
||||
this.commonness = commonness;
|
||||
this.abyssCommonness = abyssCommonness != null ? (float?)Math.Max(abyssCommonness.Value, 0.0f) : null;
|
||||
this.caveCommonness = caveCommonness != null ? (float?)Math.Max(caveCommonness.Value, 0.0f) : null;
|
||||
}
|
||||
|
||||
public CommonnessInfo WithInheritedCommonness(CommonnessInfo? parentInfo)
|
||||
{
|
||||
return new CommonnessInfo(commonness,
|
||||
abyssCommonness ?? parentInfo?.abyssCommonness,
|
||||
caveCommonness ?? parentInfo?.caveCommonness);
|
||||
}
|
||||
|
||||
public CommonnessInfo WithInheritedCommonness(params CommonnessInfo?[] parentInfos)
|
||||
{
|
||||
CommonnessInfo info = this;
|
||||
foreach (var parentInfo in parentInfos)
|
||||
{
|
||||
info = info.WithInheritedCommonness(parentInfo);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
public float GetCommonness(Level.TunnelType tunnelType)
|
||||
{
|
||||
if (tunnelType == Level.TunnelType.Cave)
|
||||
{
|
||||
return CaveCommonness;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Commonness;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How likely it is for the item to spawn in a level of a given type.
|
||||
/// Key = name of the LevelGenerationParameters (empty string = default value) /* TODO: empty string = default value???? */
|
||||
/// Value = commonness
|
||||
/// </summary>
|
||||
public ImmutableDictionary<Identifier, float> LevelCommonness { get; private set; }
|
||||
private ImmutableDictionary<Identifier, CommonnessInfo> LevelCommonness { get; set; }
|
||||
|
||||
public readonly struct FixedQuantityResourceInfo
|
||||
{
|
||||
@@ -747,7 +858,7 @@ namespace Barotrauma
|
||||
AllowDroppingOnSwapWith = allowDroppingOnSwapWith.ToImmutableHashSet();
|
||||
AllowDroppingOnSwap = allowDroppingOnSwapWith.Any();
|
||||
|
||||
var levelCommonness = new Dictionary<Identifier, float>();
|
||||
var levelCommonness = new Dictionary<Identifier, CommonnessInfo>();
|
||||
var levelQuantity = new Dictionary<Identifier, FixedQuantityResourceInfo>();
|
||||
|
||||
foreach (ContentXElement subElement in ConfigElement.Elements())
|
||||
@@ -871,7 +982,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (!levelCommonness.ContainsKey(levelName))
|
||||
{
|
||||
levelCommonness.Add(levelName, levelCommonnessElement.GetAttributeFloat("commonness", 0.0f));
|
||||
levelCommonness.Add(levelName, new CommonnessInfo(levelCommonnessElement));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -962,6 +1073,40 @@ namespace Barotrauma
|
||||
this.allowedLinks = ConfigElement.GetAttributeIdentifierArray("allowedlinks", Array.Empty<Identifier>()).ToImmutableHashSet();
|
||||
}
|
||||
|
||||
public CommonnessInfo? GetCommonnessInfo(Level level)
|
||||
{
|
||||
CommonnessInfo? levelCommonnessInfo = GetValueOrNull(level.GenerationParams.Identifier);
|
||||
CommonnessInfo? biomeCommonnessInfo = GetValueOrNull(level.LevelData.Biome.Identifier);
|
||||
CommonnessInfo? defaultCommonnessInfo = GetValueOrNull(Identifier.Empty);
|
||||
|
||||
if (levelCommonnessInfo.HasValue)
|
||||
{
|
||||
return levelCommonnessInfo?.WithInheritedCommonness(biomeCommonnessInfo, defaultCommonnessInfo);
|
||||
}
|
||||
else if (biomeCommonnessInfo.HasValue)
|
||||
{
|
||||
return biomeCommonnessInfo?.WithInheritedCommonness(defaultCommonnessInfo);
|
||||
}
|
||||
else if (defaultCommonnessInfo.HasValue)
|
||||
{
|
||||
return defaultCommonnessInfo;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
CommonnessInfo? GetValueOrNull(Identifier identifier)
|
||||
{
|
||||
if (LevelCommonness.TryGetValue(identifier, out CommonnessInfo info))
|
||||
{
|
||||
return info;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float GetTreatmentSuitability(Identifier treatmentIdentifier)
|
||||
{
|
||||
return treatmentSuitability.TryGetValue(treatmentIdentifier, out float suitability) ? suitability : 0.0f;
|
||||
|
||||
Reference in New Issue
Block a user