public void AddFireSource(FireSource fireSource) { fireSources.Add(fireSource); if (GameMain.Server != null) { GameMain.Server.CreateEntityEvent(this); } }
public void RemoveFire(FireSource fire) { FireSources.Remove(fire); if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer && !Removed && !IdFreed) { GameMain.NetworkMember.CreateEntityEvent(this); } }
public void RemoveFire(FireSource fire) { fireSources.Remove(fire); if (GameMain.Server != null) { GameMain.Server.CreateEntityEvent(this); } }
public void AddFireSource(FireSource fireSource) { FireSources.Add(fireSource); if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer && !IdFreed) { GameMain.NetworkMember.CreateEntityEvent(this); } }
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; }
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); }
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); }
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 }
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; } } }
public void RemoveFire(FireSource fire) { FireSources.Remove(fire); }
public void AddFireSource(FireSource fireSource) { FireSources.Add(fireSource); }
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 }
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 }
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; } } }
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; } } }
private bool CheckOverLap(FireSource fireSource) { return(!(position.X > fireSource.position.X + fireSource.size.X || position.X + size.X < fireSource.position.X)); }
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; } } }