From 2554e171898e211c8800f6f4dca68b2f4315a853 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Mon, 29 Apr 2019 21:08:32 +0300 Subject: [PATCH] (621326f05) Don't flee when taking damage if part of a swarm. --- Barotrauma/BarotraumaClient/Launch_Barotrauma | 2 +- .../BarotraumaClient/LinuxClient.csproj | 3 - .../Source/Characters/Animation/Ragdoll.cs | 18 +++-- .../Source/Characters/Character.cs | 3 +- .../Source/Characters/CharacterHUD.cs | 4 +- .../Source/Items/CharacterInventory.cs | 3 +- .../Source/Items/Inventory.cs | 20 ++---- .../BarotraumaClient/Source/Map/Structure.cs | 17 ----- .../Source/Sounds/SoundPlayer.cs | 2 +- Barotrauma/BarotraumaServer/Server.csproj | 2 +- .../Source/Characters/AI/EnemyAIController.cs | 66 +++++++++++-------- .../Animation/HumanoidAnimController.cs | 3 +- .../Source/Characters/Character.cs | 6 +- .../Source/Events/Missions/MonsterMission.cs | 29 ++++++-- .../BarotraumaShared/Source/Map/Structure.cs | 18 +++++ .../Source/Networking/EntitySpawner.cs | 4 +- 16 files changed, 111 insertions(+), 89 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Launch_Barotrauma b/Barotrauma/BarotraumaClient/Launch_Barotrauma index 4e95158fd..8792fad24 100644 --- a/Barotrauma/BarotraumaClient/Launch_Barotrauma +++ b/Barotrauma/BarotraumaClient/Launch_Barotrauma @@ -1,3 +1,3 @@ #!/bin/sh -./Barotrauma +exec mono "./Barotrauma.exe" MONO_LOG_LEVEL=debug "$@" diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index c74cd30c3..411dec235 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -186,9 +186,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs index 2e11c7af2..667d29d62 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs @@ -98,7 +98,7 @@ namespace Barotrauma if (distSqrd > 10.0f || !character.AllowInput) { Collider.TargetRotation = newRotation; - SetPosition(newPosition, lerp: distSqrd < 5.0f, ignorePlatforms: false); + SetPosition(newPosition, lerp: distSqrd < 5.0f); } else { @@ -238,16 +238,20 @@ namespace Barotrauma } float errorMagnitude = positionError.Length(); - if (errorMagnitude > 0.5f) - { - character.MemLocalState.Clear(); - SetPosition(serverPos.Position, lerp: true, ignorePlatforms: false); - } - else if (errorMagnitude > 0.01f) + if (errorMagnitude > 0.01f) { Collider.TargetPosition = Collider.SimPosition + positionError; Collider.TargetRotation = Collider.Rotation + rotationError; Collider.MoveToTargetPosition(lerp: true); + if (errorMagnitude > 0.5f) + { + character.MemLocalState.Clear(); + foreach (Limb limb in Limbs) + { + limb.body.TargetPosition = limb.body.SimPosition + positionError; + limb.body.MoveToTargetPosition(lerp: true); + } + } } } diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Character.cs b/Barotrauma/BarotraumaClient/Source/Characters/Character.cs index b4e831e77..2eff39aa6 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Character.cs @@ -46,7 +46,8 @@ namespace Barotrauma if (controlled == value) return; controlled = value; if (controlled != null) controlled.Enabled = true; - CharacterHealth.OpenHealthWindow = null; + CharacterHealth.OpenHealthWindow = null; + } } diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs index e180f44e6..441ae6a6e 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs @@ -85,8 +85,7 @@ namespace Barotrauma { if (character.Inventory != null) { - if (!character.LockHands && character.Stun < 0.1f && - (character.SelectedConstruction == null || character.SelectedConstruction.GetComponent() == null)) + if (!character.LockHands && character.Stun < 0.1f) { character.Inventory.Update(deltaTime, cam); } @@ -321,7 +320,6 @@ namespace Barotrauma } if (character.Inventory != null && !character.LockHands) { - character.Inventory.Locked = (character.SelectedConstruction != null && character.SelectedConstruction.GetComponent() != null); character.Inventory.DrawOwn(spriteBatch); character.Inventory.CurrentLayout = CharacterHealth.OpenHealthWindow == null && character.SelectedCharacter == null ? CharacterInventory.Layout.Default : diff --git a/Barotrauma/BarotraumaClient/Source/Items/CharacterInventory.cs b/Barotrauma/BarotraumaClient/Source/Items/CharacterInventory.cs index 0ea60b4a5..71b3d07d0 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/CharacterInventory.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/CharacterInventory.cs @@ -793,7 +793,7 @@ namespace Barotrauma base.Draw(spriteBatch); - if (hideButton != null && hideButton.Visible && !Locked) + if (hideButton != null && hideButton.Visible) { hideButton.DrawManually(spriteBatch, alsoChildren: true); } @@ -835,7 +835,6 @@ namespace Barotrauma color = Color.White; highlightedQuickUseSlot = slots[i]; } - if (Locked) { color *= 0.3f; } var quickUseIndicator = Items[i].AllowedSlots.Any(a => a == InvSlotType.Any) ? EquipIndicator : DropIndicator; diff --git a/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs b/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs index e3c4ea985..8fb30030a 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs @@ -820,9 +820,8 @@ namespace Barotrauma else { Sprite slotSprite = slot.SlotSprite ?? slotSpriteSmall; - Color slotColor = slot.IsHighlighted ? Color.White : Color.White * 0.8f; - if (inventory != null && inventory.Locked) { slotColor = Color.Gray * 0.5f; } - spriteBatch.Draw(slotSprite.Texture, rect, slotSprite.SourceRect, slotColor); + + spriteBatch.Draw(slotSprite.Texture, rect, slotSprite.SourceRect, slot.IsHighlighted ? Color.White : Color.White * 0.8f); if (item != null && drawItem) { @@ -874,17 +873,14 @@ namespace Barotrauma } indicatorSprite.Draw(spriteBatch, containedIndicatorArea.Center.ToVector2(), - (inventory != null && inventory.Locked) ? Color.DarkGray * 0.5f : Color.DarkGray * 0.9f, + Color.DarkGray * 0.9f, origin: indicatorSprite.size / 2, rotate: 0.0f, scale: indicatorScale); - - Color indicatorColor = ToolBox.GradientLerp(containedState, Color.Red, Color.Orange, Color.Green); - if (inventory != null && inventory.Locked) { indicatorColor *= 0.5f; } - + spriteBatch.Draw(indicatorSprite.Texture, containedIndicatorArea.Center.ToVector2(), sourceRectangle: new Rectangle(indicatorSprite.SourceRect.Location, new Point((int)(indicatorSprite.SourceRect.Width * containedState), indicatorSprite.SourceRect.Height)), - color: indicatorColor, + color: ToolBox.GradientLerp(containedState, Color.Red, Color.Orange, Color.Green), rotation: 0.0f, origin: indicatorSprite.size / 2, scale: indicatorScale, @@ -924,7 +920,6 @@ namespace Barotrauma } Color spriteColor = sprite == item.Sprite ? item.GetSpriteColor() : item.GetInventoryIconColor(); - if (inventory != null && inventory.Locked) { spriteColor *= 0.5f; } if (CharacterHealth.OpenHealthWindow != null && !item.UseInHealthInterface) { spriteColor = Color.Lerp(spriteColor, Color.TransparentBlack, 0.5f); @@ -936,10 +931,7 @@ namespace Barotrauma sprite.Draw(spriteBatch, itemPos, spriteColor, rotation, scale); } - if (inventory != null && - !inventory.Locked && - Character.Controlled?.Inventory == inventory && - slot.QuickUseKey != Keys.None) + if (inventory != null && Character.Controlled?.Inventory == inventory && slot.QuickUseKey != Keys.None) { GUI.DrawString(spriteBatch, rect.Location.ToVector2(), slot.QuickUseKey.ToString().Substring(1, 1), diff --git a/Barotrauma/BarotraumaClient/Source/Map/Structure.cs b/Barotrauma/BarotraumaClient/Source/Map/Structure.cs index 99b7bbedd..08a9b5ae0 100644 --- a/Barotrauma/BarotraumaClient/Source/Map/Structure.cs +++ b/Barotrauma/BarotraumaClient/Source/Map/Structure.cs @@ -1,9 +1,6 @@ using Barotrauma.Extensions; using Barotrauma.Lights; using Barotrauma.Networking; -using FarseerPhysics; -using FarseerPhysics.Dynamics; -using FarseerPhysics.Dynamics.Contacts; using Lidgren.Network; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; @@ -168,20 +165,6 @@ namespace Barotrauma { Vector2 pos = ConvertUnits.ToDisplayUnits(f2.Body.Position); - int section = FindSectionIndex(pos); - if (section > -1) - { - Vector2 normal = contact.Manifold.LocalNormal; - - float impact = Vector2.Dot(f2.Body.LinearVelocity, -normal) * f2.Body.Mass * 0.1f; - if (impact > 10.0f) - { - SoundPlayer.PlayDamageSound("StructureBlunt", impact, SectionPosition(section, true), tags: Tags); - } - } - } - } - public override bool IsVisible(Rectangle worldView) { Rectangle worldRect = WorldRect; diff --git a/Barotrauma/BarotraumaClient/Source/Sounds/SoundPlayer.cs b/Barotrauma/BarotraumaClient/Source/Sounds/SoundPlayer.cs index 515bc987a..3c1705000 100644 --- a/Barotrauma/BarotraumaClient/Source/Sounds/SoundPlayer.cs +++ b/Barotrauma/BarotraumaClient/Source/Sounds/SoundPlayer.cs @@ -238,7 +238,7 @@ namespace Barotrauma } float ambienceVolume = 0.8f; - if (Character.Controlled != null && !Character.Controlled.Removed) + if (Character.Controlled != null) { AnimController animController = Character.Controlled.AnimController; if (animController.HeadInWater) diff --git a/Barotrauma/BarotraumaServer/Server.csproj b/Barotrauma/BarotraumaServer/Server.csproj index bc97ad59e..3647a5b6d 100644 --- a/Barotrauma/BarotraumaServer/Server.csproj +++ b/Barotrauma/BarotraumaServer/Server.csproj @@ -216,7 +216,7 @@ - + PreserveNewest diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs index eac638a27..3c5e54192 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs @@ -320,8 +320,9 @@ namespace Barotrauma { State = AIState.Idle; } - else if (Character.Health < fleeHealthThreshold) + else if (Character.Health < fleeHealthThreshold && SwarmBehavior == null) { + // Don't flee from damage if in a swarm. State = AIState.Escape; } else if (targetingPriority != null) @@ -493,7 +494,7 @@ namespace Barotrauma } else { - if (!IsProperlyLatchedOnSub) + if (!IsLatchedOnSub) { UpdateWallTarget(); } @@ -552,7 +553,7 @@ namespace Barotrauma { WallSection section = wallTarget.Structure.GetSection(wallTarget.SectionIndex); Vector2 targetPos = wallTarget.Structure.SectionPosition(wallTarget.SectionIndex, true); - if (section?.gap != null && section.gap.IsRoomToRoom && SteerThroughGap(wallTarget.Structure, section, targetPos, deltaTime)) + if (section?.gap != null && SteerThroughGap(wallTarget.Structure, section, targetPos, deltaTime)) { return; } @@ -791,7 +792,6 @@ namespace Barotrauma { UpdateLimbAttack(deltaTime, AttackingLimb, attackSimPos, distance); } - return false; } private bool SteerThroughGap(Structure wall, WallSection section, Vector2 targetWorldPos, float deltaTime) @@ -1048,35 +1048,38 @@ namespace Barotrauma #region Targeting private bool IsLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub; - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - //goes through all the AItargets, evaluates how preferable it is to attack the target, //whether the Character can see/hear the target and chooses the most preferable target within //sight/hearing range public AITarget UpdateTargets(Character character, out TargetingPriority priority) { - if (IsProperlyLatchedOnSub) + if (IsLatchedOnSub) { - // If attached to a valid target, just keep the target. - // Priority not used in this case. - priority = null; - return SelectedAiTarget; + var wall = SelectedAiTarget.Entity as Structure; + // The target is not a wall or it's not the same as we are attached to -> release + bool releaseTarget = wall == null || !wall.Bodies.Contains(LatchOntoAI.AttachJoints[0].BodyB); + if (!releaseTarget) + { + for (int i = 0; i < wall.Sections.Length; i++) + { + if (CanPassThroughHole(wall, i)) + { + releaseTarget = true; + } + } + } + if (releaseTarget) + { + SelectedAiTarget = null; + LatchOntoAI.DeattachFromBody(); + } + else if (SelectedAiTarget.Entity == wallTarget?.Structure) + { + // If attached to a valid target, just keep the target. + // Priority not used in this case. + priority = null; + return SelectedAiTarget; + } } AITarget newTarget = null; priority = null; @@ -1159,7 +1162,7 @@ namespace Barotrauma else if (target.Entity != null) { //skip the target if it's a room and the character is already inside a sub - if (character.CurrentHull != null && target.Entity is Hull) continue; + if (character.CurrentHull != null && target.Entity is Hull) { continue; } Door door = null; if (target.Entity is Item item) @@ -1188,6 +1191,13 @@ namespace Barotrauma // Ignore structures that doesn't have a body (not walls) continue; } + if (s.IsPlatform) + { + continue; + } + float wallMaxHealth = 400; // Anything more than this is ignored -> 200 = 1 + // Prefer weaker targets. + valueModifier = MathHelper.Lerp(2, 0, MathHelper.Clamp(s.Health / wallMaxHealth, 0, 1)); // Ignore walls when inside. valueModifier = character.CurrentHull == null ? 1 : 0; if (aggressiveBoarding) diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs index 3530df734..5de8c9140 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs @@ -560,8 +560,7 @@ namespace Barotrauma //TODO: take into account that the feet aren't necessarily in CurrentHull //full slowdown (1.5f) when water is up to the torso surfaceY = ConvertUnits.ToSimUnits(currentHull.Surface); - float bottomPos = Math.Max(colliderPos.Y, currentHull.Rect.Y - currentHull.Rect.Height); - slowdownAmount = MathHelper.Clamp((surfaceY - bottomPos) / TorsoPosition.Value, 0.0f, 1.0f) * 1.5f; + slowdownAmount = MathHelper.Clamp((surfaceY - colliderPos.Y) / TorsoPosition.Value, 0.0f, 1.0f) * 1.5f; } float maxSpeed = Math.Max(TargetMovement.Length() - slowdownAmount, 1.0f); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index d3dcbc16b..435f0fd7d 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -2555,9 +2555,11 @@ namespace Barotrauma GameMain.GameSession?.CrewManager?.RemoveCharacter(this); #endif - CharacterList.Remove(this); +#if CLIENT + GameMain.GameSession?.CrewManager?.RemoveCharacter(this); +#endif - if (Controlled == this) { Controlled = null; } + CharacterList.Remove(this); if (Inventory != null) { diff --git a/Barotrauma/BarotraumaShared/Source/Events/Missions/MonsterMission.cs b/Barotrauma/BarotraumaShared/Source/Events/Missions/MonsterMission.cs index 01905d2cf..6e8445416 100644 --- a/Barotrauma/BarotraumaShared/Source/Events/Missions/MonsterMission.cs +++ b/Barotrauma/BarotraumaShared/Source/Events/Missions/MonsterMission.cs @@ -34,14 +34,33 @@ namespace Barotrauma { Level.Loaded.TryGetInterestingPosition(true, Level.PositionType.MainPath, Level.Loaded.Size.X * 0.3f, out Vector2 spawnPos); - bool isClient = GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient; + //bool isClient = GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient; + //for (int i = 0; i < monsterCount; i++) + //{ + // monsters.Add(Character.Create(monsterFile, spawnPos, ToolBox.RandomSeed(8), null, isClient, true, false)); + //} + //monsters.ForEach(m => m.Enabled = false); + //SwarmBehavior.CreateSwarm(monsters.Cast()); + //sonarPositions.Add(spawnPos); + + float offsetAmount = 500; for (int i = 0; i < monsterCount; i++) { - monsters.Add(Character.Create(monsterFile, spawnPos, ToolBox.RandomSeed(8), null, isClient, true, false)); + CoroutineManager.InvokeAfter(() => + { + bool isClient = GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient; + var monster = Character.Create(monsterFile, spawnPos + Rand.Vector(offsetAmount, Rand.RandSync.Server), i.ToString(), null, isClient, true, true); + monster.Enabled = false; + monsters.Add(monster); + if (monsters.Count == monsterCount) + { + //this will do nothing if the monsters have no swarm behavior defined, + //otherwise it'll make the spawned characters act as a swarm + SwarmBehavior.CreateSwarm(monsters.Cast()); + sonarPositions.Add(spawnPos); + } + }, Rand.Range(0f, monsterCount / 2, Rand.RandSync.Server)); } - monsters.ForEach(m => m.Enabled = false); - SwarmBehavior.CreateSwarm(monsters.Cast()); - sonarPositions.Add(spawnPos); } public override void Update(float deltaTime) diff --git a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs index 38dcb8a64..59d65255f 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs @@ -635,6 +635,24 @@ namespace Barotrauma var character = ((Limb)f2.Body.UserData).character; if (character.DisableImpactDamageTimer > 0.0f || ((Limb)f2.Body.UserData).Mass < 100.0f) return true; } + + if (!Prefab.Platform && Prefab.StairDirection == Direction.None) + { + Vector2 pos = ConvertUnits.ToDisplayUnits(f2.Body.Position); + + int section = FindSectionIndex(pos); + if (section > -1) + { + Vector2 normal = contact.Manifold.LocalNormal; + + float impact = Vector2.Dot(f2.Body.LinearVelocity, -normal) * f2.Body.Mass * 0.1f; + if (impact < 10.0f) return true; +#if CLIENT + SoundPlayer.PlayDamageSound("StructureBlunt", impact, SectionPosition(section, true), tags: Tags); +#endif + AddDamage(section, impact); + } + } OnImpactProjSpecific(f1, f2, contact); diff --git a/Barotrauma/BarotraumaShared/Source/Networking/EntitySpawner.cs b/Barotrauma/BarotraumaShared/Source/Networking/EntitySpawner.cs index e89da30e1..c2cd7710d 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/EntitySpawner.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/EntitySpawner.cs @@ -102,7 +102,7 @@ namespace Barotrauma { string errorMsg = "Attempted to add a null item to entity spawn queue.\n" + Environment.StackTrace; DebugConsole.ThrowError(errorMsg); - GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue1:ItemPrefabNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); + GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue3:ItemPrefabNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); return; } spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition, condition)); @@ -115,7 +115,7 @@ namespace Barotrauma { string errorMsg = "Attempted to add a null item to entity spawn queue.\n" + Environment.StackTrace; DebugConsole.ThrowError(errorMsg); - GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue2:ItemPrefabNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); + GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue3:ItemPrefabNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); return; } spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub, condition));