Unstable 0.15.13.0
This commit is contained in:
@@ -104,6 +104,7 @@ namespace Barotrauma
|
||||
!pathSteering.CurrentPath.Unreachable &&
|
||||
(!requireNonDirty || !pathSteering.IsPathDirty);
|
||||
|
||||
public bool IsCurrentPathNullOrUnreachable => IsCurrentPathUnreachable || steeringManager is IndoorsSteeringManager pathSteering && pathSteering.CurrentPath == null;
|
||||
public bool IsCurrentPathUnreachable => steeringManager is IndoorsSteeringManager pathSteering && !pathSteering.IsPathDirty && pathSteering.CurrentPath != null && pathSteering.CurrentPath.Unreachable;
|
||||
public bool IsCurrentPathFinished => steeringManager is IndoorsSteeringManager pathSteering && !pathSteering.IsPathDirty && pathSteering.CurrentPath != null && pathSteering.CurrentPath.Finished;
|
||||
|
||||
@@ -431,7 +432,7 @@ namespace Barotrauma
|
||||
Vector2 diff = EscapeTarget.WorldPosition - Character.WorldPosition;
|
||||
float sqrDist = diff.LengthSquared();
|
||||
bool isClose = sqrDist < MathUtils.Pow2(100);
|
||||
if (Character.CurrentHull == null || isClose && !isClosedDoor || pathSteering == null || IsCurrentPathUnreachable || IsCurrentPathFinished)
|
||||
if (Character.CurrentHull == null || isClose && !isClosedDoor || pathSteering == null || IsCurrentPathNullOrUnreachable || IsCurrentPathFinished)
|
||||
{
|
||||
// Very close to the target, outside, or at the end of the path -> try to steer through the gap
|
||||
SteeringManager.Reset();
|
||||
|
||||
@@ -3659,15 +3659,15 @@ namespace Barotrauma
|
||||
{
|
||||
if (SelectedAiTarget == null) { return; }
|
||||
Vector2 escapeDir = Vector2.Normalize(WorldPosition - SelectedAiTarget.WorldPosition);
|
||||
if (!MathUtils.IsValid(escapeDir))
|
||||
{
|
||||
escapeDir = Vector2.UnitY;
|
||||
}
|
||||
if (Character.CurrentHull != null && !Character.AnimController.InWater)
|
||||
{
|
||||
// Inside
|
||||
escapeDir = new Vector2(Math.Sign(escapeDir.X), 0);
|
||||
}
|
||||
if (!MathUtils.IsValid(escapeDir))
|
||||
{
|
||||
escapeDir = Vector2.UnitY;
|
||||
}
|
||||
SteeringManager.Reset();
|
||||
SteeringManager.SteeringManual(deltaTime, escapeDir);
|
||||
}
|
||||
|
||||
@@ -250,7 +250,15 @@ namespace Barotrauma
|
||||
{
|
||||
rayEnd += SelectedAiTarget.Entity.Submarine.SimPosition;
|
||||
}
|
||||
UseIndoorSteeringOutside = Submarine.PickBody(SimPosition, rayEnd, collisionCategory: Physics.CollisionLevel | Physics.CollisionWall) != null;
|
||||
IEnumerable<FarseerPhysics.Dynamics.Body> ignoredBodies = null;
|
||||
if (SelectedAiTarget.Entity is ISpatialEntity spatialTarget)
|
||||
{
|
||||
Submarine targetSub = spatialTarget.Submarine;
|
||||
if (targetSub != null)
|
||||
{
|
||||
ignoredBodies = targetSub.PhysicsBody.FarseerBody.ToEnumerable();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -340,14 +348,21 @@ namespace Barotrauma
|
||||
IsInsideCave = Character.CurrentHull == null && Level.Loaded?.Caves.FirstOrDefault(c => c.Area.Contains(Character.WorldPosition)) is Level.Cave;
|
||||
}
|
||||
|
||||
if (UseIndoorSteeringOutside || IsInsideCave || Character.CurrentHull?.Submarine != null || hasValidPath && IsCloseEnoughToTarget(maxSteeringBuffer) || IsCloseEnoughToTarget(steeringBuffer))
|
||||
if (UseIndoorSteeringOutside || IsInsideCave || Character.CurrentHull?.Submarine != null || hasValidPath || IsCloseEnoughToTarget(steeringBuffer))
|
||||
{
|
||||
if (steeringManager != insideSteering)
|
||||
{
|
||||
insideSteering.Reset();
|
||||
steeringManager = insideSteering;
|
||||
}
|
||||
steeringBuffer += steeringBufferIncreaseSpeed * deltaTime;
|
||||
if (IsCloseEnoughToTarget(maxSteeringBuffer))
|
||||
{
|
||||
steeringBuffer += steeringBufferIncreaseSpeed * deltaTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
steeringBuffer = minSteeringBuffer;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -309,13 +309,15 @@ namespace Barotrauma
|
||||
}
|
||||
if (currentPath.Finished)
|
||||
{
|
||||
Vector2 pos2 = host.SimPosition;
|
||||
if (character != null && character.Submarine == null &&
|
||||
CurrentPath.Nodes.Count > 0 && CurrentPath.Nodes.Last().Submarine != null)
|
||||
var lastNode = currentPath.Nodes.LastOrDefault();
|
||||
if (lastNode == null)
|
||||
{
|
||||
pos2 -= CurrentPath.Nodes.Last().Submarine.SimPosition;
|
||||
return Vector2.Zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ConvertUnits.ToSimUnits(lastNode.WorldPosition - host.WorldPosition);
|
||||
}
|
||||
return currentTarget - pos2;
|
||||
}
|
||||
bool doorsChecked = false;
|
||||
if (!character.LockHands && buttonPressCooldown <= 0.0f)
|
||||
@@ -323,29 +325,7 @@ namespace Barotrauma
|
||||
CheckDoorsInPath();
|
||||
doorsChecked = true;
|
||||
}
|
||||
Vector2 pos = host.SimPosition;
|
||||
if (character != null && CurrentPath.CurrentNode != null)
|
||||
{
|
||||
var nodeSub = CurrentPath.CurrentNode.Submarine;
|
||||
if (nodeSub != null)
|
||||
{
|
||||
if (character.Submarine == null)
|
||||
{
|
||||
// Going inside
|
||||
pos -= ConvertUnits.ToSimUnits(nodeSub.Position);
|
||||
}
|
||||
else if (character.Submarine != nodeSub)
|
||||
{
|
||||
// Different subs
|
||||
pos -= ConvertUnits.ToSimUnits(nodeSub.Position - character.Submarine.Position);
|
||||
}
|
||||
}
|
||||
else if (character.Submarine != null)
|
||||
{
|
||||
// Going outside
|
||||
pos += ConvertUnits.ToSimUnits(character.Submarine.Position);
|
||||
}
|
||||
}
|
||||
Vector2 pos = host.WorldPosition;
|
||||
bool isDiving = character.AnimController.InWater && character.AnimController.HeadInWater;
|
||||
// Only humanoids can climb ladders
|
||||
bool canClimb = character.AnimController is HumanoidAnimController && !character.LockHands;
|
||||
@@ -384,7 +364,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (character.IsClimbing && useLadders)
|
||||
{
|
||||
Vector2 diff = currentPath.CurrentNode.SimPosition - pos;
|
||||
Vector2 diff = currentPath.CurrentNode.WorldPosition - pos;
|
||||
bool nextLadderSameAsCurrent = IsNextLadderSameAsCurrent;
|
||||
if (nextLadderSameAsCurrent)
|
||||
{
|
||||
@@ -397,7 +377,7 @@ namespace Barotrauma
|
||||
float heightFromFloor = character.AnimController.GetColliderBottom().Y - character.AnimController.FloorY;
|
||||
if (heightFromFloor <= 0.0f)
|
||||
{
|
||||
diff.Y = Math.Max(diff.Y, 1.0f);
|
||||
diff.Y = Math.Max(diff.Y, 100);
|
||||
}
|
||||
// We need some margin, because if a hatch has closed, it's possible that the height from floor is slightly negative.
|
||||
bool isAboveFloor = heightFromFloor > -0.1f;
|
||||
@@ -430,7 +410,7 @@ namespace Barotrauma
|
||||
NextNode(!doorsChecked);
|
||||
}
|
||||
}
|
||||
return diff;
|
||||
return ConvertUnits.ToSimUnits(diff);
|
||||
}
|
||||
else if (character.AnimController.InWater)
|
||||
{
|
||||
@@ -481,7 +461,7 @@ namespace Barotrauma
|
||||
{
|
||||
return Vector2.Zero;
|
||||
}
|
||||
return currentPath.CurrentNode.SimPosition - pos;
|
||||
return ConvertUnits.ToSimUnits(currentPath.CurrentNode.WorldPosition - pos);
|
||||
}
|
||||
|
||||
private void NextNode(bool checkDoors)
|
||||
|
||||
+6
-2
@@ -45,6 +45,10 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public bool AllowStealing { get; set; }
|
||||
public bool TakeWholeStack { get; set; }
|
||||
/// <summary>
|
||||
/// Are variants of the specified item allowed
|
||||
/// </summary>
|
||||
public bool AllowVariants { get; set; }
|
||||
public bool Equip { get; set; }
|
||||
public bool Wear { get; set; }
|
||||
|
||||
@@ -265,7 +269,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
float priority = Math.Clamp(objectiveManager.GetCurrentPriority(), 10, 100);
|
||||
bool checkPath = priority >= AIObjectiveManager.LowestOrderPriority && (objectiveManager.IsCurrentOrder<AIObjectiveFixLeaks>() || objectiveManager.CurrentOrder is AIObjectiveGoTo gotoOrder && gotoOrder.followControlledCharacter);
|
||||
bool checkPath = priority >= AIObjectiveManager.LowestOrderPriority && (objectiveManager.IsCurrentOrder<AIObjectiveFixLeaks>() || objectiveManager.CurrentOrder is AIObjectiveGoTo gotoOrder && gotoOrder.isFollowOrderObjective);
|
||||
bool hasCalledPathFinder = false;
|
||||
int itemsPerFrame = (int)priority;
|
||||
for (int i = 0; i < itemsPerFrame && currSearchIndex < Item.ItemList.Count - 1; i++)
|
||||
@@ -408,7 +412,7 @@ namespace Barotrauma
|
||||
if (ignoredItems.Contains(item)) { return false; };
|
||||
if (item.Condition < TargetCondition) { return false; }
|
||||
if (ItemFilter != null && !ItemFilter(item)) { return false; }
|
||||
return identifiersOrTags.Any(id => id == item.Prefab.Identifier || item.HasTag(id));
|
||||
return identifiersOrTags.Any(id => id == item.Prefab.Identifier || item.HasTag(id) || (AllowVariants && item.Prefab.VariantOf?.Identifier == id));
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
|
||||
+10
-17
@@ -24,7 +24,7 @@ namespace Barotrauma
|
||||
|
||||
public Func<float> priorityGetter;
|
||||
|
||||
public bool followControlledCharacter;
|
||||
public bool isFollowOrderObjective;
|
||||
public bool mimic;
|
||||
public bool SpeakIfFails { get; set; } = true;
|
||||
public bool UsePathingOutside { get; set; } = true;
|
||||
@@ -165,17 +165,10 @@ namespace Barotrauma
|
||||
|
||||
protected override void Act(float deltaTime)
|
||||
{
|
||||
if (followControlledCharacter)
|
||||
if (Target == null)
|
||||
{
|
||||
if (Character.Controlled != null && HumanAIController.IsFriendly(Character.Controlled))
|
||||
{
|
||||
Target = Character.Controlled;
|
||||
}
|
||||
if (Target == null)
|
||||
{
|
||||
Abandon = true;
|
||||
return;
|
||||
}
|
||||
Abandon = true;
|
||||
return;
|
||||
}
|
||||
if (Target == character || character.SelectedBy != null && HumanAIController.IsFriendly(character.SelectedBy))
|
||||
{
|
||||
@@ -205,7 +198,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
Hull targetHull = GetTargetHull();
|
||||
if (!followControlledCharacter)
|
||||
if (!isFollowOrderObjective)
|
||||
{
|
||||
// Abandon if going through unsafe paths. Note ignores unsafe nodes when following an order or when the objective is set to ignore unsafe hulls.
|
||||
bool containsUnsafeNodes = character.IsDismissed && !HumanAIController.ObjectiveManager.CurrentObjective.IgnoreUnsafeHulls
|
||||
@@ -223,7 +216,7 @@ namespace Barotrauma
|
||||
{
|
||||
Abandon = true;
|
||||
}
|
||||
else if (HumanAIController.IsCurrentPathUnreachable)
|
||||
else if (HumanAIController.IsCurrentPathNullOrUnreachable)
|
||||
{
|
||||
waitUntilPathUnreachable -= deltaTime;
|
||||
SteeringManager.Reset();
|
||||
@@ -317,8 +310,8 @@ namespace Barotrauma
|
||||
Character targetCharacter = Target as Character;
|
||||
if (character.AnimController.InWater)
|
||||
{
|
||||
if (character.CurrentHull == null ||
|
||||
followControlledCharacter &&
|
||||
if (character.CurrentHull == null ||
|
||||
isFollowOrderObjective &&
|
||||
targetCharacter != null && (targetCharacter.CurrentHull == null) != (character.CurrentHull == null) &&
|
||||
Vector2.DistanceSquared(character.WorldPosition, Target.WorldPosition) < maxGapDistance * maxGapDistance)
|
||||
{
|
||||
@@ -361,7 +354,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (TargetGap != null)
|
||||
{
|
||||
if (TargetGap.FlowTargetHull != null && HumanAIController.SteerThroughGap(TargetGap, followControlledCharacter ? Target.WorldPosition : TargetGap.FlowTargetHull.WorldPosition, deltaTime))
|
||||
if (TargetGap.FlowTargetHull != null && HumanAIController.SteerThroughGap(TargetGap, isFollowOrderObjective ? Target.WorldPosition : TargetGap.FlowTargetHull.WorldPosition, deltaTime))
|
||||
{
|
||||
SteeringManager.SteeringAvoid(deltaTime, avoidLookAheadDistance, weight: 1);
|
||||
return;
|
||||
@@ -595,7 +588,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (gap.Open < 1) { continue; }
|
||||
if (gap.Submarine == null) { continue; }
|
||||
if (!followControlledCharacter)
|
||||
if (!isFollowOrderObjective)
|
||||
{
|
||||
if (gap.FlowTargetHull == null) { continue; }
|
||||
if (gap.Submarine != Target.Submarine) { continue; }
|
||||
|
||||
+1
-1
@@ -452,7 +452,7 @@ namespace Barotrauma
|
||||
extraDistanceWhileSwimming = 100,
|
||||
AllowGoingOutside = true,
|
||||
IgnoreIfTargetDead = true,
|
||||
followControlledCharacter = true,
|
||||
isFollowOrderObjective = true,
|
||||
mimic = true,
|
||||
DialogueIdentifier = "dialogcannotreachplace"
|
||||
};
|
||||
|
||||
+4
-1
@@ -107,7 +107,10 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (RelatedItem requiredItem in kvp.Value)
|
||||
{
|
||||
var getItemObjective = new AIObjectiveGetItem(character, requiredItem.Identifiers, objectiveManager, true);
|
||||
var getItemObjective = new AIObjectiveGetItem(character, requiredItem.Identifiers, objectiveManager, true)
|
||||
{
|
||||
AllowVariants = requiredItem.AllowVariants
|
||||
};
|
||||
if (objectiveManager.IsCurrentOrder<AIObjectiveRepairItems>())
|
||||
{
|
||||
if (character.IsOnPlayerTeam)
|
||||
|
||||
+1
-1
@@ -408,7 +408,7 @@ namespace Barotrauma
|
||||
}
|
||||
bool isCompleted =
|
||||
AIObjectiveRescueAll.GetVitalityFactor(targetCharacter) >= AIObjectiveRescueAll.GetVitalityThreshold(objectiveManager, character, targetCharacter) ||
|
||||
targetCharacter.CharacterHealth.GetAllAfflictions().All(a => a.Strength <= a.Prefab.TreatmentThreshold);
|
||||
targetCharacter.CharacterHealth.GetAllAfflictions().All(a => a.Prefab.IsBuff || a.Strength <= a.Prefab.TreatmentThreshold);
|
||||
|
||||
if (isCompleted && targetCharacter != character && character.IsOnPlayerTeam)
|
||||
{
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ namespace Barotrauma
|
||||
if (character.AIController is HumanAIController humanAI)
|
||||
{
|
||||
if (GetVitalityFactor(target) >= GetVitalityThreshold(humanAI.ObjectiveManager, character, target) ||
|
||||
target.CharacterHealth.GetAllAfflictions().All(a => a.Strength <= a.Prefab.TreatmentThreshold))
|
||||
target.CharacterHealth.GetAllAfflictions().All(a => a.Prefab.IsBuff || a.Strength <= a.Prefab.TreatmentThreshold))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1367,7 +1367,7 @@ namespace Barotrauma
|
||||
info.Job.GiveJobItems(this, spawnPoint);
|
||||
}
|
||||
|
||||
public void GiveIdCardTags(WayPoint spawnPoint)
|
||||
public void GiveIdCardTags(WayPoint spawnPoint, bool createNetworkEvent = false)
|
||||
{
|
||||
if (info?.Job == null || spawnPoint == null) { return; }
|
||||
|
||||
@@ -1378,6 +1378,10 @@ namespace Barotrauma
|
||||
{
|
||||
item.AddTag(s);
|
||||
}
|
||||
if (createNetworkEvent && (GameMain.NetworkMember?.IsServer ?? false))
|
||||
{
|
||||
GameMain.NetworkMember.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ChangeProperty, item.SerializableProperties["tags"] });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1756,6 +1760,7 @@ namespace Barotrauma
|
||||
}
|
||||
else if (IsPlayer)
|
||||
{
|
||||
float dist = -1;
|
||||
Vector2 attackPos = SimPosition + ConvertUnits.ToSimUnits(cursorPosition - Position);
|
||||
List<Body> ignoredBodies = AnimController.Limbs.Select(l => l.body.FarseerBody).ToList();
|
||||
ignoredBodies.Add(AnimController.Collider.FarseerBody);
|
||||
@@ -1787,13 +1792,13 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
if (body.UserData is IDamageable)
|
||||
if (body.UserData is IDamageable damageable)
|
||||
{
|
||||
attackTarget = (IDamageable)body.UserData;
|
||||
attackTarget = damageable;
|
||||
}
|
||||
else if (body.UserData is Limb)
|
||||
else if (body.UserData is Limb limb)
|
||||
{
|
||||
attackTarget = ((Limb)body.UserData).character;
|
||||
attackTarget = limb.character;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1822,7 +1827,20 @@ namespace Barotrauma
|
||||
var attackLimb = sortedLimbs.FirstOrDefault();
|
||||
if (attackLimb != null)
|
||||
{
|
||||
attackLimb.UpdateAttack(deltaTime, attackPos, attackTarget, out AttackResult attackResult);
|
||||
if (attackTarget is Character targetCharacter)
|
||||
{
|
||||
dist = ConvertUnits.ToDisplayUnits(Vector2.Distance(Submarine.LastPickedPosition, attackLimb.SimPosition));
|
||||
foreach (Limb limb in targetCharacter.AnimController.Limbs)
|
||||
{
|
||||
if (limb.IsSevered || limb.Removed) { continue; }
|
||||
float tempDist = ConvertUnits.ToDisplayUnits(Vector2.Distance(limb.SimPosition, attackLimb.SimPosition));
|
||||
if (tempDist < dist)
|
||||
{
|
||||
dist = tempDist;
|
||||
}
|
||||
}
|
||||
}
|
||||
attackLimb.UpdateAttack(deltaTime, attackPos, attackTarget, out AttackResult attackResult, dist);
|
||||
if (!attackLimb.attack.IsRunning)
|
||||
{
|
||||
attackCoolDown = 1.0f;
|
||||
@@ -3438,7 +3456,7 @@ namespace Barotrauma
|
||||
|
||||
var attackResult = targetLimb == null ?
|
||||
AddDamage(worldPosition, attackAfflictions, attack.Stun, playSound, attackImpulse, out limbHit, attacker, attack.DamageMultiplier * attackData.DamageMultiplier) :
|
||||
DamageLimb(worldPosition, targetLimb, attackAfflictions, attack.Stun, playSound, attackImpulse, attacker, attack.DamageMultiplier * attackData.DamageMultiplier, penetration: penetration + attackData.AddedPenetration);
|
||||
DamageLimb(worldPosition, targetLimb, attackAfflictions, attack.Stun, playSound, attackImpulse, attacker, attack.DamageMultiplier * attackData.DamageMultiplier, penetration: penetration + attackData.AddedPenetration, shouldImplode: attackData.ShouldImplode);
|
||||
|
||||
if (attacker != null)
|
||||
{
|
||||
@@ -3558,12 +3576,12 @@ namespace Barotrauma
|
||||
|
||||
public void RecordKill(Character target)
|
||||
{
|
||||
var abilityCharacter = new AbilityCharacter(target);
|
||||
var abilityCharacterKill = new AbilityCharacterKill(target, this);
|
||||
foreach (Character attackerCrewmember in GetFriendlyCrew(this))
|
||||
{
|
||||
attackerCrewmember.CheckTalents(AbilityEffectType.OnCrewKillCharacter, abilityCharacter);
|
||||
attackerCrewmember.CheckTalents(AbilityEffectType.OnCrewKillCharacter, abilityCharacterKill);
|
||||
}
|
||||
CheckTalents(AbilityEffectType.OnKillCharacter, abilityCharacter);
|
||||
CheckTalents(AbilityEffectType.OnKillCharacter, abilityCharacterKill);
|
||||
|
||||
if (!IsOnPlayerTeam) { return; }
|
||||
if (GameMain.Config.KilledCreatures.Any(name => name.Equals(target.SpeciesName, StringComparison.OrdinalIgnoreCase))) { return; }
|
||||
@@ -3579,7 +3597,7 @@ namespace Barotrauma
|
||||
GameMain.Config.RecentlyEncounteredCreatures.Add(other.SpeciesName);
|
||||
}
|
||||
|
||||
public AttackResult DamageLimb(Vector2 worldPosition, Limb hitLimb, IEnumerable<Affliction> afflictions, float stun, bool playSound, float attackImpulse, Character attacker = null, float damageMultiplier = 1, bool allowStacking = true, float penetration = 0f)
|
||||
public AttackResult DamageLimb(Vector2 worldPosition, Limb hitLimb, IEnumerable<Affliction> afflictions, float stun, bool playSound, float attackImpulse, Character attacker = null, float damageMultiplier = 1, bool allowStacking = true, float penetration = 0f, bool shouldImplode = false)
|
||||
{
|
||||
if (Removed) { return new AttackResult(); }
|
||||
|
||||
@@ -3638,6 +3656,12 @@ namespace Barotrauma
|
||||
float prevVitality = CharacterHealth.Vitality;
|
||||
AttackResult attackResult = hitLimb.AddDamage(simPos, afflictions, playSound, damageMultiplier: damageMultiplier, penetration: penetration, attacker: attacker);
|
||||
CharacterHealth.ApplyDamage(hitLimb, attackResult, allowStacking);
|
||||
if (shouldImplode)
|
||||
{
|
||||
// Only used by assistant's True Potential talent. Has to run here in order to properly give kill credit when it activates.
|
||||
Implode();
|
||||
}
|
||||
|
||||
if (attacker != this)
|
||||
{
|
||||
OnAttacked?.Invoke(attacker, attackResult);
|
||||
@@ -3786,7 +3810,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void Implode(bool isNetworkMessage = false)
|
||||
private void Implode(bool isNetworkMessage = false)
|
||||
{
|
||||
if (CharacterHealth.Unkillable || GodMode || IsDead) { return; }
|
||||
|
||||
@@ -4626,4 +4650,16 @@ namespace Barotrauma
|
||||
AggressiveBehavior = aggressiveBehavior;
|
||||
}
|
||||
}
|
||||
|
||||
class AbilityCharacterKill : AbilityObject, IAbilityCharacter
|
||||
{
|
||||
public AbilityCharacterKill(Character character, Character killer)
|
||||
{
|
||||
Character = character;
|
||||
Killer = killer;
|
||||
}
|
||||
public Character Character { get; set; }
|
||||
public Character Killer { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -291,7 +291,7 @@ namespace Barotrauma
|
||||
husk.SetStun(5);
|
||||
yield return new WaitForSeconds(5, false);
|
||||
#if CLIENT
|
||||
husk.PlaySound(CharacterSound.SoundType.Idle);
|
||||
husk?.PlaySound(CharacterSound.SoundType.Idle);
|
||||
#endif
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
@@ -844,6 +844,8 @@ namespace Barotrauma
|
||||
FaceTint = DefaultFaceTint;
|
||||
BodyTint = Color.TransparentBlack;
|
||||
|
||||
if (!(Character?.Params?.Health.ApplyAfflictionColors ?? false)) { return; }
|
||||
|
||||
for (int i = 0; i < limbHealths.Count; i++)
|
||||
{
|
||||
for (int j = limbHealths[i].Afflictions.Count - 1; j >= 0; j--)
|
||||
|
||||
@@ -466,6 +466,9 @@ namespace Barotrauma
|
||||
[Serialize(false, true), Editable]
|
||||
public bool StunImmunity { get; set; }
|
||||
|
||||
[Serialize(false, true, description: "Can afflictions affect the face/body tint of the character."), Editable]
|
||||
public bool ApplyAfflictionColors { get; private set; }
|
||||
|
||||
// TODO: limbhealths, sprite?
|
||||
|
||||
public HealthParams(XElement element, CharacterParams character) : base(element, character) { }
|
||||
|
||||
+2
-1
@@ -14,8 +14,9 @@ namespace Barotrauma.Abilities
|
||||
|
||||
protected override bool MatchesConditionSpecific(AbilityObject abilityObject)
|
||||
{
|
||||
if ((abilityObject as IAbilityCharacter)?.Character is Character character)
|
||||
if (abilityObject is IAbilityCharacter abilityCharacter)
|
||||
{
|
||||
if (!(abilityCharacter.Character is Character character)) { return false; }
|
||||
if (!IsViableTarget(targetTypes, character)) { return false; }
|
||||
|
||||
return true;
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Abilities
|
||||
{
|
||||
class AbilityConditionGeneHarvester : AbilityConditionData
|
||||
{
|
||||
|
||||
public AbilityConditionGeneHarvester(CharacterTalent characterTalent, XElement conditionElement) : base(characterTalent, conditionElement) { }
|
||||
|
||||
protected override bool MatchesConditionSpecific(AbilityObject abilityObject)
|
||||
{
|
||||
if (abilityObject is AbilityCharacterKill abilityCharacterKill)
|
||||
{
|
||||
return abilityCharacterKill.Killer.Submarine == null || abilityCharacterKill.Killer.TeamID != abilityCharacterKill.Killer.Submarine.TeamID;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogAbilityConditionError(abilityObject, typeof(AbilityCharacterKill));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -136,6 +136,7 @@ namespace Barotrauma.Abilities
|
||||
public float DamageMultiplier { get; set; } = 1f;
|
||||
public float AddedPenetration { get; set; } = 0f;
|
||||
public List<Affliction> Afflictions { get; set; }
|
||||
public bool ShouldImplode { get; set; } = false;
|
||||
public Attack SourceAttack { get; }
|
||||
public Character Character { get; set; }
|
||||
public Character Attacker { get; set; }
|
||||
|
||||
+1
-6
@@ -37,12 +37,7 @@ namespace Barotrauma.Abilities
|
||||
attackData.DamageMultiplier += addedDamageMultiplier;
|
||||
attackData.AddedPenetration += addedPenetration;
|
||||
|
||||
if (implode)
|
||||
{
|
||||
// might have issues, as the method used to be private and only used for pressure death
|
||||
attackData.Character?.Implode();
|
||||
}
|
||||
|
||||
attackData.ShouldImplode = implode;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+1
-2
@@ -19,11 +19,10 @@ namespace Barotrauma.Abilities
|
||||
moneyPerMission = abilityElement.GetAttributeInt("moneypermission", 0);
|
||||
}
|
||||
|
||||
protected override void ApplyEffect()
|
||||
protected override void ApplyEffect(AbilityObject abilityObject)
|
||||
{
|
||||
if (Character?.Info is CharacterInfo info)
|
||||
{
|
||||
|
||||
Character.GiveMoney(moneyPerMission * info.MissionsCompletedSinceDeath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,20 @@ namespace Barotrauma
|
||||
{
|
||||
wifiComponent.TeamID = TeamTag;
|
||||
}
|
||||
var idCard = item.GetComponent<Items.Components.IdCard>();
|
||||
if (idCard != null)
|
||||
{
|
||||
idCard.TeamID = TeamTag;
|
||||
idCard.SubmarineSpecificID = 0;
|
||||
}
|
||||
}
|
||||
|
||||
WayPoint subWaypoint =
|
||||
WayPoint.WayPointList.Find(wp => wp.Submarine == Submarine.MainSub && wp.SpawnType == SpawnType.Human && wp.AssignedJob == npc.Info.Job?.Prefab) ??
|
||||
WayPoint.WayPointList.Find(wp => wp.Submarine == Submarine.MainSub && wp.SpawnType == SpawnType.Human);
|
||||
if (subWaypoint != null)
|
||||
{
|
||||
npc.GiveIdCardTags(subWaypoint, createNetworkEvent: true);
|
||||
}
|
||||
#if SERVER
|
||||
GameMain.NetworkMember.CreateEntityEvent(npc, new object[] { NetEntityEvent.Type.AddToCrew, TeamTag, npc.Inventory.AllItems.Select(it => it.ID).ToArray() });
|
||||
|
||||
@@ -112,13 +112,13 @@ namespace Barotrauma
|
||||
}
|
||||
return prefab;
|
||||
}
|
||||
|
||||
|
||||
this.Prefabs = prefabIdentifiers
|
||||
.Select(tryFindPrefab)
|
||||
.Where(p => p != null)
|
||||
.ToImmutableArray();
|
||||
this.Commonness = commonness ?? this.Prefabs.Select(p => p.Commonness).Max();
|
||||
this.Probability = probability ?? this.Prefabs.Select(p => p.Probability).Max();
|
||||
this.Commonness = commonness ?? this.Prefabs.Select(p => p.Commonness).MaxOrNull() ?? 0.0f;
|
||||
this.Probability = probability ?? this.Prefabs.Select(p => p.Probability).MaxOrNull() ?? 0.0f;
|
||||
}
|
||||
|
||||
public SubEventPrefab(EventPrefab prefab, float commonness, float probability)
|
||||
|
||||
@@ -390,7 +390,7 @@ namespace Barotrauma
|
||||
|
||||
private bool DeadOrCaptured(Character character)
|
||||
{
|
||||
return character != null && !character.Removed && (character.IsDead || (character.LockHands && character.Submarine == Submarine.MainSub));
|
||||
return character == null || character.Removed || character.IsDead || (character.LockHands && character.Submarine == Submarine.MainSub);
|
||||
}
|
||||
|
||||
public override void End()
|
||||
|
||||
@@ -171,5 +171,21 @@ namespace Barotrauma.Extensions
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum element in a given enumerable, or null if there
|
||||
/// aren't any elements in the input.
|
||||
/// </summary>
|
||||
/// <param name="enumerable">Input collection</param>
|
||||
/// <returns>Maximum element or null</returns>
|
||||
public static T? MaxOrNull<T>(this IEnumerable<T> enumerable) where T : struct, IComparable<T>
|
||||
{
|
||||
T? retVal = null;
|
||||
foreach (T v in enumerable)
|
||||
{
|
||||
if (!retVal.HasValue || v.CompareTo(retVal.Value) > 0) { retVal = v; }
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,8 @@ namespace Barotrauma.Items.Components
|
||||
if ((picker.PickingItem == null || picker.PickingItem == item) && PickingTime <= float.MaxValue)
|
||||
{
|
||||
#if SERVER
|
||||
// Set active picker before creating the server event to make sure it's set correctly
|
||||
activePicker = picker;
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
pickingCoroutine = CoroutineManager.StartCoroutine(WaitForPick(picker, abilityPickingTime.Value));
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
get
|
||||
{
|
||||
Matrix bodyTransform = Matrix.CreateRotationZ(item.body.Rotation);
|
||||
Matrix bodyTransform = Matrix.CreateRotationZ(item.body == null ? MathHelper.ToRadians(item.Rotation) : item.body.Rotation);
|
||||
Vector2 flippedPos = barrelPos;
|
||||
if (item.body.Dir < 0.0f) { flippedPos.X = -flippedPos.X; }
|
||||
return Vector2.Transform(flippedPos, bodyTransform) * item.Scale;
|
||||
|
||||
@@ -202,7 +202,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
float percentageHealth = targetItem.Condition / targetItem.MaxCondition;
|
||||
|
||||
if (percentageHealth <= deconstructProduct.MinCondition || percentageHealth > deconstructProduct.MaxCondition) { return; }
|
||||
if (percentageHealth < deconstructProduct.MinCondition || percentageHealth > deconstructProduct.MaxCondition) { return; }
|
||||
|
||||
if (!(MapEntityPrefab.Find(null, deconstructProduct.ItemIdentifier) is ItemPrefab itemPrefab))
|
||||
{
|
||||
|
||||
@@ -347,22 +347,20 @@ namespace Barotrauma.Items.Components
|
||||
float outCondition = fabricatedItem.OutCondition;
|
||||
if (i < amountFittingContainer)
|
||||
{
|
||||
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, outputContainer.Inventory, fabricatedItem.TargetItem.Health * outCondition,
|
||||
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, outputContainer.Inventory, fabricatedItem.TargetItem.Health * outCondition, quality,
|
||||
onSpawned: (Item spawnedItem) =>
|
||||
{
|
||||
onItemSpawned(spawnedItem, tempUser);
|
||||
spawnedItem.Quality = quality;
|
||||
//reset the condition in case the max condition is higher than the prefab's due to e.g. quality modifiers
|
||||
spawnedItem.Condition = spawnedItem.MaxCondition * outCondition;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, item.Position, item.Submarine, fabricatedItem.TargetItem.Health * outCondition,
|
||||
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, item.Position, item.Submarine, fabricatedItem.TargetItem.Health * outCondition, quality,
|
||||
onSpawned: (Item spawnedItem) =>
|
||||
{
|
||||
onItemSpawned(spawnedItem, tempUser);
|
||||
spawnedItem.Quality = quality;
|
||||
//reset the condition in case the max condition is higher than the prefab's due to e.g. quality modifiers
|
||||
spawnedItem.Condition = spawnedItem.MaxCondition * outCondition;
|
||||
});
|
||||
|
||||
@@ -547,6 +547,11 @@ namespace Barotrauma.Items.Components
|
||||
//power transfer items (junction boxes, relays) don't deteriorate if they're no carrying any power
|
||||
if (Math.Abs(pt.CurrPowerConsumption) > 0.1f) { return true; }
|
||||
}
|
||||
else if (ic is PowerContainer pc)
|
||||
{
|
||||
//batteries don't deteriorate if they're not charging/discharging
|
||||
if (Math.Abs(pc.CurrPowerConsumption) > 0.1f || Math.Abs(pc.CurrPowerOutput) > 0.1f) { return true; }
|
||||
}
|
||||
else if (ic is Engine engine)
|
||||
{
|
||||
//engines don't deteriorate if they're not running
|
||||
@@ -555,7 +560,7 @@ namespace Barotrauma.Items.Components
|
||||
else if (ic is Pump pump)
|
||||
{
|
||||
//pumps don't deteriorate if they're not running
|
||||
if (Math.Abs(pump.FlowPercentage) > 1.0f && pump.IsActive) { return true; }
|
||||
if (Math.Abs(pump.FlowPercentage) > 1.0f && pump.IsActive && pump.HasPower) { return true; }
|
||||
}
|
||||
else if (ic is Reactor reactor)
|
||||
{
|
||||
|
||||
@@ -127,6 +127,8 @@ namespace Barotrauma.Items.Components
|
||||
if (source == null || target == null || target.Removed ||
|
||||
(source is Entity sourceEntity && sourceEntity.Removed))
|
||||
{
|
||||
source = null;
|
||||
target = null;
|
||||
IsActive = false;
|
||||
return;
|
||||
}
|
||||
|
||||
+16
-3
@@ -225,10 +225,23 @@ namespace Barotrauma.Items.Components
|
||||
//no electrocution in sub editor
|
||||
if (Screen.Selected == GameMain.SubEditorScreen) { return true; }
|
||||
|
||||
var powered = item.GetComponent<Powered>();
|
||||
if (powered != null)
|
||||
var reactor = item.GetComponent<Reactor>();
|
||||
if (reactor != null)
|
||||
{
|
||||
//unpowered panels can be rewired without a risk of electrical shock
|
||||
//reactors that arent generating power atm can be rewired without the risk of electrical shock
|
||||
if (MathUtils.NearlyEqual(reactor.CurrPowerConsumption, 0.0f)) { return true; }
|
||||
}
|
||||
var powerContainer = item.GetComponent<PowerContainer>();
|
||||
if (powerContainer != null)
|
||||
{
|
||||
//empty batteries/supercapacitors can be rewired without the risk of electrical shock
|
||||
//non-empty ones always have a chance of zapping the user
|
||||
if (powerContainer.Charge <= 0.0f) { return true; }
|
||||
}
|
||||
var powered = item.GetComponent<Powered>();
|
||||
if (powered != null && powerContainer == null)
|
||||
{
|
||||
//unpowered panels can be rewired without the risk of electrical shock
|
||||
if (powered.Voltage < 0.1f) { return true; }
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Barotrauma
|
||||
struct DeconstructItem
|
||||
{
|
||||
public readonly string ItemIdentifier;
|
||||
//minCondition does <= check, meaning that below or equeal to min condition will be skipped.
|
||||
//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.
|
||||
public readonly float MaxCondition;
|
||||
@@ -50,7 +50,6 @@ namespace Barotrauma
|
||||
ActivateButtonText = element.GetAttributeString("activatebuttontext", string.Empty);
|
||||
InfoText = element.GetAttributeString("infotext", string.Empty);
|
||||
InfoTextOnOtherItemMissing = element.GetAttributeString("infotextonotheritemmissing", string.Empty);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public bool ExcludeBroken { get; private set; }
|
||||
|
||||
private bool allowVariants = true;
|
||||
public bool AllowVariants { get; private set; } = true;
|
||||
|
||||
public RelationType Type
|
||||
{
|
||||
@@ -84,13 +84,13 @@ namespace Barotrauma
|
||||
{
|
||||
if (item == null) { return false; }
|
||||
if (excludedIdentifiers.Any(id => item.Prefab.Identifier == id || item.HasTag(id))) { return false; }
|
||||
return Identifiers.Any(id => item.Prefab.Identifier == id || item.HasTag(id) || (allowVariants && item.Prefab.VariantOf?.Identifier == id));
|
||||
return Identifiers.Any(id => item.Prefab.Identifier == id || item.HasTag(id) || (AllowVariants && item.Prefab.VariantOf?.Identifier == id));
|
||||
}
|
||||
public bool MatchesItem(ItemPrefab itemPrefab)
|
||||
{
|
||||
if (itemPrefab == null) { return false; }
|
||||
if (excludedIdentifiers.Any(id => itemPrefab.Identifier == id || itemPrefab.Tags.Contains(id))) { return false; }
|
||||
return Identifiers.Any(id => itemPrefab.Identifier == id || itemPrefab.Tags.Contains(id) || (allowVariants && itemPrefab.VariantOf?.Identifier == id));
|
||||
return Identifiers.Any(id => itemPrefab.Identifier == id || itemPrefab.Tags.Contains(id) || (AllowVariants && itemPrefab.VariantOf?.Identifier == id));
|
||||
}
|
||||
|
||||
public RelatedItem(string[] identifiers, string[] excludedIdentifiers)
|
||||
@@ -171,7 +171,7 @@ namespace Barotrauma
|
||||
new XAttribute("ignoreineditor", IgnoreInEditor),
|
||||
new XAttribute("excludebroken", ExcludeBroken),
|
||||
new XAttribute("targetslot", TargetSlot),
|
||||
new XAttribute("allowvariants", allowVariants));
|
||||
new XAttribute("allowvariants", AllowVariants));
|
||||
|
||||
if (excludedIdentifiers.Length > 0)
|
||||
{
|
||||
@@ -235,7 +235,7 @@ namespace Barotrauma
|
||||
RelatedItem ri = new RelatedItem(identifiers, excludedIdentifiers)
|
||||
{
|
||||
ExcludeBroken = element.GetAttributeBool("excludebroken", true),
|
||||
allowVariants = element.GetAttributeBool("allowvariants", true)
|
||||
AllowVariants = element.GetAttributeBool("allowvariants", true)
|
||||
};
|
||||
string typeStr = element.GetAttributeString("type", "");
|
||||
if (string.IsNullOrEmpty(typeStr))
|
||||
|
||||
@@ -510,14 +510,14 @@ namespace Barotrauma.MapCreatures.Behavior
|
||||
List<BallastFloraBranch> list = branches[hull];
|
||||
if (!list.Any(HasAcidEmitter))
|
||||
{
|
||||
BallastFloraBranch randomBranh = branches[hull].GetRandom();
|
||||
randomBranh.SpawningItem = true;
|
||||
BallastFloraBranch randomBranch = branches[hull].GetRandom();
|
||||
randomBranch.SpawningItem = true;
|
||||
|
||||
ItemPrefab prefab = ItemPrefab.Find(null, AttackItemPrefab);
|
||||
Entity.Spawner?.AddToSpawnQueue(prefab, Parent.Position + Offset + randomBranh.Position, Parent.Submarine, null, item =>
|
||||
Entity.Spawner?.AddToSpawnQueue(prefab, Parent.Position + Offset + randomBranch.Position, Parent.Submarine, onSpawned: item =>
|
||||
{
|
||||
randomBranh.AttackItem = item;
|
||||
randomBranh.SpawningItem = false;
|
||||
randomBranch.AttackItem = item;
|
||||
randomBranch.SpawningItem = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -213,9 +213,8 @@ namespace Barotrauma
|
||||
};
|
||||
PhysicsBody.FarseerBody.OnCollision += PhysicsBody_OnCollision;
|
||||
PhysicsBody.FarseerBody.OnSeparation += PhysicsBody_OnSeparation;
|
||||
PhysicsBody.FarseerBody.SetIsSensor(true);
|
||||
PhysicsBody.FarseerBody.SetIsSensor(element.GetAttributeBool("sensor", true));
|
||||
PhysicsBody.FarseerBody.BodyType = BodyType.Static;
|
||||
PhysicsBody.FarseerBody.BodyType = BodyType.Kinematic;
|
||||
|
||||
ColliderRadius = ConvertUnits.ToDisplayUnits(Math.Max(Math.Max(PhysicsBody.radius, PhysicsBody.width / 2.0f), PhysicsBody.height / 2.0f));
|
||||
|
||||
@@ -532,10 +531,9 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (triggerOnce)
|
||||
if (triggerOnce && triggeredOnce)
|
||||
{
|
||||
if (triggeredOnce) { return; }
|
||||
if (triggerers.Count > 0) { triggeredOnce = true; }
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (Entity triggerer in triggerers)
|
||||
@@ -577,6 +575,12 @@ namespace Barotrauma
|
||||
GameMain.GameScreen.Cam.Shake = Math.Max(GameMain.GameScreen.Cam.Shake, cameraShake);
|
||||
}
|
||||
}
|
||||
|
||||
if (triggerOnce && triggerers.Count > 0)
|
||||
{
|
||||
PhysicsBody.Enabled = false;
|
||||
triggeredOnce = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveDistantTriggerers(PhysicsBody physicsBody, HashSet<Entity> triggerers, Vector2 calculateDistanceTo)
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace Barotrauma
|
||||
public readonly Inventory Inventory;
|
||||
public readonly Submarine Submarine;
|
||||
public readonly float Condition;
|
||||
public readonly int Quality;
|
||||
|
||||
public bool SpawnIfInventoryFull = true;
|
||||
public bool IgnoreLimbSlots = false;
|
||||
@@ -33,28 +34,31 @@ namespace Barotrauma
|
||||
|
||||
private readonly Action<Item> onSpawned;
|
||||
|
||||
public ItemSpawnInfo(ItemPrefab prefab, Vector2 worldPosition, Action<Item> onSpawned, float? condition = null)
|
||||
public ItemSpawnInfo(ItemPrefab prefab, Vector2 worldPosition, Action<Item> onSpawned, float? condition = null, int? quality = null)
|
||||
{
|
||||
Prefab = prefab ?? throw new ArgumentException("ItemSpawnInfo prefab cannot be null.");
|
||||
Position = worldPosition;
|
||||
Condition = condition ?? prefab.Health;
|
||||
Quality = quality ?? 0;
|
||||
this.onSpawned = onSpawned;
|
||||
}
|
||||
|
||||
public ItemSpawnInfo(ItemPrefab prefab, Vector2 position, Submarine sub, Action<Item> onSpawned, float? condition = null)
|
||||
public ItemSpawnInfo(ItemPrefab prefab, Vector2 position, Submarine sub, Action<Item> onSpawned, float? condition = null, int? quality = null)
|
||||
{
|
||||
Prefab = prefab ?? throw new ArgumentException("ItemSpawnInfo prefab cannot be null.");
|
||||
Position = position;
|
||||
Submarine = sub;
|
||||
Condition = condition ?? prefab.Health;
|
||||
Quality = quality ?? 0;
|
||||
this.onSpawned = onSpawned;
|
||||
}
|
||||
|
||||
public ItemSpawnInfo(ItemPrefab prefab, Inventory inventory, Action<Item> onSpawned, float? condition = null)
|
||||
public ItemSpawnInfo(ItemPrefab prefab, Inventory inventory, Action<Item> onSpawned, float? condition = null, int? quality = null)
|
||||
{
|
||||
Prefab = prefab ?? throw new ArgumentException("ItemSpawnInfo prefab cannot be null.");
|
||||
Inventory = inventory;
|
||||
Condition = condition ?? prefab.Health;
|
||||
Quality = quality ?? 0;
|
||||
this.onSpawned = onSpawned;
|
||||
}
|
||||
|
||||
@@ -73,7 +77,8 @@ namespace Barotrauma
|
||||
}
|
||||
spawnedItem = new Item(Prefab, Vector2.Zero, null)
|
||||
{
|
||||
Condition = Condition
|
||||
Condition = Condition,
|
||||
Quality = Quality
|
||||
};
|
||||
var slot = Slot != InvSlotType.None ? Slot.ToEnumerable() : spawnedItem.AllowedSlots;
|
||||
if (!Inventory.Owner.Removed && !Inventory.TryPutItem(spawnedItem, null, slot))
|
||||
@@ -94,7 +99,11 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
spawnedItem = new Item(Prefab, Position, Submarine);
|
||||
spawnedItem = new Item(Prefab, Position, Submarine)
|
||||
{
|
||||
Condition = Condition,
|
||||
Quality = Quality
|
||||
};
|
||||
}
|
||||
return spawnedItem;
|
||||
}
|
||||
@@ -241,7 +250,7 @@ namespace Barotrauma
|
||||
return "EntitySpawner";
|
||||
}
|
||||
|
||||
public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 worldPosition, float? condition = null, Action<Item> onSpawned = null)
|
||||
public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 worldPosition, float? condition = null, int? quality = null, Action<Item> onSpawned = null)
|
||||
{
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||
if (itemPrefab == null)
|
||||
@@ -251,10 +260,10 @@ namespace Barotrauma
|
||||
GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue1:ItemPrefabNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
}
|
||||
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition, onSpawned, condition));
|
||||
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition, onSpawned, condition, quality));
|
||||
}
|
||||
|
||||
public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 position, Submarine sub, float? condition = null, Action<Item> onSpawned = null)
|
||||
public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 position, Submarine sub, float? condition = null, int? quality = null, Action<Item> onSpawned = null)
|
||||
{
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||
if (itemPrefab == null)
|
||||
@@ -264,10 +273,10 @@ namespace Barotrauma
|
||||
GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue2:ItemPrefabNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
}
|
||||
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub, onSpawned, condition));
|
||||
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub, onSpawned, condition, quality));
|
||||
}
|
||||
|
||||
public void AddToSpawnQueue(ItemPrefab itemPrefab, Inventory inventory, float? condition = null, Action<Item> onSpawned = null, bool spawnIfInventoryFull = true, bool ignoreLimbSlots = false, InvSlotType slot = InvSlotType.None)
|
||||
public void AddToSpawnQueue(ItemPrefab itemPrefab, Inventory inventory, float? condition = null, int? quality = null, Action<Item> onSpawned = null, bool spawnIfInventoryFull = true, bool ignoreLimbSlots = false, InvSlotType slot = InvSlotType.None)
|
||||
{
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||
if (itemPrefab == null)
|
||||
@@ -277,7 +286,7 @@ namespace Barotrauma
|
||||
GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue3:ItemPrefabNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
}
|
||||
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory, onSpawned, condition)
|
||||
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory, onSpawned, condition, quality)
|
||||
{
|
||||
SpawnIfInventoryFull = spawnIfInventoryFull,
|
||||
IgnoreLimbSlots = ignoreLimbSlots,
|
||||
@@ -395,10 +404,6 @@ namespace Barotrauma
|
||||
{
|
||||
CreateNetworkEventProjSpecific(spawnedEntity, false);
|
||||
}
|
||||
if (spawnedEntity is Item item)
|
||||
{
|
||||
item.Condition = ((ItemSpawnInfo)entitySpawnInfo).Condition;
|
||||
}
|
||||
entitySpawnInfo.OnSpawned(spawnedEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,7 +244,7 @@ namespace Barotrauma
|
||||
cam.TargetPos = targetPos;
|
||||
}
|
||||
|
||||
cam.MoveCamera((float)deltaTime, allowZoom: GUI.MouseOn == null);
|
||||
cam.MoveCamera((float)deltaTime, allowZoom: GUI.MouseOn == null && !Inventory.IsMouseOnInventory);
|
||||
#endif
|
||||
|
||||
foreach (Submarine sub in Submarine.Loaded)
|
||||
|
||||
Reference in New Issue
Block a user