Esempio n. 1
0
        public void AddFireSource(FireSource fireSource)
        {
            fireSources.Add(fireSource);

            if (GameMain.Server != null)
            {
                GameMain.Server.CreateEntityEvent(this);
            }
        }
Esempio n. 2
0
        public void RemoveFire(FireSource fire)
        {
            FireSources.Remove(fire);

            if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer && !Removed && !IdFreed)
            {
                GameMain.NetworkMember.CreateEntityEvent(this);
            }
        }
Esempio n. 3
0
        public void RemoveFire(FireSource fire)
        {
            fireSources.Remove(fire);

            if (GameMain.Server != null)
            {
                GameMain.Server.CreateEntityEvent(this);
            }
        }
Esempio n. 4
0
        public void AddFireSource(FireSource fireSource)
        {
            FireSources.Add(fireSource);

            if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer && !IdFreed)
            {
                GameMain.NetworkMember.CreateEntityEvent(this);
            }
        }
Esempio n. 5
0
        private bool CheckOverLap(FireSource fireSource)
        {
            if (this is DummyFireSource != fireSource is DummyFireSource)
            {
                return(false);
            }

            return(!(position.X > fireSource.position.X + fireSource.size.X ||
                     position.X + size.X < fireSource.position.X));
        }
        public override void Update(float deltaTime)
        {
            if (isFinished)
            {
                return;
            }
            var targets = ParentEvent.GetTargets(TargetTag);

            foreach (var target in targets)
            {
                Vector2 pos = target.WorldPosition;

                var newFire = new FireSource(pos);
                newFire.Size = new Vector2(Size, Size);
            }
            isFinished = true;
        }
Esempio n. 7
0
        private void UpdateFires(Character character, float deltaTime)
        {
            createFireSourceTimer += deltaTime;
            if (fakeFireSources.Count < MaxFakeFireSources &&
                character.Submarine != null &&
                createFireSourceTimer > MathHelper.Lerp(maxFakeFireSourceInterval, minFakeFireSourceInterval, Strength / 100.0f))
            {
                Hull fireHull = Hull.hullList.GetRandom(h => h.Submarine == character.Submarine);

                fakeFireSources.Add(new FakeFireSource()
                {
                    Size     = Vector2.One * 20.0f,
                    Hull     = fireHull,
                    Position = new Vector2(Rand.Range(0.0f, fireHull.Rect.Width), 30.0f),
                    LifeTime = MathHelper.Lerp(10.0f, 100.0f, Strength / 100.0f)
                });
                createFireSourceTimer = 0.0f;
            }

            foreach (FakeFireSource fakeFireSource in fakeFireSources)
            {
                if (fakeFireSource.Hull.Surface > fakeFireSource.Hull.Rect.Y - fakeFireSource.Hull.Rect.Height + fakeFireSource.Position.Y)
                {
                    fakeFireSource.LifeTime -= deltaTime * 10.0f;
                }

                fakeFireSource.LifeTime -= deltaTime;
                float growAmount = deltaTime * 5.0f;
                fakeFireSource.Size.X    += growAmount;
                fakeFireSource.Position.X = MathHelper.Clamp(fakeFireSource.Position.X - growAmount / 2.0f, 0.0f, fakeFireSource.Hull.Rect.Width);
                fakeFireSource.Position.Y = MathHelper.Clamp(fakeFireSource.Position.Y, 0.0f, fakeFireSource.Hull.Rect.Height);
                fakeFireSource.Size.X     = Math.Min(fakeFireSource.Hull.Rect.Width - fakeFireSource.Position.X, fakeFireSource.Size.X);
                fakeFireSource.Size.Y     = Math.Min(fakeFireSource.Hull.Rect.Height - fakeFireSource.Position.Y, fakeFireSource.Size.Y);

                FireSource.EmitParticles(
                    fakeFireSource.Size,
                    fakeFireSource.Hull.WorldRect.Location.ToVector2() + fakeFireSource.Position - Vector2.UnitY * fakeFireSource.Hull.Rect.Height,
                    fakeFireSource.Hull,
                    0.5f);
            }

            fakeFireSources.RemoveAll(fs => fs.LifeTime <= 0.0f);
        }
Esempio n. 8
0
        protected void Apply(float deltaTime, Entity entity, List <ISerializableEntity> targets)
        {
            Hull hull = null;

            if (entity is Character)
            {
                hull = ((Character)entity).AnimController.CurrentHull;
            }
            else if (entity is Item)
            {
                hull = ((Item)entity).CurrentHull;
            }

            foreach (ISerializableEntity serializableEntity in targets)
            {
                if (!(serializableEntity is Item item))
                {
                    continue;
                }

                Character targetCharacter = targets.FirstOrDefault(t => t is Character character && !character.Removed) as Character;
                if (targetCharacter == null)
                {
                    foreach (var target in targets)
                    {
                        if (target is Limb limb && limb.character != null && !limb.character.Removed)
                        {
                            targetCharacter = ((Limb)target).character;
                        }
                    }
                }
                for (int i = 0; i < useItemCount; i++)
                {
                    if (item.Removed)
                    {
                        continue;
                    }
                    item.Use(deltaTime, targetCharacter, targets.FirstOrDefault(t => t is Limb) as Limb);
                }
            }

            if (removeItem)
            {
                foreach (Item item in targets.Where(t => t is Item).Cast <Item>())
                {
                    Entity.Spawner?.AddToRemoveQueue(item);
                }
            }

            if (duration > 0.0f)
            {
                DurationListElement element = new DurationListElement
                {
                    Parent  = this,
                    Timer   = duration,
                    Entity  = entity,
                    Targets = targets
                };

                DurationList.Add(element);
            }
            else
            {
                foreach (ISerializableEntity target in targets)
                {
                    if (target is Entity targetEntity)
                    {
                        if (targetEntity.Removed)
                        {
                            continue;
                        }
                    }

                    for (int i = 0; i < propertyNames.Length; i++)
                    {
                        if (target == null || target.SerializableProperties == null ||
                            !target.SerializableProperties.TryGetValue(propertyNames[i], out SerializableProperty property))
                        {
                            continue;
                        }
                        ApplyToProperty(target, property, propertyEffects[i], deltaTime);
                    }
                }
            }

            if (explosion != null && entity != null)
            {
                explosion.Explode(entity.WorldPosition, damageSource: entity, attacker: user);
            }

            foreach (ISerializableEntity target in targets)
            {
                foreach (Affliction affliction in Afflictions)
                {
                    Affliction multipliedAffliction = affliction;
                    if (!disableDeltaTime)
                    {
                        multipliedAffliction = affliction.CreateMultiplied(deltaTime);
                    }

                    if (target is Character character)
                    {
                        character.LastDamageSource = entity;
                        foreach (Limb limb in character.AnimController.Limbs)
                        {
                            limb.character.DamageLimb(entity.WorldPosition, limb, new List <Affliction>()
                            {
                                multipliedAffliction
                            }, stun: 0.0f, playSound: false, attackImpulse: 0.0f, attacker: affliction.Source);
                            //only apply non-limb-specific afflictions to the first limb
                            if (!affliction.Prefab.LimbSpecific)
                            {
                                break;
                            }
                        }
                    }
                    else if (target is Limb limb)
                    {
                        limb.character.DamageLimb(entity.WorldPosition, limb, new List <Affliction>()
                        {
                            multipliedAffliction
                        }, stun: 0.0f, playSound: false, attackImpulse: 0.0f, attacker: affliction.Source);
                    }
                }

                foreach (Pair <string, float> reduceAffliction in ReduceAffliction)
                {
                    float     reduceAmount    = disableDeltaTime ? reduceAffliction.Second : reduceAffliction.Second * deltaTime;
                    Limb      targetLimb      = null;
                    Character targetCharacter = null;
                    if (target is Character character)
                    {
                        targetCharacter = character;
                    }
                    else if (target is Limb limb)
                    {
                        targetLimb      = limb;
                        targetCharacter = limb.character;
                    }
                    if (targetCharacter != null)
                    {
                        float prevVitality = targetCharacter.Vitality;
                        targetCharacter.CharacterHealth.ReduceAffliction(targetLimb, reduceAffliction.First, reduceAmount);
#if SERVER
                        GameMain.Server.KarmaManager.OnCharacterHealthChanged(targetCharacter, user, prevVitality - targetCharacter.Vitality);
#endif
                    }
                }
            }

            if (FireSize > 0.0f && entity != null)
            {
                var fire = new FireSource(entity.WorldPosition, hull);
                fire.Size = new Vector2(FireSize, fire.Size.Y);
            }

            bool isNotClient = GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient;
            if (isNotClient && entity != null && Entity.Spawner != null) //clients are not allowed to spawn items
            {
                foreach (ItemSpawnInfo itemSpawnInfo in spawnItems)
                {
                    switch (itemSpawnInfo.SpawnPosition)
                    {
                    case ItemSpawnInfo.SpawnPositionType.This:
                        Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, entity.WorldPosition);
                        break;

                    case ItemSpawnInfo.SpawnPositionType.ThisInventory:
                    {
                        if (entity is Character character)
                        {
                            if (character.Inventory != null && character.Inventory.Items.Any(it => it == null))
                            {
                                Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, character.Inventory);
                            }
                        }
                        else if (entity is Item item)
                        {
                            var inventory = item?.GetComponent <ItemContainer>()?.Inventory;
                            if (inventory != null && inventory.Items.Any(it => it == null))
                            {
                                Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, inventory);
                            }
                        }
                    }
                    break;

                    case ItemSpawnInfo.SpawnPositionType.ContainedInventory:
                    {
                        Inventory thisInventory = null;
                        if (entity is Character character)
                        {
                            thisInventory = character.Inventory;
                        }
                        else if (entity is Item item)
                        {
                            thisInventory = item?.GetComponent <ItemContainer>()?.Inventory;
                        }
                        if (thisInventory != null)
                        {
                            foreach (Item item in thisInventory.Items)
                            {
                                if (item == null)
                                {
                                    continue;
                                }
                                Inventory containedInventory = item.GetComponent <ItemContainer>()?.Inventory;
                                if (containedInventory == null || !containedInventory.Items.Any(i => i == null))
                                {
                                    continue;
                                }
                                Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, containedInventory);
                                break;
                            }
                        }
                    }
                    break;
                    }
                }
            }

            ApplyProjSpecific(deltaTime, entity, targets, hull);
        }
Esempio n. 9
0
        protected void Apply(float deltaTime, Entity entity, List <IPropertyObject> targets)
        {
#if CLIENT
            if (sound != null)
            {
                sound.Play(1.0f, 1000.0f, entity.WorldPosition);
            }
#endif

            if (useItem)
            {
                foreach (Item item in targets.FindAll(t => t is Item).Cast <Item>())
                {
                    item.Use(deltaTime, targets.FirstOrDefault(t => t is Character) as Character);
                }
            }

            foreach (IPropertyObject target in targets)
            {
                for (int i = 0; i < propertyNames.Length; i++)
                {
                    ObjectProperty property;

                    if (!target.ObjectProperties.TryGetValue(propertyNames[i], out property))
                    {
                        continue;
                    }

                    if (duration > 0.0f)
                    {
                        CoroutineManager.StartCoroutine(
                            ApplyToPropertyOverDuration(duration, property, propertyEffects[i]), "statuseffect");
                    }
                    else
                    {
                        ApplyToProperty(property, propertyEffects[i], deltaTime);
                    }
                }
            }

            if (explosion != null)
            {
                explosion.Explode(entity.WorldPosition);
            }


            Hull hull = null;
            if (entity is Character)
            {
                hull = ((Character)entity).AnimController.CurrentHull;
            }
            else if (entity is Item)
            {
                hull = ((Item)entity).CurrentHull;
            }

            if (FireSize > 0.0f)
            {
                var fire = new FireSource(entity.WorldPosition, hull);

                fire.Size = new Vector2(FireSize, fire.Size.Y);
            }

#if CLIENT
            foreach (ParticleEmitterPrefab emitter in particleEmitters)
            {
                emitter.Emit(entity.WorldPosition, hull);
            }
#endif
        }
Esempio n. 10
0
        public override void Update(Camera cam, float deltaTime)
        {
            Oxygen -= OxygenDetoriationSpeed * deltaTime;

            if (EditWater)
            {
                Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
                if (Submarine.RectContains(WorldRect, position))
                {
                    if (PlayerInput.LeftButtonHeld())
                    {
                        //waveY[GetWaveIndex(position.X - rect.X - Submarine.Position.X) / WaveWidth] = 100.0f;
                        Volume = Volume + 1500.0f;
                    }
                    else if (PlayerInput.RightButtonHeld())
                    {
                        Volume = Volume - 1500.0f;
                    }
                }
            }
            else if (EditFire)
            {
                Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
                if (Submarine.RectContains(WorldRect, position))
                {
                    if (PlayerInput.LeftButtonClicked())
                    {
                        new FireSource(position, this);
                    }
                }
            }

            FireSource.UpdateAll(fireSources, deltaTime);

            aiTarget.SightRange  = Submarine == null ? 0.0f : Math.Max(Submarine.Velocity.Length() * 500.0f, 500.0f);
            aiTarget.SoundRange -= deltaTime * 1000.0f;

            float strongestFlow = 0.0f;

            foreach (Gap gap in ConnectedGaps)
            {
                if (gap.IsRoomToRoom)
                {
                    //only the first linked hull plays the flow sound
                    if (gap.linkedTo[1] == this)
                    {
                        continue;
                    }
                }

                float gapFlow = gap.LerpedFlowForce.Length();

                if (gapFlow > strongestFlow)
                {
                    strongestFlow = gapFlow;
                }
            }

            if (strongestFlow > 1.0f)
            {
                soundVolume = soundVolume + ((strongestFlow < 100.0f) ? -deltaTime * 0.5f : deltaTime * 0.5f);
                soundVolume = MathHelper.Clamp(soundVolume, 0.0f, 1.0f);

                int index = (int)Math.Floor(strongestFlow / 100.0f);
                index = Math.Min(index, 2);

                var flowSound = SoundPlayer.flowSounds[index];
                if (flowSound != currentFlowSound && soundIndex > -1)
                {
                    Sounds.SoundManager.Stop(soundIndex);
                    currentFlowSound = null;
                    soundIndex       = -1;
                }

                currentFlowSound = flowSound;
                soundIndex       = currentFlowSound.Loop(soundIndex, soundVolume, WorldPosition, Math.Min(strongestFlow * 5.0f, 2000.0f));
            }
            else
            {
                if (soundIndex > -1)
                {
                    Sounds.SoundManager.Stop(soundIndex);
                    currentFlowSound = null;
                    soundIndex       = -1;
                }
            }

            //update client hulls if the amount of water has changed by >10%
            //or if oxygen percentage has changed by 5%
            if (Math.Abs(lastSentVolume - volume) > FullVolume * 0.1f ||
                Math.Abs(lastSentOxygen - OxygenPercentage) > 5f)
            {
                if (GameMain.Server != null)
                {
                    sendUpdateTimer -= deltaTime;
                    if (sendUpdateTimer < 0.0f)
                    {
                        GameMain.Server.CreateEntityEvent(this);
                        lastSentVolume  = volume;
                        lastSentOxygen  = OxygenPercentage;
                        sendUpdateTimer = NetworkUpdateInterval;
                    }
                }
            }

            if (!update)
            {
                lethalPressure = 0.0f;
                return;
            }


            float surfaceY = rect.Y - rect.Height + Volume / rect.Width;

            for (int i = 0; i < waveY.Length; i++)
            {
                float maxDelta = Math.Max(Math.Abs(rightDelta[i]), Math.Abs(leftDelta[i]));
                if (maxDelta > Rand.Range(1.0f, 10.0f))
                {
                    var particlePos = new Vector2(rect.X + WaveWidth * i, surface + waveY[i]);
                    if (Submarine != null)
                    {
                        particlePos += Submarine.Position;
                    }

                    GameMain.ParticleManager.CreateParticle("mist",
                                                            particlePos,
                                                            new Vector2(0.0f, -50.0f), 0.0f, this);
                }

                waveY[i] = waveY[i] + waveVel[i];

                if (surfaceY + waveY[i] > rect.Y)
                {
                    waveY[i]  -= (surfaceY + waveY[i]) - rect.Y;
                    waveVel[i] = waveVel[i] * -0.5f;
                }
                else if (surfaceY + waveY[i] < rect.Y - rect.Height)
                {
                    waveY[i]  -= (surfaceY + waveY[i]) - (rect.Y - rect.Height);
                    waveVel[i] = waveVel[i] * -0.5f;
                }

                //acceleration
                float a = -WaveStiffness * waveY[i] - waveVel[i] * WaveDampening;
                waveVel[i] = waveVel[i] + a;
            }

            for (int j = 0; j < 2; j++)
            {
                for (int i = 1; i < waveY.Length - 1; i++)
                {
                    leftDelta[i]   = WaveSpread * (waveY[i] - waveY[i - 1]);
                    waveVel[i - 1] = waveVel[i - 1] + leftDelta[i];

                    rightDelta[i]  = WaveSpread * (waveY[i] - waveY[i + 1]);
                    waveVel[i + 1] = waveVel[i + 1] + rightDelta[i];
                }

                for (int i = 1; i < waveY.Length - 1; i++)
                {
                    waveY[i - 1] = waveY[i - 1] + leftDelta[i];
                    waveY[i + 1] = waveY[i + 1] + rightDelta[i];
                }
            }

            //interpolate the position of the rendered surface towards the "target surface"
            surface = Math.Max(MathHelper.Lerp(surface, surfaceY, deltaTime * 10.0f), rect.Y - rect.Height);

            if (volume < FullVolume)
            {
                LethalPressure -= 10.0f * deltaTime;
                if (Volume == 0.0f)
                {
                    //wait for the surface to be lerped back to bottom and the waves to settle until disabling update
                    if (surface > rect.Y - rect.Height + 1)
                    {
                        return;
                    }
                    for (int i = 1; i < waveY.Length - 1; i++)
                    {
                        if (waveY[i] > 0.1f)
                        {
                            return;
                        }
                    }

                    update = false;
                }
            }
        }
Esempio n. 11
0
 public void RemoveFire(FireSource fire)
 {
     FireSources.Remove(fire);
 }
Esempio n. 12
0
 public void AddFireSource(FireSource fireSource)
 {
     FireSources.Add(fireSource);
 }
Esempio n. 13
0
        protected void Apply(float deltaTime, Entity entity, List <ISerializableEntity> targets, List <int> cancelledEffects = null, Character causecharacter = null, string identifier = "")
        {
#if CLIENT
            if (sound != null)
            {
                if (loopSound)
                {
                    if (!Sounds.SoundManager.IsPlaying(sound))
                    {
                        sound.Play(entity.WorldPosition);
                    }
                    else
                    {
                        sound.UpdatePosition(entity.WorldPosition);
                    }
                }
                else
                {
                    sound.Play(entity.WorldPosition);
                }
            }
#endif

            if (identifier == "")
            {
                identifier = "statuseffect";
            }

            for (int i = 0; i < useItemCount; i++)
            {
                foreach (Item item in targets.FindAll(t => t is Item).Cast <Item>())
                {
                    if (item.Removed)
                    {
                        continue;
                    }
                    item.Use(deltaTime, targets.FirstOrDefault(t => t is Character) as Character, causecharacter, identifier);
                }
            }

            if (removeItem)
            {
                foreach (Item item in targets.FindAll(t => t is Item).Cast <Item>())
                {
                    Entity.Spawner?.AddToRemoveQueue(item);
                }
            }

            if (duration > 0.0f)
            {
                DurationListElement element = new DurationListElement();
                element.Parent  = this;
                element.Timer   = duration;
                element.Entity  = entity;
                element.Targets = targets;
                if (cancelledEffects != null)
                {
                    element.CancelledEffects = cancelledEffects;
                }
                element.causecharacter = causecharacter;
                element.identifier     = identifier;

/*                    if (!target.SerializableProperties.TryGetValue(propertyNames[i], out property)) continue;
 *
 *                  if (duration > 0.0f)
 *                  {
 *                      if (GameMain.Server != null)
 *                      {
 *                          if (target is Character)
 *                          {
 *                              Character effectedcharacter = (Character)target;
 *
 *                              if (GameMain.NilMod.LogStatusEffectStun && property.Name.ToLowerInvariant() == "health" && propertyEffects[i] is float && (float)propertyEffects[i] < 0f)
 *                              {
 *                                  Barotrauma.Networking.GameServer.Log(effectedcharacter.Name + " Poisoned for " + Math.Round((float)propertyEffects[i], 2) + " health per second for " + ToolBox.SecondsToReadableTime(duration) + ".", Networking.ServerLog.MessageType.Attack);
 *                              }
 *                              else if (GameMain.NilMod.LogStatusEffectHealth && property.Name.ToLowerInvariant() == "health" && propertyEffects[i] is float && (float)propertyEffects[i] < 0f)
 *                              {
 *                                  Barotrauma.Networking.GameServer.Log(effectedcharacter.Name + " Poisoned for " + Math.Round((float)propertyEffects[i], 2) + " health per second for " + ToolBox.SecondsToReadableTime(duration) + ".", Networking.ServerLog.MessageType.Attack);
 *                              }
 *                              else if (GameMain.NilMod.LogStatusEffectBleed && property.Name.ToLowerInvariant() == "bleeding" && propertyEffects[i] is float && (float)propertyEffects[i] < 0f)
 *                              {
 *                                  Barotrauma.Networking.GameServer.Log(effectedcharacter.Name + " Poisoned for " + Math.Round((float)propertyEffects[i], 2) + " bleed per second for " + ToolBox.SecondsToReadableTime(duration) + ".", Networking.ServerLog.MessageType.Attack);
 *                              }
 *                              else if (GameMain.NilMod.LogStatusEffectOxygen && property.Name.ToLowerInvariant() == "oxygen" && propertyEffects[i] is float && (float)propertyEffects[i] < 0f)
 *                              {
 *                                  Barotrauma.Networking.GameServer.Log(effectedcharacter.Name + " Poisoned for " + Math.Round((float)propertyEffects[i], 2) + " oxygen per second for " + ToolBox.SecondsToReadableTime(duration) + ".", Networking.ServerLog.MessageType.Attack);
 *                              }
 *                          }
 *                      }*/

                DurationList.Add(element);
            }
            else
            {
/*                        if (GameMain.Server != null)
 *                      {
 *                          if (target is Character)
 *                          {
 *                              Character effectedcharacter = (Character)target;
 *
 *                              //Only show values that are not continous to a character over time, that'd get rediculous fast.
 *                              if (deltaTime == 1f)
 *                              {
 *                                  if (GameMain.NilMod.LogStatusEffectStun && property.Name.ToLowerInvariant() == "stun" && propertyEffects[i] is float && (float)propertyEffects[i] > 5f)
 *                                  {
 *                                      Barotrauma.Networking.GameServer.Log(effectedcharacter.Name + " Stunned for " + (Math.Round((float)propertyEffects[i] * (1f - effectedcharacter.Stunresistance), 2)) + " (" + Math.Round(effectedcharacter.Stunresistance * 100f, 2) + "% Resisted).", Networking.ServerLog.MessageType.Attack);
 *                                  }
 *                                  else if (GameMain.NilMod.LogStatusEffectHealth && property.Name.ToLowerInvariant() == "health" && propertyEffects[i] is float && (float)propertyEffects[i] < 5f)
 *                                  {
 *                                      Barotrauma.Networking.GameServer.Log(effectedcharacter.Name + " Poisoned for " + Math.Round((float)propertyEffects[i], 2) + " health.", Networking.ServerLog.MessageType.Attack);
 *                                  }
 *                                  else if (GameMain.NilMod.LogStatusEffectBleed && property.Name.ToLowerInvariant() == "bleeding" && propertyEffects[i] is float && (float)propertyEffects[i] < 5f)
 *                                  {
 *                                      Barotrauma.Networking.GameServer.Log(effectedcharacter.Name + " Poisoned for " + Math.Round((float)propertyEffects[i], 2) + " bleed.", Networking.ServerLog.MessageType.Attack);
 *                                  }
 *                                  else if (GameMain.NilMod.LogStatusEffectOxygen && property.Name.ToLowerInvariant() == "oxygen" && propertyEffects[i] is float && (float)propertyEffects[i] < 5f)
 *                                  {
 *                                      Barotrauma.Networking.GameServer.Log(effectedcharacter.Name + " Poisoned for " + Math.Round((float)propertyEffects[i], 2) + " oxygen.", Networking.ServerLog.MessageType.Attack);
 *                                  }
 *                              }
 *                          }
 *                      }*/

                foreach (ISerializableEntity target in targets)
                {
                    if (target is Entity targetEntity)
                    {
                        if (targetEntity.Removed)
                        {
                            continue;
                        }
                    }

                    if (target is Character)
                    {
                        for (int i = 0; i < propertyNames.Length; i++)
                        {
                            SerializableProperty property;
                            if (cancelledEffects != null && cancelledEffects.Contains(i))
                            {
                                continue;
                            }
                            if (target == null || target.SerializableProperties == null || !target.SerializableProperties.TryGetValue(propertyNames[i], out property))
                            {
                                continue;
                            }
                            float     prevstat        = 0f;
                            Character targetcharacter = target as Character;
                            Boolean   prevdead        = targetcharacter.IsDead;

                            if (propertyEffects[i].GetType() == typeof(float))
                            {
                                float propertyfloat = Convert.ToSingle(propertyEffects[i]);

                                switch (property.Name.ToLowerInvariant())
                                {
                                case "health":
                                    prevstat = targetcharacter.Health;
                                    if (propertyfloat < 0f)
                                    {
                                        targetcharacter.charRecord.DamageStat("health", -(propertyfloat * CoroutineManager.UnscaledDeltaTime), causecharacter, identifier);
                                    }
                                    break;

                                case "bleeding":
                                    if (propertyfloat > 0f)
                                    {
                                        targetcharacter.charRecord.DamageStat("bleeding", (propertyfloat * CoroutineManager.UnscaledDeltaTime), causecharacter, identifier);
                                    }
                                    break;

                                case "oxygen":
                                    prevstat = targetcharacter.Oxygen;
                                    if (propertyfloat < 0f)
                                    {
                                        targetcharacter.charRecord.DamageStat("oxygen", -(propertyfloat * CoroutineManager.UnscaledDeltaTime), causecharacter, identifier);
                                    }
                                    break;

                                case "stun":
                                    if (propertyfloat > 0f)
                                    {
                                        targetcharacter.charRecord.DamageStat("stun", (propertyfloat * CoroutineManager.UnscaledDeltaTime), causecharacter, identifier);
                                    }
                                    break;

                                case "huskinfectionstate":
                                    if (propertyfloat > 0f)
                                    {
                                        targetcharacter.charRecord.DamageStat("huskinfectionstate", (propertyfloat * CoroutineManager.UnscaledDeltaTime), causecharacter, identifier);
                                    }
                                    break;

                                default:
                                    break;
                                }
                            }

                            ApplyToProperty(property, propertyEffects[i], deltaTime);

                            if (GameMain.NilMod.EnableGriefWatcher && GameMain.Server != null && causecharacter != null)
                            {
                                Barotrauma.Networking.Client targetclient    = GameMain.Server.ConnectedClients.Find(c => c.Character == targetcharacter);
                                Barotrauma.Networking.Client attackingclient = GameMain.Server.ConnectedClients.Find(c => c.Character == causecharacter);
                                if (attackingclient != null && targetclient != null)
                                {
                                    switch (property.Name.ToLowerInvariant())
                                    {
                                    case "health":
                                        if (NilMod.NilModGriefWatcher.PlayerIncapaciteDamage)
                                        {
                                            if (!prevdead)
                                            {
                                                if (targetcharacter.IsDead)
                                                {
                                                    NilMod.NilModGriefWatcher.SendWarning(attackingclient.Character.LogName
                                                                                          + " Killed player " + targetclient.Character.LogName
                                                                                          + " via " + identifier, attackingclient);
                                                }
                                                else if (prevstat > 0f && targetcharacter.Health < 0f)
                                                {
                                                    NilMod.NilModGriefWatcher.SendWarning(attackingclient.Character.LogName
                                                                                          + " Incapacitated player " + targetclient.Character.LogName
                                                                                          + " via " + identifier, attackingclient);
                                                }
                                            }
                                        }
                                        break;

                                    case "oxygen":
                                        if (NilMod.NilModGriefWatcher.PlayerIncapaciteOxygen)
                                        {
                                            if (!prevdead)
                                            {
                                                if (targetcharacter.IsDead)
                                                {
                                                    NilMod.NilModGriefWatcher.SendWarning(attackingclient.Character.LogName
                                                                                          + " Killed player " + targetclient.Character.LogName
                                                                                          + " via " + identifier, attackingclient);
                                                }
                                                else if (prevstat > 0f && targetcharacter.Oxygen < 0f)
                                                {
                                                    NilMod.NilModGriefWatcher.SendWarning(attackingclient.Character.LogName
                                                                                          + " Incapacitated player " + targetclient.Character.LogName
                                                                                          + " via " + identifier, attackingclient);
                                                }
                                            }
                                        }
                                        break;

                                    default:
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    else if (target is Items.Components.ItemComponent && GameMain.Server != null && causecharacter != null)
                    {
                        for (int i = 0; i < propertyNames.Length; i++)
                        {
                            SerializableProperty property;
                            if (cancelledEffects != null && cancelledEffects.Contains(i))
                            {
                                continue;
                            }
                            if (target == null || target.SerializableProperties == null || !target.SerializableProperties.TryGetValue(propertyNames[i], out property))
                            {
                                continue;
                            }
                            Items.Components.ItemComponent targetitemcomponent = target as Items.Components.ItemComponent;
                            Networking.Client attackingclient = GameMain.Server.ConnectedClients.Find(c => c.Character == causecharacter);

                            Items.Components.Door door = targetitemcomponent as Items.Components.Door;
                            Boolean previsStuck        = false;
                            //Door stuck griefing here
                            if (door != null)
                            {
                                if (propertyNames[i].ToLowerInvariant() == "stuck")
                                {
                                    previsStuck = door.IsStuck;
                                }
                            }

                            ApplyToProperty(property, propertyEffects[i], deltaTime);

                            //Door stuck griefing here
                            if (door != null)
                            {
                                if (propertyNames[i].ToLowerInvariant() == "stuck")
                                {
                                    if (previsStuck != door.IsStuck)
                                    {
                                        if (door.IsStuck)
                                        {
                                            Networking.GameServer.Log(causecharacter.LogName
                                                                      + (door.LinkedGap != null && door.LinkedGap.IsRoomToRoom ? " sealed interior " : " sealed exterior ")
                                                                      + door.Item.Name, Networking.ServerLog.MessageType.ItemInteraction);

                                            if (GameMain.NilMod.EnableGriefWatcher && NilMod.NilModGriefWatcher.DoorStuck && attackingclient != null)
                                            {
                                                NilMod.NilModGriefWatcher.SendWarning(
                                                    attackingclient.Character.LogName
                                                    + (door.LinkedGap != null && door.LinkedGap.IsRoomToRoom ? " sealed interior " : " sealed exterior ")
                                                    + door.Item.Name
                                                    + " via " + identifier, attackingclient);
                                            }
                                        }
                                        else
                                        {
                                            Networking.GameServer.Log(causecharacter.LogName
                                                                      + (door.LinkedGap != null && door.LinkedGap.IsRoomToRoom ? " unsealed interior " : " unsealed exterior ")
                                                                      + door.Item.Name, Networking.ServerLog.MessageType.ItemInteraction);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        for (int i = 0; i < propertyNames.Length; i++)
                        {
                            SerializableProperty property;
                            if (cancelledEffects != null && cancelledEffects.Contains(i))
                            {
                                continue;
                            }
                            if (target == null || target.SerializableProperties == null || !target.SerializableProperties.TryGetValue(propertyNames[i], out property))
                            {
                                continue;
                            }

                            ApplyToProperty(property, propertyEffects[i], deltaTime);
                        }
                    }
                }
            }

            if (explosion != null)
            {
                if (identifier == "statuseffect")
                {
                    explosion.Explode(entity.WorldPosition, causecharacter, "");
                }
                else
                {
                    explosion.Explode(entity.WorldPosition, causecharacter, identifier);
                }
            }


            Hull hull = null;
            if (entity is Character)
            {
                hull = ((Character)entity).AnimController.CurrentHull;
            }
            else if (entity is Item)
            {
                hull = ((Item)entity).CurrentHull;
            }

            if (FireSize > 0.0f)
            {
                var fire = new FireSource(entity.WorldPosition, hull);

                fire.Size = new Vector2(FireSize, fire.Size.Y);
            }

#if CLIENT
            foreach (ParticleEmitter emitter in particleEmitters)
            {
                emitter.Emit(deltaTime, entity.WorldPosition, hull);
            }
#endif
        }
Esempio n. 14
0
        protected void Apply(float deltaTime, Entity entity, List <ISerializableEntity> targets)
        {
            Hull hull = null;

            if (entity is Character)
            {
                hull = ((Character)entity).AnimController.CurrentHull;
            }
            else if (entity is Item)
            {
                hull = ((Item)entity).CurrentHull;
            }
#if CLIENT
            if (entity != null && sounds.Count > 0)
            {
                if (soundChannel == null || !soundChannel.IsPlaying)
                {
                    if (soundSelectionMode == SoundSelectionMode.All)
                    {
                        foreach (RoundSound sound in sounds)
                        {
                            soundChannel = SoundPlayer.PlaySound(sound.Sound, sound.Volume, sound.Range, entity.WorldPosition, hull);
                            if (soundChannel != null)
                            {
                                soundChannel.Looping = loopSound;
                            }
                        }
                    }
                    else
                    {
                        int selectedSoundIndex = 0;
                        if (soundSelectionMode == SoundSelectionMode.ItemSpecific && entity is Item item)
                        {
                            selectedSoundIndex = item.ID % sounds.Count;
                        }
                        else if (soundSelectionMode == SoundSelectionMode.CharacterSpecific && entity is Character user)
                        {
                            selectedSoundIndex = user.ID % sounds.Count;
                        }
                        else
                        {
                            selectedSoundIndex = Rand.Int(sounds.Count);
                        }
                        var selectedSound = sounds[selectedSoundIndex];
                        soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, selectedSound.Volume, selectedSound.Range, entity.WorldPosition, hull);
                        if (soundChannel != null)
                        {
                            soundChannel.Looping = loopSound;
                        }
                    }
                }
            }
#endif

            foreach (ISerializableEntity serializableEntity in targets)
            {
                Item item = serializableEntity as Item;
                if (item == null)
                {
                    continue;
                }

                Character targetCharacter = targets.FirstOrDefault(t => t is Character character && !character.Removed) as Character;
                if (targetCharacter == null)
                {
                    foreach (var target in targets)
                    {
                        if (target is Limb limb && limb.character != null && !limb.character.Removed)
                        {
                            targetCharacter = ((Limb)target).character;
                        }
                    }
                }
                for (int i = 0; i < useItemCount; i++)
                {
                    if (item.Removed)
                    {
                        continue;
                    }
                    item.Use(deltaTime, targetCharacter, targets.FirstOrDefault(t => t is Limb) as Limb);
                }
            }

            if (removeItem)
            {
                foreach (Item item in targets.Where(t => t is Item).Cast <Item>())
                {
                    Entity.Spawner?.AddToRemoveQueue(item);
                }
            }

            if (duration > 0.0f)
            {
                DurationListElement element = new DurationListElement
                {
                    Parent  = this,
                    Timer   = duration,
                    Entity  = entity,
                    Targets = targets
                };

                DurationList.Add(element);
            }
            else
            {
                foreach (ISerializableEntity target in targets)
                {
                    if (target is Entity targetEntity)
                    {
                        if (targetEntity.Removed)
                        {
                            continue;
                        }
                    }

                    for (int i = 0; i < propertyNames.Length; i++)
                    {
                        if (target == null || target.SerializableProperties == null ||
                            !target.SerializableProperties.TryGetValue(propertyNames[i], out SerializableProperty property))
                        {
                            continue;
                        }
                        ApplyToProperty(target, property, propertyEffects[i], deltaTime);
                    }
                }
            }

            if (explosion != null && entity != null)
            {
                explosion.Explode(entity.WorldPosition, entity);
            }

            foreach (ISerializableEntity target in targets)
            {
                foreach (Affliction affliction in Afflictions)
                {
                    Affliction multipliedAffliction = affliction;
                    if (!disableDeltaTime)
                    {
                        multipliedAffliction = affliction.CreateMultiplied(deltaTime);
                    }

                    if (target is Character character)
                    {
                        character.LastDamageSource = entity;
                        foreach (Limb limb in character.AnimController.Limbs)
                        {
                            limb.character.DamageLimb(entity.WorldPosition, limb, new List <Affliction>()
                            {
                                multipliedAffliction
                            }, stun: 0.0f, playSound: false, attackImpulse: 0.0f);
                            //only apply non-limb-specific afflictions to the first limb
                            if (!affliction.Prefab.LimbSpecific)
                            {
                                break;
                            }
                        }
                    }
                    else if (target is Limb limb)
                    {
                        limb.character.DamageLimb(entity.WorldPosition, limb, new List <Affliction>()
                        {
                            multipliedAffliction
                        }, stun: 0.0f, playSound: false, attackImpulse: 0.0f);
                    }
                }

                foreach (Pair <string, float> reduceAffliction in ReduceAffliction)
                {
                    float reduceAmount = disableDeltaTime ? reduceAffliction.Second : reduceAffliction.Second * deltaTime;
                    if (target is Character character)
                    {
                        character.CharacterHealth.ReduceAffliction(null, reduceAffliction.First, reduceAmount);
                    }
                    else if (target is Limb limb)
                    {
                        limb.character.CharacterHealth.ReduceAffliction(limb, reduceAffliction.First, reduceAmount);
                    }
                }
            }

            if (FireSize > 0.0f && entity != null)
            {
                var fire = new FireSource(entity.WorldPosition, hull);
                fire.Size = new Vector2(FireSize, fire.Size.Y);
            }

            bool isNotClient = true;
#if CLIENT
            isNotClient = GameMain.Client == null;
#endif

            if (isNotClient && entity != null && Entity.Spawner != null) //clients are not allowed to spawn items
            {
                foreach (ItemSpawnInfo itemSpawnInfo in spawnItems)
                {
                    switch (itemSpawnInfo.SpawnPosition)
                    {
                    case ItemSpawnInfo.SpawnPositionType.This:
                        Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, entity.WorldPosition);
                        break;

                    case ItemSpawnInfo.SpawnPositionType.ThisInventory:
                    {
                        if (entity is Character character)
                        {
                            if (character.Inventory != null && character.Inventory.Items.Any(it => it == null))
                            {
                                Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, character.Inventory);
                            }
                        }
                        else if (entity is Item item)
                        {
                            var inventory = item?.GetComponent <ItemContainer>()?.Inventory;
                            if (inventory != null && inventory.Items.Any(it => it == null))
                            {
                                Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, inventory);
                            }
                        }
                    }
                    break;

                    case ItemSpawnInfo.SpawnPositionType.ContainedInventory:
                    {
                        Inventory thisInventory = null;
                        if (entity is Character character)
                        {
                            thisInventory = character.Inventory;
                        }
                        else if (entity is Item item)
                        {
                            thisInventory = item?.GetComponent <ItemContainer>()?.Inventory;
                        }
                        if (thisInventory != null)
                        {
                            foreach (Item item in thisInventory.Items)
                            {
                                if (item == null)
                                {
                                    continue;
                                }
                                Inventory containedInventory = item.GetComponent <ItemContainer>()?.Inventory;
                                if (containedInventory == null || !containedInventory.Items.Any(i => i == null))
                                {
                                    continue;
                                }
                                Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, containedInventory);
                                break;
                            }
                        }
                    }
                    break;
                    }
                }
            }

#if CLIENT
            if (entity != null)
            {
                foreach (ParticleEmitter emitter in particleEmitters)
                {
                    float angle = 0.0f;
                    if (emitter.Prefab.CopyEntityAngle)
                    {
                        if (entity is Item it)
                        {
                            angle = it.body == null ? 0.0f : it.body.Rotation;
                        }
                    }

                    emitter.Emit(deltaTime, entity.WorldPosition, hull, angle);
                }
            }
#endif
        }
        protected void Apply(float deltaTime, Entity entity, List <ISerializableEntity> targets)
        {
#if CLIENT
            if (sound != null)
            {
                if (loopSound)
                {
                    if (!Sounds.SoundManager.IsPlaying(sound))
                    {
                        sound.Play(entity.WorldPosition);
                    }
                    else
                    {
                        sound.UpdatePosition(entity.WorldPosition);
                    }
                }
                else
                {
                    sound.Play(entity.WorldPosition);
                }
            }
#endif

            for (int i = 0; i < useItemCount; i++)
            {
                foreach (Item item in targets.FindAll(t => t is Item).Cast <Item>())
                {
                    item.Use(deltaTime, targets.FirstOrDefault(t => t is Character) as Character);
                }
            }

            if (removeItem)
            {
                foreach (Item item in targets.FindAll(t => t is Item).Cast <Item>())
                {
                    Entity.Spawner?.AddToRemoveQueue(item);
                }
            }

            if (duration > 0.0f)
            {
                DurationListElement element = new DurationListElement();
                element.Parent  = this;
                element.Timer   = duration;
                element.Entity  = entity;
                element.Targets = targets;

                DurationList.Add(element);
            }
            else
            {
                foreach (ISerializableEntity target in targets)
                {
                    for (int i = 0; i < propertyNames.Length; i++)
                    {
                        SerializableProperty property;

                        if (target == null || target.SerializableProperties == null || !target.SerializableProperties.TryGetValue(propertyNames[i], out property))
                        {
                            continue;
                        }

                        ApplyToProperty(property, propertyEffects[i], deltaTime);
                    }
                }
            }


            if (explosion != null)
            {
                explosion.Explode(entity.WorldPosition);
            }


            Hull hull = null;
            if (entity is Character)
            {
                hull = ((Character)entity).AnimController.CurrentHull;
            }
            else if (entity is Item)
            {
                hull = ((Item)entity).CurrentHull;
            }

            if (FireSize > 0.0f)
            {
                var fire = new FireSource(entity.WorldPosition, hull);

                fire.Size = new Vector2(FireSize, fire.Size.Y);
            }

#if CLIENT
            foreach (ParticleEmitter emitter in particleEmitters)
            {
                emitter.Emit(deltaTime, entity.WorldPosition, hull);
            }
#endif
        }
Esempio n. 16
0
        public override void Update(float deltaTime, Camera cam)
        {
            UpdateProjSpecific(deltaTime, cam);

            Oxygen -= OxygenDetoriationSpeed * deltaTime;

            FireSource.UpdateAll(fireSources, deltaTime);

            aiTarget.SightRange  = Submarine == null ? 0.0f : Math.Max(Submarine.Velocity.Length() * 500.0f, 500.0f);
            aiTarget.SoundRange -= deltaTime * 1000.0f;

            //update client hulls if the amount of water has changed by >10%
            //or if oxygen percentage has changed by 5%
            if (Math.Abs(lastSentVolume - waterVolume) > Volume * 0.1f ||
                Math.Abs(lastSentOxygen - OxygenPercentage) > 5f)
            {
                if (GameMain.Server != null && !IdFreed)
                {
                    sendUpdateTimer -= deltaTime;
                    if (sendUpdateTimer < 0.0f)
                    {
                        GameMain.Server.CreateEntityEvent(this);
                        lastSentVolume  = waterVolume;
                        lastSentOxygen  = OxygenPercentage;
                        sendUpdateTimer = NetworkUpdateInterval;
                    }
                }
            }

            if (!update)
            {
                lethalPressure = 0.0f;
                return;
            }

            float surfaceY = rect.Y - rect.Height + WaterVolume / rect.Width;

            for (int i = 0; i < waveY.Length; i++)
            {
                waveY[i] = waveY[i] + waveVel[i];

                if (surfaceY + waveY[i] > rect.Y)
                {
                    waveY[i]  -= (surfaceY + waveY[i]) - rect.Y;
                    waveVel[i] = waveVel[i] * -0.5f;
                }
                else if (surfaceY + waveY[i] < rect.Y - rect.Height)
                {
                    waveY[i]  -= (surfaceY + waveY[i]) - (rect.Y - rect.Height);
                    waveVel[i] = waveVel[i] * -0.5f;
                }

                //acceleration
                float a = -WaveStiffness * waveY[i] - waveVel[i] * WaveDampening;
                waveVel[i] = waveVel[i] + a;
            }

            for (int j = 0; j < 2; j++)
            {
                for (int i = 1; i < waveY.Length - 1; i++)
                {
                    leftDelta[i]   = WaveSpread * (waveY[i] - waveY[i - 1]);
                    waveVel[i - 1] = waveVel[i - 1] + leftDelta[i];

                    rightDelta[i]  = WaveSpread * (waveY[i] - waveY[i + 1]);
                    waveVel[i + 1] = waveVel[i + 1] + rightDelta[i];
                }

                for (int i = 1; i < waveY.Length - 1; i++)
                {
                    waveY[i - 1] = waveY[i - 1] + leftDelta[i];
                    waveY[i + 1] = waveY[i + 1] + rightDelta[i];
                }
            }

            //interpolate the position of the rendered surface towards the "target surface"
            surface = Math.Max(MathHelper.Lerp(surface, surfaceY, deltaTime * 10.0f), rect.Y - rect.Height);

            if (waterVolume < Volume)
            {
                LethalPressure -= 10.0f * deltaTime;
                if (WaterVolume <= 0.0f)
                {
                    //wait for the surface to be lerped back to bottom and the waves to settle until disabling update
                    if (surface > rect.Y - rect.Height + 1)
                    {
                        return;
                    }
                    for (int i = 1; i < waveY.Length - 1; i++)
                    {
                        if (waveY[i] > 0.1f)
                        {
                            return;
                        }
                    }

                    update = false;
                }
            }
        }
Esempio n. 17
0
        public override void Update(float deltaTime, Camera cam)
        {
            UpdateProjSpecific(deltaTime, cam);

            Oxygen -= OxygenDeteriorationSpeed * deltaTime;

            FireSource.UpdateAll(FireSources, deltaTime);

            aiTarget.SightRange  = Submarine == null ? 0.0f : Math.Max(Submarine.Velocity.Length() * 2000.0f, AITarget.StaticSightRange);
            aiTarget.SoundRange -= deltaTime * 1000.0f;

            if (!update)
            {
                lethalPressure = 0.0f;
                return;
            }

            surface = Math.Max(MathHelper.Lerp(
                                   surface,
                                   rect.Y - rect.Height + WaterVolume / rect.Width,
                                   deltaTime * 10.0f), rect.Y - rect.Height);
            //interpolate the position of the rendered surface towards the "target surface"
            drawSurface = Math.Max(MathHelper.Lerp(
                                       drawSurface,
                                       rect.Y - rect.Height + WaterVolume / rect.Width,
                                       deltaTime * 10.0f), rect.Y - rect.Height);

            for (int i = 0; i < waveY.Length; i++)
            {
                //apply velocity
                waveY[i] = waveY[i] + waveVel[i];

                //if the wave attempts to go "through" the top of the hull, make it bounce back
                if (surface + waveY[i] > rect.Y)
                {
                    float excess = (surface + waveY[i]) - rect.Y;
                    waveY[i]  -= excess;
                    waveVel[i] = waveVel[i] * -0.5f;
                }
                //if the wave attempts to go "through" the bottom of the hull, make it bounce back
                else if (surface + waveY[i] < rect.Y - rect.Height)
                {
                    float excess = (surface + waveY[i]) - (rect.Y - rect.Height);
                    waveY[i]  -= excess;
                    waveVel[i] = waveVel[i] * -0.5f;
                }

                //acceleration
                float a = -WaveStiffness * waveY[i] - waveVel[i] * WaveDampening;
                waveVel[i] = waveVel[i] + a;
            }

            //apply spread (two iterations)
            for (int j = 0; j < 2; j++)
            {
                for (int i = 1; i < waveY.Length - 1; i++)
                {
                    leftDelta[i]    = WaveSpread * (waveY[i] - waveY[i - 1]);
                    waveVel[i - 1] += leftDelta[i];

                    rightDelta[i]   = WaveSpread * (waveY[i] - waveY[i + 1]);
                    waveVel[i + 1] += rightDelta[i];
                }

                for (int i = 1; i < waveY.Length - 1; i++)
                {
                    waveY[i - 1] += leftDelta[i];
                    waveY[i + 1] += rightDelta[i];
                }
            }

            //make waves propagate through horizontal gaps
            foreach (Gap gap in ConnectedGaps)
            {
                if (!gap.IsRoomToRoom || !gap.IsHorizontal || gap.Open <= 0.0f)
                {
                    continue;
                }
                if (surface > gap.Rect.Y || surface < gap.Rect.Y - gap.Rect.Height)
                {
                    continue;
                }

                Hull  hull2         = this == gap.linkedTo[0] as Hull ? (Hull)gap.linkedTo[1] : (Hull)gap.linkedTo[0];
                float otherSurfaceY = hull2.surface;
                if (otherSurfaceY > gap.Rect.Y || otherSurfaceY < gap.Rect.Y - gap.Rect.Height)
                {
                    continue;
                }

                float surfaceDiff = (surface - otherSurfaceY) * gap.Open;
                if (this != gap.linkedTo[0] as Hull)
                {
                    //the first hull linked to the gap handles the wave propagation,
                    //the second just updates the surfaces to the same level
                    if (surfaceDiff < 32.0f)
                    {
                        hull2.waveY[hull2.waveY.Length - 1] = surfaceDiff * 0.5f;
                        waveY[0] = -surfaceDiff * 0.5f;
                    }
                    continue;
                }

                for (int j = 0; j < 2; j++)
                {
                    int i = waveY.Length - 1;

                    leftDelta[i]    = WaveSpread * (waveY[i] - waveY[i - 1]);
                    waveVel[i - 1] += leftDelta[i];

                    rightDelta[i]     = WaveSpread * (waveY[i] - hull2.waveY[0] + surfaceDiff);
                    hull2.waveVel[0] += rightDelta[i];

                    i = 0;

                    hull2.leftDelta[i]           = WaveSpread * (hull2.waveY[i] - waveY[waveY.Length - 1] - surfaceDiff);
                    waveVel[waveVel.Length - 1] += hull2.leftDelta[i];

                    hull2.rightDelta[i]   = WaveSpread * (hull2.waveY[i] - hull2.waveY[i + 1]);
                    hull2.waveVel[i + 1] += hull2.rightDelta[i];
                }

                if (surfaceDiff < 32.0f)
                {
                    //update surfaces to the same level
                    hull2.waveY[0]          = surfaceDiff * 0.5f;
                    waveY[waveY.Length - 1] = -surfaceDiff * 0.5f;
                }
                else
                {
                    hull2.waveY[0]          += rightDelta[waveY.Length - 1];
                    waveY[waveY.Length - 1] += hull2.leftDelta[0];
                }
            }

            if (waterVolume < Volume)
            {
                LethalPressure -= 10.0f * deltaTime;
                if (WaterVolume <= 0.0f)
                {
                    //wait for the surface to be lerped back to bottom and the waves to settle until disabling update
                    if (drawSurface > rect.Y - rect.Height + 1)
                    {
                        return;
                    }
                    for (int i = 1; i < waveY.Length - 1; i++)
                    {
                        if (waveY[i] > 0.1f)
                        {
                            return;
                        }
                    }

                    update = false;
                }
            }
        }
Esempio n. 18
0
 private bool CheckOverLap(FireSource fireSource)
 {
     return(!(position.X > fireSource.position.X + fireSource.size.X ||
              position.X + size.X < fireSource.position.X));
 }
Esempio n. 19
0
        public override void Update(float deltaTime, Camera cam)
        {
            base.Update(deltaTime, cam);
            UpdateProjSpecific(deltaTime, cam);

            Oxygen -= OxygenDeteriorationSpeed * deltaTime;

            FireSource.UpdateAll(FireSources, deltaTime);

            if (aiTarget != null)
            {
                aiTarget.SightRange  = Submarine == null ? aiTarget.MinSightRange : Submarine.Velocity.Length() / 2 * aiTarget.MaxSightRange;
                aiTarget.SoundRange -= deltaTime * 1000.0f;
            }

            if (!update)
            {
                lethalPressure = 0.0f;
                return;
            }

            float waterDepth = WaterVolume / rect.Width;

            if (waterDepth < 1.0f)
            {
                //if there's only a minuscule amount of water, consider the surface to be at the bottom of the hull
                //otherwise unnoticeable amounts of water can for example cause magnesium to explode
                waterDepth = 0.0f;
            }

            surface = Math.Max(MathHelper.Lerp(
                                   surface,
                                   rect.Y - rect.Height + waterDepth,
                                   deltaTime * 10.0f), rect.Y - rect.Height);
            //interpolate the position of the rendered surface towards the "target surface"
            drawSurface = Math.Max(MathHelper.Lerp(
                                       drawSurface,
                                       rect.Y - rect.Height + waterDepth,
                                       deltaTime * 10.0f), rect.Y - rect.Height);

            for (int i = 0; i < waveY.Length; i++)
            {
                //apply velocity
                waveY[i] = waveY[i] + waveVel[i];

                //if the wave attempts to go "through" the top of the hull, make it bounce back
                if (surface + waveY[i] > rect.Y)
                {
                    float excess = (surface + waveY[i]) - rect.Y;
                    waveY[i]  -= excess;
                    waveVel[i] = waveVel[i] * -0.5f;
                }
                //if the wave attempts to go "through" the bottom of the hull, make it bounce back
                else if (surface + waveY[i] < rect.Y - rect.Height)
                {
                    float excess = (surface + waveY[i]) - (rect.Y - rect.Height);
                    waveY[i]  -= excess;
                    waveVel[i] = waveVel[i] * -0.5f;
                }

                //acceleration
                float a = -WaveStiffness * waveY[i] - waveVel[i] * WaveDampening;
                waveVel[i] = waveVel[i] + a;
            }

            //apply spread (two iterations)
            for (int j = 0; j < 2; j++)
            {
                for (int i = 1; i < waveY.Length - 1; i++)
                {
                    leftDelta[i]    = WaveSpread * (waveY[i] - waveY[i - 1]);
                    waveVel[i - 1] += leftDelta[i];

                    rightDelta[i]   = WaveSpread * (waveY[i] - waveY[i + 1]);
                    waveVel[i + 1] += rightDelta[i];
                }
            }

            //make waves propagate through horizontal gaps
            foreach (Gap gap in ConnectedGaps)
            {
                if (this != gap.linkedTo[0] as Hull)
                {
                    //let the first linked hull handle the water propagation
                    continue;
                }

                if (!gap.IsRoomToRoom || !gap.IsHorizontal || gap.Open <= 0.0f)
                {
                    continue;
                }
                if (surface > gap.Rect.Y || surface < gap.Rect.Y - gap.Rect.Height)
                {
                    continue;
                }

                // ReSharper refuses to compile this if it's using "as Hull" since "as" means it can be null and you can't compare null to true or false
                Hull  hull2         = this == gap.linkedTo[0] ? (Hull)gap.linkedTo[1] : (Hull)gap.linkedTo[0];
                float otherSurfaceY = hull2.surface;
                if (otherSurfaceY > gap.Rect.Y || otherSurfaceY < gap.Rect.Y - gap.Rect.Height)
                {
                    continue;
                }

                float surfaceDiff = (surface - otherSurfaceY) * gap.Open;
                for (int j = 0; j < 2; j++)
                {
                    rightDelta[waveY.Length - 1] = WaveSpread * (hull2.waveY[0] - waveY[waveY.Length - 1] - surfaceDiff) * 0.5f;
                    waveVel[waveY.Length - 1]   += rightDelta[waveY.Length - 1];
                    waveY[waveY.Length - 1]     += rightDelta[waveY.Length - 1];

                    hull2.leftDelta[0] = WaveSpread * (waveY[waveY.Length - 1] - hull2.waveY[0] + surfaceDiff) * 0.5f;
                    hull2.waveVel[0]  += hull2.leftDelta[0];
                    hull2.waveY[0]    += hull2.leftDelta[0];
                }

                if (surfaceDiff < 32.0f)
                {
                    //update surfaces to the same level
                    hull2.waveY[0]          = surfaceDiff * 0.5f;
                    waveY[waveY.Length - 1] = -surfaceDiff * 0.5f;
                }
            }


            //apply spread (two iterations)
            for (int j = 0; j < 2; j++)
            {
                for (int i = 1; i < waveY.Length - 1; i++)
                {
                    waveY[i - 1] += leftDelta[i];
                    waveY[i + 1] += rightDelta[i];
                }
            }

            if (waterVolume < Volume)
            {
                LethalPressure -= 10.0f * deltaTime;
                if (WaterVolume <= 0.0f)
                {
                    //wait for the surface to be lerped back to bottom and the waves to settle until disabling update
                    if (drawSurface > rect.Y - rect.Height + 1)
                    {
                        return;
                    }
                    for (int i = 1; i < waveY.Length - 1; i++)
                    {
                        if (waveY[i] > 0.1f)
                        {
                            return;
                        }
                    }

                    update = false;
                }
            }
        }