Unstable v0.15.17.0 (Hex is out of town edition)
This commit is contained in:
@@ -484,7 +484,7 @@ namespace Barotrauma.Items.Components
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"DockingPort.CreateDoorBody:InvalidPosition",
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
GameAnalyticsManager.ErrorSeverity.Error,
|
||||
errorMsg);
|
||||
position = Vector2.Zero;
|
||||
}
|
||||
@@ -779,29 +779,25 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (IsHorizontal)
|
||||
{
|
||||
if (hulls[0].WorldRect.X < hulls[1].WorldRect.X)
|
||||
if (hulls[0].WorldRect.X > hulls[1].WorldRect.X)
|
||||
{
|
||||
gap.linkedTo.Add(hulls[0]);
|
||||
gap.linkedTo.Add(hulls[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
gap.linkedTo.Add(hulls[1]);
|
||||
gap.linkedTo.Add(hulls[0]);
|
||||
var temp = hulls[0];
|
||||
hulls[0] = hulls[1];
|
||||
hulls[1] = temp;
|
||||
}
|
||||
gap.linkedTo.Add(hulls[0]);
|
||||
gap.linkedTo.Add(hulls[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hulls[0].WorldRect.Y > hulls[1].WorldRect.Y)
|
||||
if (hulls[0].WorldRect.Y < hulls[1].WorldRect.Y)
|
||||
{
|
||||
gap.linkedTo.Add(hulls[0]);
|
||||
gap.linkedTo.Add(hulls[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
gap.linkedTo.Add(hulls[1]);
|
||||
gap.linkedTo.Add(hulls[0]);
|
||||
var temp = hulls[0];
|
||||
hulls[0] = hulls[1];
|
||||
hulls[1] = temp;
|
||||
}
|
||||
gap.linkedTo.Add(hulls[0]);
|
||||
gap.linkedTo.Add(hulls[1]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
@@ -813,7 +809,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (IsHorizontal)
|
||||
{
|
||||
if (item.WorldPosition.X < DockingTarget.item.WorldPosition.X)
|
||||
if (doorGap.WorldPosition.X < gap.WorldPosition.X)
|
||||
{
|
||||
if (!doorGap.linkedTo.Contains(hulls[0])) { doorGap.linkedTo.Add(hulls[0]); }
|
||||
}
|
||||
@@ -831,7 +827,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.WorldPosition.Y > DockingTarget.item.WorldPosition.Y)
|
||||
if (doorGap.WorldPosition.Y > gap.WorldPosition.Y)
|
||||
{
|
||||
if (!doorGap.linkedTo.Contains(hulls[0])) { doorGap.linkedTo.Add(hulls[0]); }
|
||||
}
|
||||
|
||||
@@ -204,9 +204,12 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(true, true, description: ""), Editable]
|
||||
[Editable, Serialize(true, true, description: "", alwaysUseInstanceValues: true)]
|
||||
public bool UseBetweenOutpostModules { get; private set; }
|
||||
|
||||
[Editable, Serialize(false, false, description: "If true, bots won't try to close this door behind them.", alwaysUseInstanceValues: true)]
|
||||
public bool BotsShouldKeepOpen { get; private set; }
|
||||
|
||||
public Door(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
@@ -291,7 +294,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool Pick(Character picker)
|
||||
{
|
||||
if (item.Condition < RepairThreshold) { return true; }
|
||||
if (item.Condition < RepairThreshold && item.GetComponent<Repairable>().HasRequiredItems(picker, addMessage: false)) { return true; }
|
||||
if (requiredItems.None()) { return false; }
|
||||
if (HasAccess(picker) && HasRequiredItems(picker, false)) { return false; }
|
||||
return base.Pick(picker);
|
||||
@@ -299,7 +302,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool OnPicked(Character picker)
|
||||
{
|
||||
if (item.Condition < RepairThreshold) { return true; }
|
||||
if (item.Condition < RepairThreshold && item.GetComponent<Repairable>().HasRequiredItems(picker, addMessage: false)) { return true; }
|
||||
if (!HasAccess(picker))
|
||||
{
|
||||
ToggleState(ActionType.OnPicked, picker);
|
||||
@@ -339,6 +342,7 @@ namespace Barotrauma.Items.Components
|
||||
ToggleState(ActionType.OnUse, character);
|
||||
PickingTime = originalPickingTime;
|
||||
StopPicking(picker);
|
||||
return true;
|
||||
}
|
||||
#if CLIENT
|
||||
else if (hasRequiredItems && character != null && character == Character.Controlled)
|
||||
@@ -545,7 +549,7 @@ namespace Barotrauma.Items.Components
|
||||
if (!itemPosErrorShown)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to push a character out of a doorway - position of the door is not valid (" + item.SimPosition + ")");
|
||||
GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:DoorPosInvalid", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:DoorPosInvalid", GameAnalyticsManager.ErrorSeverity.Error,
|
||||
"Failed to push a character out of a doorway - position of the door is not valid (" + item.SimPosition + ").");
|
||||
itemPosErrorShown = true;
|
||||
}
|
||||
@@ -568,8 +572,8 @@ namespace Barotrauma.Items.Components
|
||||
if (!characterPosErrorShown.Contains(c))
|
||||
{
|
||||
if (GameSettings.VerboseLogging) { DebugConsole.ThrowError("Failed to push a character out of a doorway - position of the character \"" + c.Name + "\" is not valid (" + c.SimPosition + ")"); }
|
||||
GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:CharacterPosInvalid", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Failed to push a character out of a doorway - position of the character \"" + c.Name + "\" is not valid (" + c.SimPosition + ")." +
|
||||
GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:CharacterPosInvalid", GameAnalyticsManager.ErrorSeverity.Error,
|
||||
"Failed to push a character out of a doorway - position of the character \"" + c.SpeciesName + "\" is not valid (" + c.SimPosition + ")." +
|
||||
" Removed: " + c.Removed +
|
||||
" Remoteplayer: " + c.IsRemotePlayer);
|
||||
characterPosErrorShown.Add(c);
|
||||
@@ -598,8 +602,8 @@ namespace Barotrauma.Items.Components
|
||||
if (!MathUtils.IsValid(body.SimPosition))
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to push a limb out of a doorway - position of the body (character \"" + c.Name + "\") is not valid (" + body.SimPosition + ")");
|
||||
GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:LimbPosInvalid", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Failed to push a character out of a doorway - position of the character \"" + c.Name + "\" is not valid (" + body.SimPosition + ")." +
|
||||
GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:LimbPosInvalid", GameAnalyticsManager.ErrorSeverity.Error,
|
||||
"Failed to push a character out of a doorway - position of the character \"" + c.SpeciesName + "\" is not valid (" + body.SimPosition + ")." +
|
||||
" Removed: " + c.Removed +
|
||||
" Remoteplayer: " + c.IsRemotePlayer);
|
||||
return false;
|
||||
|
||||
@@ -310,12 +310,6 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
internal static class GrowthSideExtension
|
||||
{
|
||||
// Enum.HasFlag() sucks
|
||||
public static bool IsBitSet(this TileSide side, TileSide bit)
|
||||
{
|
||||
return ((int) side & (int) bit) != 0;
|
||||
}
|
||||
|
||||
// K&R algorithm for counting how many bits are set in a bit field
|
||||
public static int Count(this TileSide side)
|
||||
{
|
||||
|
||||
@@ -169,7 +169,7 @@ namespace Barotrauma.Items.Components
|
||||
CollidesWith = Physics.CollisionCharacter,
|
||||
CollisionCategories = Physics.CollisionItemBlocking,
|
||||
Enabled = false,
|
||||
UserData = "Holdable.Pusher"
|
||||
UserData = this
|
||||
};
|
||||
Pusher.FarseerBody.OnCollision += OnPusherCollision;
|
||||
Pusher.FarseerBody.FixedRotation = false;
|
||||
|
||||
@@ -69,14 +69,28 @@ namespace Barotrauma.Items.Components
|
||||
public override bool Pick(Character picker)
|
||||
{
|
||||
//return if someone is already trying to pick the item
|
||||
if (pickTimer > 0.0f) return false;
|
||||
if (picker == null || picker.Inventory == null) return false;
|
||||
if (pickTimer > 0.0f) { return false; }
|
||||
if (picker == null || picker.Inventory == null) { return false; }
|
||||
|
||||
if (PickingTime > 0.0f)
|
||||
{
|
||||
var abilityPickingTime = new AbilityValueItem(PickingTime, item.Prefab);
|
||||
picker.CheckTalents(AbilityEffectType.OnItemPicked, abilityPickingTime);
|
||||
|
||||
if (requiredItems.ContainsKey(RelatedItem.RelationType.Equipped))
|
||||
{
|
||||
foreach (RelatedItem ri in requiredItems[RelatedItem.RelationType.Equipped])
|
||||
{
|
||||
foreach (var heldItem in picker.HeldItems)
|
||||
{
|
||||
if (ri.MatchesItem(heldItem))
|
||||
{
|
||||
abilityPickingTime.Value /= 1 + heldItem.Prefab.AddedPickingSpeedMultiplier;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((picker.PickingItem == null || picker.PickingItem == item) && PickingTime <= float.MaxValue)
|
||||
{
|
||||
#if SERVER
|
||||
|
||||
@@ -32,6 +32,13 @@ namespace Barotrauma.Items.Components
|
||||
set { reload = Math.Max(value, 0.0f); }
|
||||
}
|
||||
|
||||
[Serialize(false, false, description: "Tells the AI to hold the trigger down when it uses this weapon")]
|
||||
public bool HoldTrigger
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(1, false, description: "How projectiles the weapon launches when fired once.")]
|
||||
public int ProjectileCount
|
||||
{
|
||||
@@ -110,9 +117,7 @@ namespace Barotrauma.Items.Components
|
||||
if (ReloadTimer < 0.0f)
|
||||
{
|
||||
ReloadTimer = 0.0f;
|
||||
// was this an optimization or related to something else? it cannot occur for charge-type weapons
|
||||
//IsActive = false;
|
||||
if (MaxChargeTime == 0.0f)
|
||||
if (MaxChargeTime <= 0f)
|
||||
{
|
||||
IsActive = false;
|
||||
return;
|
||||
@@ -147,7 +152,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private float GetSpread(Character user)
|
||||
{
|
||||
float degreeOfFailure = 1.0f - DegreeOfSuccess(user);
|
||||
float degreeOfFailure = MathHelper.Clamp(1.0f - DegreeOfSuccess(user), 0.0f, 1.0f);
|
||||
degreeOfFailure *= degreeOfFailure;
|
||||
float spread = MathHelper.Lerp(Spread, UnskilledSpread, degreeOfFailure) / (1f + user.GetStatValue(StatTypes.RangedSpreadReduction));
|
||||
return MathHelper.ToRadians(spread);
|
||||
@@ -204,7 +209,8 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
lastProjectile?.Item.GetComponent<Rope>()?.Snap();
|
||||
}
|
||||
float damageMultiplier = 1f + item.GetQualityModifier(Quality.StatType.StoppingPowerMultiplier);
|
||||
float damageMultiplier = 1f + item.GetQualityModifier(Quality.StatType.FirepowerMultiplier);
|
||||
projectile.Launcher = item;
|
||||
projectile.Shoot(character, character.AnimController.AimSourceSimPos, barrelPos, rotation + spread, ignoredBodies: limbBodies.ToList(), createNetworkEvent: false, damageMultiplier);
|
||||
projectile.Item.GetComponent<Rope>()?.Attach(Item, projectile.Item);
|
||||
if (i == 0)
|
||||
|
||||
@@ -613,7 +613,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
string errorMsg = "ItemComponent.DegreeOfSuccess failed (character was null).\n" + Environment.StackTrace.CleanupStackTrace();
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("ItemComponent.DegreeOfSuccess:CharacterNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("ItemComponent.DegreeOfSuccess:CharacterNull", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
@@ -889,7 +889,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
DebugConsole.ThrowError("Error while loading entity of the type " + t + ".", e.InnerException);
|
||||
GameAnalyticsManager.AddErrorEventOnce("ItemComponent.Load:TargetInvocationException" + item.Name + element.Name,
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
GameAnalyticsManager.ErrorSeverity.Error,
|
||||
"Error while loading entity of the type " + t + " (" + e.InnerException + ")\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
}
|
||||
|
||||
@@ -994,7 +994,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
containObjective = new AIObjectiveContainItem(character, container.ContainableItemIdentifiers.ToArray(), container, currentObjective.objectiveManager, spawnItemIfNotFound: spawnItemIfNotFound)
|
||||
{
|
||||
targetItemCount = itemCount,
|
||||
ItemCount = itemCount,
|
||||
Equip = equip,
|
||||
RemoveEmpty = removeEmpty,
|
||||
GetItemPriority = i =>
|
||||
|
||||
@@ -471,7 +471,7 @@ namespace Barotrauma.Items.Components
|
||||
if (!slotRestrictions.Any(s => s.MatchesItem(item))) { return false; }
|
||||
if (user != null && !user.CanAccessInventory(Inventory)) { return false; }
|
||||
//genetic materials use special logic for combining, don't allow doing it by placing them inside each other here
|
||||
if (item.GetComponent<GeneticMaterial>() != null) { return false; }
|
||||
if (this.Item.GetComponent<GeneticMaterial>() != null) { return false; }
|
||||
|
||||
if (Inventory.TryPutItem(item, user))
|
||||
{
|
||||
@@ -577,7 +577,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
DebugConsole.Log("SetTransformIgnoreContacts threw an exception in SetContainedItemPositions (" + e.Message + ")\n" + e.StackTrace.CleanupStackTrace());
|
||||
GameAnalyticsManager.AddErrorEventOnce("ItemContainer.SetContainedItemPositions.InvalidPosition:" + contained.Name,
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
GameAnalyticsManager.ErrorSeverity.Error,
|
||||
"SetTransformIgnoreContacts threw an exception in SetContainedItemPositions (" + e.Message + ")\n" + e.StackTrace.CleanupStackTrace());
|
||||
}
|
||||
contained.body.Submarine = item.Submarine;
|
||||
|
||||
@@ -61,14 +61,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public IEnumerable<LimbPos> LimbPositions { get { return limbPositions; } }
|
||||
|
||||
[Editable, Serialize(false, false, description: "When enabled, the item will continuously send out a 0/1 signal and interacting with it will flip the signal (making the item behave like a switch). When disabled, the item will simply send out 1 when interacted with.")]
|
||||
[Editable, Serialize(false, false, description: "When enabled, the item will continuously send out a 0/1 signal and interacting with it will flip the signal (making the item behave like a switch). When disabled, the item will simply send out 1 when interacted with.", alwaysUseInstanceValues: true)]
|
||||
public bool IsToggle
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Editable, Serialize(false, false, description: "Whether the item is toggled on/off. Only valid if IsToggle is set to true.")]
|
||||
[Editable, Serialize(false, false, description: "Whether the item is toggled on/off. Only valid if IsToggle is set to true.", alwaysUseInstanceValues: true)]
|
||||
public bool State
|
||||
{
|
||||
get;
|
||||
|
||||
+39
-11
@@ -158,10 +158,21 @@ namespace Barotrauma.Items.Components
|
||||
// In multiplayer, the server handles the deconstruction into new items
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||
|
||||
float amountMultiplier = 1f;
|
||||
|
||||
if (user != null && !user.Removed)
|
||||
{
|
||||
var abilityTargetItem = new AbilityItem(targetItem);
|
||||
var abilityTargetItem = new AbilityDeconstructedItem(targetItem, user);
|
||||
user.CheckTalents(AbilityEffectType.OnItemDeconstructed, abilityTargetItem);
|
||||
|
||||
foreach (Character character in Character.GetFriendlyCrew(user))
|
||||
{
|
||||
character.CheckTalents(AbilityEffectType.OnItemDeconstructedByAlly, abilityTargetItem);
|
||||
}
|
||||
|
||||
var itemCreationMultiplier = new AbilityValueItem(amountMultiplier, targetItem.Prefab);
|
||||
user.CheckTalents(AbilityEffectType.OnItemDeconstructedMaterial, itemCreationMultiplier);
|
||||
amountMultiplier = (int)itemCreationMultiplier.Value;
|
||||
}
|
||||
|
||||
if (targetItem.Prefab.RandomDeconstructionOutput)
|
||||
@@ -187,18 +198,18 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
foreach (DeconstructItem deconstructProduct in products)
|
||||
{
|
||||
CreateDeconstructProduct(deconstructProduct, inputItems);
|
||||
CreateDeconstructProduct(deconstructProduct, inputItems, amountMultiplier);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (DeconstructItem deconstructProduct in validDeconstructItems)
|
||||
{
|
||||
CreateDeconstructProduct(deconstructProduct, inputItems);
|
||||
CreateDeconstructProduct(deconstructProduct, inputItems, amountMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
void CreateDeconstructProduct(DeconstructItem deconstructProduct, IEnumerable<Item> inputItems)
|
||||
void CreateDeconstructProduct(DeconstructItem deconstructProduct, IEnumerable<Item> inputItems, float amountMultiplier)
|
||||
{
|
||||
float percentageHealth = targetItem.Condition / targetItem.MaxCondition;
|
||||
|
||||
@@ -247,19 +258,15 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
int amount = 1;
|
||||
|
||||
if (user != null && !user.Removed)
|
||||
{
|
||||
var itemsCreated = new AbilityValueItem(amount, targetItem.Prefab);
|
||||
user.CheckTalents(AbilityEffectType.OnItemDeconstructedMaterial, itemsCreated);
|
||||
amount = (int)itemsCreated.Value;
|
||||
|
||||
// used to spawn items directly into the deconstructor
|
||||
var itemContainer = new AbilityItemPrefabItem(item, targetItem.Prefab);
|
||||
user.CheckTalents(AbilityEffectType.OnItemDeconstructedInventory, itemContainer);
|
||||
}
|
||||
|
||||
int amount = (int)amountMultiplier;
|
||||
|
||||
for (int i = 0; i < amount; i++)
|
||||
{
|
||||
Entity.Spawner.AddToSpawnQueue(itemPrefab, outputContainer.Inventory, condition, onSpawned: (Item spawnedItem) =>
|
||||
@@ -269,7 +276,17 @@ namespace Barotrauma.Items.Components
|
||||
for (int i = 0; i < outputContainer.Capacity; i++)
|
||||
{
|
||||
var containedItem = outputContainer.Inventory.GetItemAt(i);
|
||||
if (containedItem?.Combine(spawnedItem, null) ?? false)
|
||||
if (containedItem?.OwnInventory != null)
|
||||
{
|
||||
foreach (Item subItem in containedItem.ContainedItems.ToList())
|
||||
{
|
||||
if (subItem.Combine(spawnedItem, null))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (containedItem?.Combine(spawnedItem, null) ?? false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -409,4 +426,15 @@ namespace Barotrauma.Items.Components
|
||||
inputContainer.Inventory.Locked = IsActive;
|
||||
}
|
||||
}
|
||||
class AbilityDeconstructedItem : AbilityObject, IAbilityItem, IAbilityCharacter
|
||||
{
|
||||
public AbilityDeconstructedItem(Item item, Character character)
|
||||
{
|
||||
Item = item;
|
||||
Character = character;
|
||||
}
|
||||
public Item Item { get; set; }
|
||||
public Character Character { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -376,7 +376,7 @@ namespace Barotrauma.Items.Components
|
||||
int quality = 0;
|
||||
if (user?.Info != null)
|
||||
{
|
||||
foreach (Character character in Character.CharacterList.Where(c => c.TeamID == user.TeamID))
|
||||
foreach (Character character in Character.GetFriendlyCrew(user))
|
||||
{
|
||||
character.CheckTalents(AbilityEffectType.OnAllyItemFabricatedAmount, fabricationValueItem);
|
||||
}
|
||||
@@ -433,13 +433,12 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
float userSkill = user.GetSkillLevel(skill.Identifier);
|
||||
float addedSkill = skill.Level * SkillSettings.Current.SkillIncreasePerFabricatorRequiredSkill / Math.Max(userSkill, 1.0f);
|
||||
var addedSkillValue = new AbilityValueString(0f, skill.Identifier);
|
||||
var addedSkillValue = new AbilityValueString(addedSkill, skill.Identifier);
|
||||
user.CheckTalents(AbilityEffectType.OnItemFabricationSkillGain, addedSkillValue);
|
||||
addedSkill += addedSkillValue.Value;
|
||||
|
||||
user.Info.IncreaseSkillLevel(
|
||||
skill.Identifier,
|
||||
addedSkill);
|
||||
addedSkillValue.Value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -147,16 +147,12 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
case "water_data_in":
|
||||
//cheating a bit because water detectors don't actually send the water level
|
||||
float waterAmount;
|
||||
if (source.GetComponent<WaterDetector>() == null)
|
||||
bool fromWaterDetector = source.GetComponent<WaterDetector>() != null;
|
||||
hullData.ReceivedWaterAmount = null;
|
||||
if (fromWaterDetector)
|
||||
{
|
||||
waterAmount = Rand.Range(0.0f, 1.0f);
|
||||
hullData.ReceivedWaterAmount = Math.Min(sourceHull.WaterVolume / sourceHull.Volume, 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
waterAmount = Math.Min(sourceHull.WaterVolume / sourceHull.Volume, 1.0f);
|
||||
}
|
||||
hullData.ReceivedWaterAmount = waterAmount;
|
||||
foreach (var linked in sourceHull.linkedTo)
|
||||
{
|
||||
if (!(linked is Hull linkedHull)) { continue; }
|
||||
@@ -165,7 +161,11 @@ namespace Barotrauma.Items.Components
|
||||
linkedHullData = new HullData();
|
||||
hullDatas.Add(linkedHull, linkedHullData);
|
||||
}
|
||||
linkedHullData.ReceivedWaterAmount = waterAmount;
|
||||
linkedHullData.ReceivedWaterAmount = null;
|
||||
if (fromWaterDetector)
|
||||
{
|
||||
linkedHullData.ReceivedWaterAmount = Math.Min(linkedHull.WaterVolume / linkedHull.Volume, 1.0f);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "oxygen_data_in":
|
||||
|
||||
@@ -186,6 +186,13 @@ namespace Barotrauma.Items.Components
|
||||
[Serialize(0.0f, true)]
|
||||
public float CorrectTurbineOutput { get; set; }
|
||||
|
||||
[Editable, Serialize(true, true)]
|
||||
public bool ExplosionDamagesOtherSubs
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Reactor(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
@@ -544,6 +551,20 @@ namespace Barotrauma.Items.Components
|
||||
if (item.Condition <= 0.0f) { return; }
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||
|
||||
if (!ExplosionDamagesOtherSubs && (statusEffectLists?.ContainsKey(ActionType.OnBroken) ?? false))
|
||||
{
|
||||
foreach (var statusEffect in statusEffectLists[ActionType.OnBroken])
|
||||
{
|
||||
foreach (Explosion explosion in statusEffect.Explosions)
|
||||
{
|
||||
foreach (Submarine sub in Submarine.Loaded)
|
||||
{
|
||||
if (sub != item.Submarine) { explosion.IgnoredSubmarines.Add(sub); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item.Condition = 0.0f;
|
||||
fireTimer = 0.0f;
|
||||
meltDownTimer = 0.0f;
|
||||
@@ -600,7 +621,7 @@ namespace Barotrauma.Items.Components
|
||||
var container = item.GetComponent<ItemContainer>();
|
||||
if (objective.SubObjectives.None())
|
||||
{
|
||||
var containObjective = AIContainItems<Reactor>(container, character, objective, itemCount: 1, equip: true, removeEmpty: true, spawnItemIfNotFound: character.TeamID == CharacterTeamType.FriendlyNPC, dropItemOnDeselected: true);
|
||||
var containObjective = AIContainItems<Reactor>(container, character, objective, itemCount: 1, equip: true, removeEmpty: true, spawnItemIfNotFound: !character.IsOnPlayerTeam, dropItemOnDeselected: true);
|
||||
containObjective.Completed += ReportFuelRodCount;
|
||||
containObjective.Abandoned += ReportFuelRodCount;
|
||||
character.Speak(TextManager.Get("DialogReactorFuel"), null, 0.0f, "reactorfuel", 30.0f);
|
||||
|
||||
@@ -61,6 +61,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public List<Body> IgnoredBodies;
|
||||
|
||||
/// <summary>
|
||||
/// The item that launched this projectile (if any)
|
||||
/// </summary>
|
||||
public Item Launcher;
|
||||
|
||||
private Character stickTargetCharacter;
|
||||
|
||||
private Character _user;
|
||||
@@ -324,6 +329,7 @@ namespace Barotrauma.Items.Components
|
||||
item.body.SetTransform(item.body.SimPosition, launchAngle);
|
||||
float modifiedLaunchImpulse = LaunchImpulse * (1 + Rand.Range(-ImpulseSpread, ImpulseSpread));
|
||||
DoLaunch(launchDir * modifiedLaunchImpulse * item.body.Mass);
|
||||
System.Diagnostics.Debug.WriteLine("launch: " + modifiedLaunchImpulse + " - " + item.body.LinearVelocity);
|
||||
}
|
||||
}
|
||||
User = character;
|
||||
@@ -347,7 +353,7 @@ namespace Barotrauma.Items.Components
|
||||
launchPos = item.SimPosition;
|
||||
|
||||
item.body.Enabled = true;
|
||||
item.body.ApplyLinearImpulse(impulse, maxVelocity: NetConfig.MaxPhysicsBodyVelocity * 0.9f);
|
||||
item.body.ApplyLinearImpulse(impulse, maxVelocity: NetConfig.MaxPhysicsBodyVelocity * 0.95f);
|
||||
|
||||
item.body.FarseerBody.OnCollision += OnProjectileCollision;
|
||||
item.body.FarseerBody.IsBullet = true;
|
||||
@@ -523,11 +529,13 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (fixture.Body.UserData is Item item && (item.GetComponent<Door>() == null && !item.Prefab.DamagedByProjectiles || item.Condition <= 0)) { return -1; }
|
||||
if (fixture.Body.UserData as string == "ruinroom" || fixture.Body?.UserData is Hull || fixture.UserData is Hull) { return -1; }
|
||||
|
||||
//ignore everything else than characters, sub walls and level walls
|
||||
if (!fixture.CollisionCategories.HasFlag(Physics.CollisionCharacter) &&
|
||||
!fixture.CollisionCategories.HasFlag(Physics.CollisionWall) &&
|
||||
!fixture.CollisionCategories.HasFlag(Physics.CollisionLevel)) { return -1; }
|
||||
if (!(fixture.Body.UserData is Holdable holdable && holdable.CanPush))
|
||||
{
|
||||
//ignore everything else than characters, sub walls and level walls
|
||||
if (!fixture.CollisionCategories.HasFlag(Physics.CollisionCharacter) &&
|
||||
!fixture.CollisionCategories.HasFlag(Physics.CollisionWall) &&
|
||||
!fixture.CollisionCategories.HasFlag(Physics.CollisionLevel)) { return -1; }
|
||||
}
|
||||
|
||||
//if doing the raycast in a submarine's coordinate space, ignore anything that's not in that sub
|
||||
if (submarine != null)
|
||||
@@ -566,7 +574,7 @@ namespace Barotrauma.Items.Components
|
||||
hits.Add(new HitscanResult(fixture, point, normal, fraction));
|
||||
|
||||
return 1;
|
||||
}, rayStart, rayEnd, Physics.CollisionCharacter | Physics.CollisionWall | Physics.CollisionLevel);
|
||||
}, rayStart, rayEnd, Physics.CollisionCharacter | Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionItemBlocking);
|
||||
|
||||
return hits;
|
||||
}
|
||||
@@ -754,7 +762,7 @@ namespace Barotrauma.Items.Components
|
||||
if (Attack != null) { attackResult = Attack.DoDamageToLimb(User ?? Attacker, limb, item.WorldPosition, 1.0f); }
|
||||
if (limb.character != null) { character = limb.character; }
|
||||
}
|
||||
else if (target.Body.UserData is Item targetItem)
|
||||
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)
|
||||
|
||||
@@ -26,12 +26,13 @@ namespace Barotrauma.Items.Components
|
||||
RepairToolStructureRepairMultiplier,
|
||||
RepairToolStructureDamageMultiplier,
|
||||
RepairToolDeattachTimeMultiplier,
|
||||
StoppingPowerMultiplier,
|
||||
FirepowerMultiplier,
|
||||
StrikingPowerMultiplier,
|
||||
StrikingSpeedMultiplier,
|
||||
FiringRateMultiplier,
|
||||
// unused as of now
|
||||
AttackMultiplier,
|
||||
// unused as of now
|
||||
AttackSpeedMultiplier,
|
||||
ForceDoorsOpenSpeedMultiplier,
|
||||
RangedSpreadReduction,
|
||||
@@ -46,7 +47,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private int qualityLevel;
|
||||
|
||||
[Serialize(0, true)]
|
||||
[Editable, Serialize(0, true)]
|
||||
public int QualityLevel
|
||||
{
|
||||
get { return qualityLevel; }
|
||||
|
||||
@@ -16,6 +16,8 @@ namespace Barotrauma.Items.Components
|
||||
private float deteriorationTimer;
|
||||
private float deteriorateAlwaysResetTimer;
|
||||
|
||||
private float repairBoost;
|
||||
|
||||
bool wasBroken;
|
||||
bool wasGoodCondition;
|
||||
|
||||
@@ -214,6 +216,18 @@ namespace Barotrauma.Items.Components
|
||||
return ((average + 100.0f) / 2.0f) / 100.0f;
|
||||
}
|
||||
|
||||
public void RepairBoost(bool qteSuccess)
|
||||
{
|
||||
if (qteSuccess)
|
||||
{
|
||||
repairBoost = RepairDegreeOfSuccess(CurrentFixer, requiredSkills) * 3 * (currentFixerAction == FixActions.Repair ? 1.0f : -1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
repairBoost = (1 - RepairDegreeOfSuccess(CurrentFixer, requiredSkills)) * 10 * (currentFixerAction == FixActions.Repair ? -1.0f : 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public bool StartRepairing(Character character, FixActions action)
|
||||
{
|
||||
if (character == null || character.IsDead || action == FixActions.None)
|
||||
@@ -409,6 +423,12 @@ namespace Barotrauma.Items.Components
|
||||
wasGoodCondition = true;
|
||||
}
|
||||
|
||||
if (!MathUtils.NearlyEqual(repairBoost, 0.0f))
|
||||
{
|
||||
item.Condition += repairBoost;
|
||||
repairBoost = 0.0f;
|
||||
}
|
||||
|
||||
float fixDuration = MathHelper.Lerp(FixDurationLowSkill, FixDurationHighSkill, successFactor);
|
||||
fixDuration /= 1 + CurrentFixer.GetStatValue(StatTypes.RepairSpeed) + currentRepairItem?.Prefab.AddedRepairSpeedMultiplier ?? 0f;
|
||||
fixDuration /= 1 + item.GetQualityModifier(Quality.StatType.RepairSpeed);
|
||||
@@ -444,6 +464,7 @@ namespace Barotrauma.Items.Components
|
||||
SteamAchievementManager.OnItemRepaired(item, CurrentFixer);
|
||||
CurrentFixer.CheckTalents(AbilityEffectType.OnRepairComplete);
|
||||
}
|
||||
if (CurrentFixer?.SelectedConstruction == item) { CurrentFixer.SelectedConstruction = null; }
|
||||
deteriorationTimer = Rand.Range(MinDeteriorationDelay, MaxDeteriorationDelay);
|
||||
wasBroken = false;
|
||||
StopRepairing(CurrentFixer);
|
||||
|
||||
@@ -36,9 +36,9 @@ namespace Barotrauma.Items.Components
|
||||
if (UseHSV)
|
||||
{
|
||||
Color hsvColor = ToolBox.HSVToRGB(signalR, signalG, signalB);
|
||||
signalR = hsvColor.R / (float) byte.MaxValue;
|
||||
signalG = hsvColor.G / (float) byte.MaxValue;
|
||||
signalB = hsvColor.B / (float) byte.MaxValue;
|
||||
signalR = hsvColor.R;
|
||||
signalG = hsvColor.G;
|
||||
signalB = hsvColor.B;
|
||||
}
|
||||
|
||||
output = signalR.ToString("G", CultureInfo.InvariantCulture);
|
||||
|
||||
@@ -36,9 +36,17 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
case FunctionType.Round:
|
||||
value = MathF.Round(value);
|
||||
if (value == -0)
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case FunctionType.Ceil:
|
||||
value = MathF.Ceiling(value);
|
||||
if (value == -0)
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
case FunctionType.Floor:
|
||||
value = MathF.Floor(value);
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace Barotrauma.Items.Components
|
||||
switch (connection.Name)
|
||||
{
|
||||
case "set_text":
|
||||
|
||||
case "signal_in":
|
||||
if (signal.value.Length > MaxMessageLength)
|
||||
{
|
||||
signal.value = signal.value.Substring(0, MaxMessageLength);
|
||||
@@ -128,6 +128,8 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
history.ClearChildren();
|
||||
}
|
||||
|
||||
CreateFillerBlock();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,12 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (item.CurrentHull != null)
|
||||
{
|
||||
int waterPercentage = MathHelper.Clamp((int)Math.Ceiling(item.CurrentHull.WaterPercentage), 0, 100);
|
||||
int waterPercentage = 0;
|
||||
//ignore minuscule amounts of water
|
||||
if (item.CurrentHull.WaterVolume < 1.0f)
|
||||
{
|
||||
waterPercentage = MathHelper.Clamp((int)Math.Ceiling(item.CurrentHull.WaterPercentage), 0, 100);
|
||||
}
|
||||
item.SendSignal(waterPercentage.ToString(), "water_%");
|
||||
}
|
||||
string highPressureOut = (item.CurrentHull == null || item.CurrentHull.LethalPressure > 5.0f) ? "1" : "0";
|
||||
|
||||
@@ -112,7 +112,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
return HasRequiredContainedItems(user: null, addMessage: false);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the wifi components that can receive signals from this one
|
||||
/// </summary>
|
||||
public IEnumerable<WifiComponent> GetReceiversInRange()
|
||||
{
|
||||
return list.Where(w => w != this && w.CanReceive(this));
|
||||
@@ -121,11 +124,7 @@ namespace Barotrauma.Items.Components
|
||||
public bool CanReceive(WifiComponent sender)
|
||||
{
|
||||
if (sender == null || sender.channel != channel) { return false; }
|
||||
|
||||
if (sender.TeamID != TeamID && !AllowCrossTeamCommunication)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (sender.TeamID != TeamID && !AllowCrossTeamCommunication) { return false; }
|
||||
|
||||
//if the component is not linked to chat and has nothing connected to the output, sending a signal to it does nothing
|
||||
// = no point in receiving
|
||||
@@ -142,6 +141,21 @@ namespace Barotrauma.Items.Components
|
||||
return HasRequiredContainedItems(user: null, addMessage: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the wifi components that can transmit signals to this one
|
||||
/// </summary>
|
||||
public IEnumerable<WifiComponent> GetTransmittersInRange()
|
||||
{
|
||||
return list.Where(w => w != this && w.CanTransmit(this));
|
||||
}
|
||||
|
||||
public bool CanTransmit(WifiComponent sender)
|
||||
{
|
||||
if (sender == null || sender.channel != channel) { return false; }
|
||||
if (sender.TeamID != TeamID && !AllowCrossTeamCommunication) { return false; }
|
||||
if (Vector2.DistanceSquared(item.WorldPosition, sender.item.WorldPosition) > sender.range * sender.range) { return false; }
|
||||
return HasRequiredContainedItems(user: null, addMessage: false);
|
||||
}
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
chatMsgCooldown -= deltaTime;
|
||||
|
||||
@@ -756,14 +756,17 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (item.ParentInventory != null) { return; }
|
||||
#if CLIENT
|
||||
if (!relativeToSub && Screen.Selected != GameMain.SubEditorScreen) { return; }
|
||||
if (!relativeToSub)
|
||||
{
|
||||
if (Screen.Selected != GameMain.SubEditorScreen || (item.Submarine?.Loading ?? false)) { return; }
|
||||
}
|
||||
#else
|
||||
if (!relativeToSub) { return; }
|
||||
#endif
|
||||
|
||||
Vector2 refPos = item.Submarine == null ?
|
||||
Vector2.Zero :
|
||||
item.Position - item.Submarine.HiddenSubPosition;
|
||||
item.Position - item.Submarine.HiddenSubPosition;
|
||||
|
||||
for (int i = 0; i < nodes.Count; i++)
|
||||
{
|
||||
|
||||
@@ -64,6 +64,8 @@ namespace Barotrauma.Items.Components
|
||||
private Character currentTarget;
|
||||
const float aiFindTargetInterval = 5.0f;
|
||||
|
||||
private int currentLoaderIndex;
|
||||
|
||||
private const float TinkeringPowerCostReduction = 0.2f;
|
||||
private const float TinkeringDamageIncrease = 0.2f;
|
||||
private const float TinkeringReloadDecrease = 0.2f;
|
||||
@@ -592,16 +594,17 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (MapEntity e in item.linkedTo)
|
||||
for (int j = 0; j < item.linkedTo.Count; j++)
|
||||
{
|
||||
var e = item.linkedTo[(j + currentLoaderIndex) % item.linkedTo.Count];
|
||||
//use linked projectile containers in case they have to react to the turret being launched somehow
|
||||
//(play a sound, spawn more projectiles)
|
||||
if (!(e is Item linkedItem)) { continue; }
|
||||
if (!item.prefab.IsLinkAllowed(e.prefab)) { continue; }
|
||||
if (linkedItem.Condition <= 0.0f)
|
||||
if (linkedItem.Condition <= 0.0f)
|
||||
{
|
||||
loaderBroken = true;
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
ItemContainer projectileContainer = linkedItem.GetComponent<ItemContainer>();
|
||||
if (projectileContainer != null)
|
||||
@@ -610,7 +613,6 @@ namespace Barotrauma.Items.Components
|
||||
projectiles = GetLoadedProjectiles();
|
||||
if (projectiles.Any()) { break; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (projectiles.Count == 0 && !LaunchWithoutProjectile)
|
||||
@@ -705,6 +707,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
ShiftItemsInProjectileContainer(container.GetComponent<ItemContainer>());
|
||||
}
|
||||
if (item.linkedTo.Count > 0)
|
||||
{
|
||||
currentLoaderIndex = (currentLoaderIndex + 1) % item.linkedTo.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -759,6 +765,7 @@ namespace Barotrauma.Items.Components
|
||||
Projectile projectileComponent = projectile.GetComponent<Projectile>();
|
||||
if (projectileComponent != null)
|
||||
{
|
||||
projectileComponent.Launcher = item;
|
||||
projectileComponent.Attacker = projectileComponent.User = user;
|
||||
if (projectileComponent.Attack != null)
|
||||
{
|
||||
@@ -1163,7 +1170,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
targetPos = closestEnemy.WorldPosition;
|
||||
//if the enemy is inside another sub, aim at the room they're in to make it less obvious that the enemy "knows" exactly where the target is
|
||||
if (closestEnemy.Submarine != null && closestEnemy.CurrentHull != null && closestEnemy.Submarine != item.Submarine)
|
||||
if (closestEnemy.Submarine != null && closestEnemy.CurrentHull != null && closestEnemy.Submarine != item.Submarine && !closestEnemy.CanSeeTarget(Item))
|
||||
{
|
||||
targetPos = closestEnemy.CurrentHull.WorldPosition;
|
||||
}
|
||||
@@ -1442,8 +1449,9 @@ namespace Barotrauma.Items.Components
|
||||
List<Projectile> projectiles = new List<Projectile>();
|
||||
// check the item itself first
|
||||
CheckProjectileContainer(item, projectiles, out bool _);
|
||||
foreach (MapEntity e in item.linkedTo)
|
||||
for (int j = 0; j < item.linkedTo.Count; j++)
|
||||
{
|
||||
var e = item.linkedTo[(j + currentLoaderIndex) % item.linkedTo.Count];
|
||||
if (!item.prefab.IsLinkAllowed(e.prefab)) { continue; }
|
||||
if (e is Item projectileContainer)
|
||||
{
|
||||
@@ -1451,7 +1459,6 @@ namespace Barotrauma.Items.Components
|
||||
if (projectiles.Any() || stopSearching) { return projectiles; }
|
||||
}
|
||||
}
|
||||
|
||||
return projectiles;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user