diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj index 1eed57d21..6700832dd 100644 --- a/Subsurface/Barotrauma.csproj +++ b/Subsurface/Barotrauma.csproj @@ -414,6 +414,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -921,6 +924,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Subsurface/Barotrauma.csproj.user b/Subsurface/Barotrauma.csproj.user index 1782abafa..df35fcf91 100644 --- a/Subsurface/Barotrauma.csproj.user +++ b/Subsurface/Barotrauma.csproj.user @@ -9,7 +9,7 @@ en-US false - ShowAllFiles + ProjectFiles diff --git a/Subsurface/Content/Items/Clothes/clothes.xml b/Subsurface/Content/Items/Clothes/clothes.xml index 27f4328e0..a0b34fed0 100644 --- a/Subsurface/Content/Items/Clothes/clothes.xml +++ b/Subsurface/Content/Items/Clothes/clothes.xml @@ -85,9 +85,10 @@ + tags="smallitem" + fireproof="true"> - + @@ -102,8 +103,31 @@ - + + + + + + + + + + + + + + + + + + + + diff --git a/Subsurface/Content/Items/Clothes/engigear.png b/Subsurface/Content/Items/Clothes/engigear.png index 11ac9854a..3c8a966ba 100644 Binary files a/Subsurface/Content/Items/Clothes/engigear.png and b/Subsurface/Content/Items/Clothes/engigear.png differ diff --git a/Subsurface/Content/Items/Diving/divinggear.xml b/Subsurface/Content/Items/Diving/divinggear.xml index 13e7b77c8..fd67f56e7 100644 --- a/Subsurface/Content/Items/Diving/divinggear.xml +++ b/Subsurface/Content/Items/Diving/divinggear.xml @@ -45,13 +45,16 @@ + price="200" + fireproof="true"> + + @@ -89,7 +92,7 @@ - + diff --git a/Subsurface/Content/Items/Tools/extinguisher.ogg b/Subsurface/Content/Items/Tools/extinguisher.ogg new file mode 100644 index 000000000..630a63246 Binary files /dev/null and b/Subsurface/Content/Items/Tools/extinguisher.ogg differ diff --git a/Subsurface/Content/Items/Tools/extinguisher.png b/Subsurface/Content/Items/Tools/extinguisher.png new file mode 100644 index 000000000..d04561fbe Binary files /dev/null and b/Subsurface/Content/Items/Tools/extinguisher.png differ diff --git a/Subsurface/Content/Items/Tools/tools.xml b/Subsurface/Content/Items/Tools/tools.xml index 1704af206..d26e8214c 100644 --- a/Subsurface/Content/Items/Tools/tools.xml +++ b/Subsurface/Content/Items/Tools/tools.xml @@ -102,6 +102,28 @@ + + + + + + + + + + + + + + + + + - \ No newline at end of file diff --git a/Subsurface/Content/Jobs.xml b/Subsurface/Content/Jobs.xml index 925e30fc2..4a9ab622f 100644 --- a/Subsurface/Content/Jobs.xml +++ b/Subsurface/Content/Jobs.xml @@ -22,6 +22,7 @@ + @@ -33,6 +34,7 @@ + diff --git a/Subsurface/Content/Particles/ParticlePrefabs.xml b/Subsurface/Content/Particles/ParticlePrefabs.xml index e89939ca4..457077a27 100644 --- a/Subsurface/Content/Particles/ParticlePrefabs.xml +++ b/Subsurface/Content/Particles/ParticlePrefabs.xml @@ -10,7 +10,9 @@ growtime ="0.2" collideswithwalls="true" velocitychange="0.0, -9.8"> - + + + - + - + + + - + + + - + @@ -128,10 +134,25 @@ growtime ="0.2" lifetime="3" collideswithwalls="true" + collisionradius="30.0" velocitychange="0.0, 2.5"> - + + + + + + + + + diff --git a/Subsurface/Content/Particles/spatter.png b/Subsurface/Content/Particles/spatter.png index 0a436ce2a..da66f16ae 100644 Binary files a/Subsurface/Content/Particles/spatter.png and b/Subsurface/Content/Particles/spatter.png differ diff --git a/Subsurface/Source/Characters/AICharacter.cs b/Subsurface/Source/Characters/AICharacter.cs index 8d7694cb6..7000b67a3 100644 --- a/Subsurface/Source/Characters/AICharacter.cs +++ b/Subsurface/Source/Characters/AICharacter.cs @@ -111,6 +111,8 @@ namespace Barotrauma aiController.FillNetworkData(message); return true; case NetworkEventType.EntityUpdate: + if (AnimController.RefLimb.SimPosition.Length() > NetConfig.CharacterIgnoreDistance) return false; + message.Write((float)NetTime.Now); message.Write(AnimController.TargetDir == Direction.Right); diff --git a/Subsurface/Source/Characters/Attack.cs b/Subsurface/Source/Characters/Attack.cs index 26a19cc89..fd7f06ce2 100644 --- a/Subsurface/Source/Characters/Attack.cs +++ b/Subsurface/Source/Characters/Attack.cs @@ -8,10 +8,10 @@ namespace Barotrauma { enum CauseOfDeath { - Damage, Bloodloss, Pressure, Suffocation, Drowning + Damage, Bloodloss, Pressure, Suffocation, Drowning, Burn } - public enum DamageType { None, Blunt, Slash } + public enum DamageType { None, Blunt, Slash, Burn } public enum AttackType { diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 7d11a8001..4cc19993e 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -272,6 +272,7 @@ namespace Barotrauma DeathMsg[(int)CauseOfDeath.Drowning] = "drowned"; DeathMsg[(int)CauseOfDeath.Suffocation] = "suffocated"; DeathMsg[(int)CauseOfDeath.Pressure] = "been crushed by water pressure"; + DeathMsg[(int)CauseOfDeath.Burn] = "burnt to death"; } public Character(string file) : this(file, Vector2.Zero, null) @@ -1030,6 +1031,8 @@ namespace Barotrauma AttackResult attackResult = closestLimb.AddDamage(simPosition, damageType, amount, bleedingAmount, playSound); health -= attackResult.Damage; + if (health <= 0.0f && damageType == DamageType.Burn) Kill(CauseOfDeath.Burn); + bleeding += attackResult.Bleeding; return attackResult; diff --git a/Subsurface/Source/Characters/Limb.cs b/Subsurface/Source/Characters/Limb.cs index 1a26e55b4..c2e455649 100644 --- a/Subsurface/Source/Characters/Limb.cs +++ b/Subsurface/Source/Characters/Limb.cs @@ -50,7 +50,7 @@ namespace Barotrauma public readonly float impactTolerance; - private float damage; + private float damage, burnt; private readonly Vector2 armorSector; private readonly float armorValue; @@ -138,6 +138,12 @@ namespace Barotrauma get { return stepOffset; } } + public float Burnt + { + get { return burnt; } + set { burnt = MathHelper.Clamp(value,0.0f,100.0f); } + } + //public float Damage //{ // get { return damage; } @@ -381,6 +387,8 @@ namespace Barotrauma if (!character.IsDead) damage = Math.Max(0.0f, damage-deltaTime*0.1f); + if (burnt > 0.0f) Burnt -= deltaTime; + if (LinearVelocity.X>100.0f) { //DebugConsole.ThrowError("CHARACTER EXPLODED"); @@ -435,7 +443,8 @@ namespace Barotrauma public void Draw(SpriteBatch spriteBatch) { - Color color = Color.White;// new Color(1.0f, 1.0f - damage / maxHealth, 1.0f - damage / maxHealth); + float brightness = 1.0f - (burnt / 100.0f) * 0.5f; + Color color = new Color(brightness, brightness, brightness); body.Dir = Dir; diff --git a/Subsurface/Source/Items/Components/Holdable/RepairTool.cs b/Subsurface/Source/Items/Components/Holdable/RepairTool.cs index 05d4f12bf..cdcbaac48 100644 --- a/Subsurface/Source/Items/Components/Holdable/RepairTool.cs +++ b/Subsurface/Source/Items/Components/Holdable/RepairTool.cs @@ -21,8 +21,6 @@ namespace Barotrauma.Items.Components private string particles; - float structureFixAmount, limbFixAmount; - [HasDefaultValue(0.0f, false)] public float Range { @@ -33,15 +31,18 @@ namespace Barotrauma.Items.Components [HasDefaultValue(0.0f, false)] public float StructureFixAmount { - get { return structureFixAmount; } - set { structureFixAmount = value; } + get; set; } [HasDefaultValue(0.0f, false)] public float LimbFixAmount { - get { return limbFixAmount; } - set { limbFixAmount = value; } + get; set; + } + [HasDefaultValue(0.0f, false)] + public float ExtinquishAmount + { + get; set; } [HasDefaultValue("", false)] @@ -51,6 +52,12 @@ namespace Barotrauma.Items.Components set { particles = value; } } + [HasDefaultValue(0.0f, false)] + public float ParticleSpeed + { + get; set; + } + [HasDefaultValue("0.0,0.0", false)] public string BarrelPos { @@ -130,9 +137,18 @@ namespace Barotrauma.Items.Components ignoredBodies.Add(limb.body.FarseerBody); } + + Body targetBody = Submarine.PickBody(TransformedBarrelPos, targetPosition, ignoredBodies); pickedPosition = Submarine.LastPickedPosition; + if (ExtinquishAmount > 0.0f) + { + Vector2 displayPos = ConvertUnits.ToDisplayUnits(TransformedBarrelPos + (targetPosition-TransformedBarrelPos)*Submarine.LastPickedFraction*0.9f); + Hull hull = Hull.FindHull(displayPos, item.CurrentHull); + if (hull != null) hull.Extinquish(deltaTime, ExtinquishAmount, displayPos); + } + if (targetBody == null || targetBody.UserData == null) return true; Structure targetStructure; @@ -147,7 +163,7 @@ namespace Barotrauma.Items.Components targetStructure.HighLightSection(sectionIndex); - targetStructure.AddDamage(sectionIndex, -structureFixAmount*degreeOfSuccess); + targetStructure.AddDamage(sectionIndex, -StructureFixAmount*degreeOfSuccess); //if the next section is small enough, apply the effect to it as well //(to make it easier to fix a small "left-over" section) @@ -155,7 +171,7 @@ namespace Barotrauma.Items.Components if (nextSectionLength > 0 && nextSectionLength < Structure.wallSectionSize * 0.3f) { targetStructure.HighLightSection(sectionIndex + 1); - targetStructure.AddDamage(sectionIndex + 1, -structureFixAmount * degreeOfSuccess); + targetStructure.AddDamage(sectionIndex + 1, -StructureFixAmount * degreeOfSuccess); } } @@ -163,7 +179,7 @@ namespace Barotrauma.Items.Components { if (character.IsKeyDown(InputType.Aim)) { - targetLimb.character.Health += limbFixAmount * degreeOfSuccess; + targetLimb.character.Health += LimbFixAmount * degreeOfSuccess; //isActive = true; } } @@ -180,7 +196,6 @@ namespace Barotrauma.Items.Components } //ApplyStatusEffects(ActionType.OnUse, 1.0f, null, targ); } - //if (Character.SecondaryKeyDown.State) //{ // IPropertyObject propertyObject = targetBody.UserData as IPropertyObject; @@ -210,7 +225,7 @@ namespace Barotrauma.Items.Components if (!string.IsNullOrWhiteSpace(particles)) { GameMain.ParticleManager.CreateParticle(particles, ConvertUnits.ToDisplayUnits(TransformedBarrelPos), - -item.body.Rotation + ((item.body.Dir>0.0f) ? 0.0f : MathHelper.Pi), 0.0f); + -item.body.Rotation + ((item.body.Dir>0.0f) ? 0.0f : MathHelper.Pi), ParticleSpeed); } //Vector2 startPos = ConvertUnits.ToDisplayUnits(item.body.Position); diff --git a/Subsurface/Source/Items/Components/Machines/Controller.cs b/Subsurface/Source/Items/Components/Machines/Controller.cs index 45305b3cd..ea21d683e 100644 --- a/Subsurface/Source/Items/Components/Machines/Controller.cs +++ b/Subsurface/Source/Items/Components/Machines/Controller.cs @@ -182,7 +182,7 @@ namespace Barotrauma.Items.Components IsActive = false; if (activator != null) activator.AnimController.Anim = AnimController.Animation.None; - return false; + return true; } else { diff --git a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs index fd3df461a..548f8a29e 100644 --- a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs +++ b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs @@ -12,6 +12,8 @@ namespace Barotrauma.Items.Components static float fullPower; static float fullLoad; + const float FireProbability = 0.15f; + //affects how fast changes in power/load are carried over the grid static float inertia = 5.0f; @@ -71,7 +73,10 @@ namespace Barotrauma.Items.Components if (particle != null) particle.Size *= Rand.Range(0.5f, 1.0f); } - new FireSource(pt.item.Position); + if (FireProbability > 0.0f && Rand.Int((int)(1.0f / FireProbability)) == 1) + { + new FireSource(pt.item.Position); + } } } diff --git a/Subsurface/Source/Items/Inventory.cs b/Subsurface/Source/Items/Inventory.cs index 3a8284b0a..0a67f83f5 100644 --- a/Subsurface/Source/Items/Inventory.cs +++ b/Subsurface/Source/Items/Inventory.cs @@ -119,7 +119,7 @@ namespace Barotrauma if (item.inventory != null && removeItem) { item.Drop(null, false); - item.inventory.RemoveItem(item); + if (item.inventory != null) item.inventory.RemoveItem(item); } items[i] = item; @@ -139,6 +139,7 @@ namespace Barotrauma { if (items[n] != item) continue; items[n] = null; + item.inventory = null; } } diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs index 9ef58891a..7f902edb7 100644 --- a/Subsurface/Source/Items/Item.cs +++ b/Subsurface/Source/Items/Item.cs @@ -594,7 +594,7 @@ namespace Barotrauma body.ApplyTorque(body.AngularVelocity * volume * -0.05f); } - public override void Draw(SpriteBatch spriteBatch, bool editing) + public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) { Color color = (isSelected && editing) ? color = Color.Red : spriteColor; if (isHighlighted) color = Color.Orange; diff --git a/Subsurface/Source/Map/Entity.cs b/Subsurface/Source/Map/Entity.cs index bbda52b13..61ab82b0b 100644 --- a/Subsurface/Source/Map/Entity.cs +++ b/Subsurface/Source/Map/Entity.cs @@ -15,7 +15,7 @@ namespace Barotrauma protected AITarget aiTarget; //protected float soundRange; //protected float sightRange; - + public ushort ID { get { return id; } diff --git a/Subsurface/Source/Map/FireSource.cs b/Subsurface/Source/Map/FireSource.cs index e301522f7..8785da854 100644 --- a/Subsurface/Source/Map/FireSource.cs +++ b/Subsurface/Source/Map/FireSource.cs @@ -23,15 +23,26 @@ namespace Barotrauma Vector2 position; Vector2 size; + public Vector2 Position + { + get { return position; } + set + { + if (!MathUtils.IsValid(value)) return; + + position = value; + } + } + public Vector2 Size { get { return size; } } - public FireSource(Vector2 position) + public FireSource(Vector2 position, Hull spawningHull = null, bool networkEvent=false) { - hull = Hull.FindHull(position); - if (hull == null) return; + hull = Hull.FindHull(position, spawningHull); + if (hull == null || (!networkEvent && GameMain.Client!=null)) return; if (fireSoundBasic==null) { @@ -41,7 +52,7 @@ namespace Barotrauma lightSource = new LightSource(position, 50.0f, new Color(1.0f, 0.9f, 0.6f)); - hull.AddFireSource(this); + hull.AddFireSource(this, !networkEvent); this.position = position - new Vector2(-5.0f, 5.0f); @@ -87,33 +98,47 @@ namespace Barotrauma } } + public bool Contains(Vector2 pos) + { + return pos.X > position.X && pos.X fireSource.position.X + fireSource.size.X && + return !(position.X > fireSource.position.X + fireSource.size.X || position.X + size.X < fireSource.position.X); - - } public void Update(float deltaTime) { - float count = Rand.Range(0.0f, (float)Math.Sqrt(size.X)/2.0f); + float count = Rand.Range(0.0f, (float)Math.Sqrt(size.X)/3.0f); - basicSoundIndex = fireSoundBasic.Loop(basicSoundIndex, Math.Min(size.X/100.0f,1.0f), position+size/2.0f, 2000.0f); - largeSoundIndex = fireSoundLarge.Loop(largeSoundIndex, MathHelper.Clamp((size.X-200.0f) / 100.0f, 0.0f, 1.0f), position + size / 2.0f, 2000.0f); + if (fireSoundBasic != null) + { + basicSoundIndex = fireSoundBasic.Loop(basicSoundIndex, + Math.Min(size.X / 100.0f, 1.0f), position + size / 2.0f, 2000.0f); + + } + if (fireSoundLarge != null) + { + largeSoundIndex = fireSoundLarge.Loop(largeSoundIndex, + MathHelper.Clamp((size.X - 200.0f) / 100.0f, 0.0f, 1.0f), position + size / 2.0f, 2000.0f); + } if (size.X>50.0f) { this.position.Y = MathHelper.Lerp(this.position.Y, hull.Rect.Y - hull.Rect.Height, deltaTime); } + float growModifier = hull.OxygenPercentage < 20.0f ? (hull.OxygenPercentage/10.0f)-1.0f : 1.0f; + for (int i = 0; i < count; i++ ) { float normalizedPos = 0.5f-(i / count); Vector2 spawnPos = new Vector2(position.X + Rand.Range(0.0f, size.X), Rand.Range(position.Y - size.Y, position.Y)+10.0f); - Vector2 speed = new Vector2((spawnPos.X - (position.X + size.X/2.0f)), (float)Math.Sqrt(size.X)*Rand.Range(10.0f,15.0f)); + Vector2 speed = new Vector2((spawnPos.X - (position.X + size.X/2.0f)), (float)Math.Sqrt(size.X)*Rand.Range(10.0f,15.0f)*growModifier); var particle = GameMain.ParticleManager.CreateParticle("flame", spawnPos, speed, 0.0f, hull); @@ -122,22 +147,29 @@ namespace Barotrauma if (Rand.Int(20) == 1) particle.OnChangeHull = OnChangeHull; + particle.Size *= MathHelper.Clamp(size.X/100.0f * Math.Max(hull.Oxygen/hull.FullVolume, 0.4f), 0.5f, 4.0f); - particle.Size *= MathHelper.Clamp(size.X/100.0f * (hull.Oxygen/hull.FullVolume), 0.5f, 4.0f); + if (size.X < 100.0f) continue; + + var smokeParticle = GameMain.ParticleManager.CreateParticle("smoke", + spawnPos, speed, 0.0f, hull); + + if (smokeParticle != null) + { + smokeParticle.Size *= MathHelper.Clamp(size.X / 100.0f * Math.Max(hull.Oxygen / hull.FullVolume, 0.4f), 0.5f, 4.0f); + } } DamageCharacters(deltaTime); DamageItems(deltaTime); - if (hull.Volume > 0.0f) Extinquish(deltaTime); + if (hull.Volume > 0.0f) HullWaterExtinquish(deltaTime); - lightSource.Range = Math.Max(size.X, size.Y)*Rand.Range(8.0f, 10.0f)/2.0f; + lightSource.Range = Math.Max(size.X, size.Y) * Rand.Range(8.0f, 10.0f)/2.0f; lightSource.Color = new Color(1.0f, 0.9f, 0.6f) * Rand.Range(0.8f, 1.0f); hull.Oxygen -= size.X*deltaTime*OxygenConsumption; - float growModifier = hull.OxygenPercentage < 20.0f ? (hull.OxygenPercentage/10.0f)-1.0f : 1.0f; - position.X -= GrowSpeed * growModifier * 0.5f * deltaTime; //position.Y += GrowSpeed*0.5f * deltaTime; @@ -151,7 +183,7 @@ namespace Barotrauma { if (particleHull == hull || particleHull==null) return; - if (particleHull.FireSources.Find(fs => pos.X > fs.position.X && pos.X < fs.position.X+fs.size.X)!=null) return; + if (particleHull.FireSources.Find(fs => pos.X > fs.position.X-100.0f && pos.X < fs.position.X+fs.size.X+100.0f)!=null) return; new FireSource(new Vector2(pos.X, particleHull.Rect.Y-particleHull.Rect.Height + 5.0f)); } @@ -164,11 +196,17 @@ namespace Barotrauma { if (c.AnimController.CurrentHull == null) continue; - float range = (float)Math.Sqrt(size.X) * 10.0f; + float range = (float)Math.Sqrt(size.X) * 20.0f; if (c.Position.X < position.X - range || c.Position.X > position.X + size.X + range) continue; if (c.Position.Y < position.Y - size.Y || c.Position.Y > hull.Rect.Y) continue; - c.Health -= (float)Math.Sqrt(size.X) * deltaTime; + float dmg = (float)Math.Sqrt(size.X) * deltaTime / c.AnimController.Limbs.Count(); + foreach (Limb limb in c.AnimController.Limbs) + { + if (limb.WearingItem != null && limb.WearingItem.Item.FireProof) continue; + limb.Burnt += dmg * 10.0f; + c.AddDamage(limb.SimPosition, DamageType.None, dmg, 0,0,false); + } } } @@ -179,20 +217,21 @@ namespace Barotrauma foreach (Item item in Item.ItemList) { if (item.CurrentHull != hull || item.FireProof || item.Condition <= 0.0f) continue; + if (item.inventory != null) return; float range = (float)Math.Sqrt(size.X) * 10.0f; if (item.Position.X < position.X - range || item.Position.X > position.X + size.X + range) continue; if (item.Position.Y < position.Y - size.Y || item.Position.Y > hull.Rect.Y) continue; - item.Condition -= (float)Math.Sqrt(size.X) * deltaTime; + //item.Condition -= (float)Math.Sqrt(size.X) * deltaTime; item.ApplyStatusEffects(ActionType.OnFire, deltaTime); } } - private void Extinquish(float deltaTime) + private void HullWaterExtinquish(float deltaTime) { - float extinquishAmount = Math.Min(hull.Volume / 100.0f, size.X); + float extinquishAmount = Math.Min(hull.Volume / 100.0f, size.X)*10.0f*deltaTime; float steamCount = Rand.Range(-5.0f, (float)Math.Sqrt(extinquishAmount)); @@ -210,16 +249,50 @@ namespace Barotrauma particle.Size *= MathHelper.Clamp(size.X / 10.0f, 0.5f, 3.0f); } - position.X += extinquishAmount * 0.1f / 2.0f; - size.X -= extinquishAmount * 0.1f; + position.X += extinquishAmount / 2.0f; + size.X -= extinquishAmount; hull.Volume -= extinquishAmount; if (size.X < 1.0f) Remove(); } - public void Remove() + public void Extinquish(float deltaTime, float amount, Vector2 pos) { + float range = 100.0f; + + if (pos.X < position.X-range || pos.X > position.X + size.X+range) return; + if (pos.Y < position.Y - size.Y || pos.Y > position.Y + 500.0f) return; + + float extinquishAmount = amount * deltaTime; + + float steamCount = Rand.Range(-5.0f, (float)Math.Sqrt(amount)); + for (int i = 0; i < steamCount; i++) + { + Vector2 spawnPos = new Vector2(pos.X + Rand.Range(-5.0f, 5.0f), Rand.Range(position.Y - size.Y, position.Y) + 10.0f); + + Vector2 speed = new Vector2((spawnPos.X - (position.X + size.X / 2.0f)), (float)Math.Sqrt(size.X) * Rand.Range(20.0f, 25.0f)); + + var particle = GameMain.ParticleManager.CreateParticle("steam", + spawnPos, speed, 0.0f, hull); + + if (particle == null) continue; + + particle.Size *= MathHelper.Clamp(size.X / 10.0f, 0.5f, 3.0f); + } + + position.X += extinquishAmount / 2.0f; + size.X -= extinquishAmount; + + hull.Volume -= extinquishAmount; + + if (size.X < 1.0f) Remove(); + } + + public void Remove(bool isNetworkEvent = false) + { + if (!isNetworkEvent && GameMain.Client != null) return; + lightSource.Remove(); if (basicSoundIndex > -1) Sounds.SoundManager.Stop(basicSoundIndex); diff --git a/Subsurface/Source/Map/Gap.cs b/Subsurface/Source/Map/Gap.cs index 83e05e1f0..5f6eeb680 100644 --- a/Subsurface/Source/Map/Gap.cs +++ b/Subsurface/Source/Map/Gap.cs @@ -172,7 +172,7 @@ namespace Barotrauma //} } - public override void Draw(SpriteBatch sb, bool editing) + public override void Draw(SpriteBatch sb, bool editing, bool back = true) { if (GameMain.DebugDraw) { diff --git a/Subsurface/Source/Map/Hull.cs b/Subsurface/Source/Map/Hull.cs index 9ad2b00f0..36c8dbce2 100644 --- a/Subsurface/Source/Map/Hull.cs +++ b/Subsurface/Source/Map/Hull.cs @@ -212,9 +212,13 @@ namespace Barotrauma hullList.Remove(this); } - public void AddFireSource(FireSource fireSource) + public void AddFireSource(FireSource fireSource, bool createNetworkEvent = true) { fireSources.Add(fireSource); + if (createNetworkEvent) + { + new Networking.NetworkEvent(Networking.NetworkEventType.ImportantEntityUpdate, this.ID, false); + } } public override void Update(Camera cam, float deltaTime) @@ -327,12 +331,21 @@ namespace Barotrauma } } + public void Extinquish(float deltaTime, float amount, Vector2 position) + { + for (int i = fireSources.Count - 1; i >= 0; i-- ) + { + fireSources[i].Extinquish(deltaTime, amount, position); + } + } + public void RemoveFire(FireSource fire) { fireSources.Remove(fire); + new Networking.NetworkEvent(Networking.NetworkEventType.ImportantEntityUpdate, this.ID, false); } - public override void Draw(SpriteBatch spriteBatch, bool editing) + public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) { if (!editing && !GameMain.DebugDraw) return; @@ -533,6 +546,16 @@ namespace Barotrauma { message.WriteRangedSingle(MathHelper.Clamp(volume/FullVolume, 0.0f, 1.5f), 0.0f, 1.5f, 6); + message.Write((byte)fireSources.Count, 4); + foreach (FireSource fireSource in fireSources) + { + Vector2 normalizedPos = new Vector2( + (fireSource.Position.X - rect.X) / rect.Width, + (fireSource.Position.Y - (rect.Y - rect.Height))/rect.Height); + message.WriteRangedSingle(MathHelper.Clamp(normalizedPos.X, 0.0f, 1.0f), 0.0f, 1.0f, 4); + message.WriteRangedSingle(MathHelper.Clamp(normalizedPos.Y, 0.0f, 1.0f), 0.0f, 1.0f, 4); + } + return true; } @@ -554,6 +577,44 @@ namespace Barotrauma } Volume = newVolume; + + int fireSourceCount = message.ReadByte(4); + + List newFireSources = new List(); + for (int i = 0; i < fireSourceCount; i++) + { + Vector2 pos = Vector2.Zero; + pos.X = message.ReadRangedSingle(0.0f, 1.0f, 4); + pos.Y = message.ReadRangedSingle(0.0f, 1.0f, 4); + if (!MathUtils.IsValid(pos)) continue; + + pos.X = MathHelper.Clamp(pos.X, 0.05f, 0.95f); + pos.Y = MathHelper.Clamp(pos.Y, 0.05f, 0.95f); + + pos = new Vector2(rect.X + rect.Width * pos.X, rect.Y - rect.Height + (rect.Height * pos.Y)); + + var existingFire = fireSources.Find(fs => fs.Contains(pos)); + if (existingFire!=null) + { + newFireSources.Add(existingFire); + existingFire.Position = pos; + } + else + { + var newFire = new FireSource(pos, this, true); + + //ignore if the fire wasn't added to this room (invalid position)? + if (!fireSources.Contains(newFire)) continue; + newFireSources.Add(newFire); + } + } + + var toBeRemoved = fireSources.FindAll(fs => !newFireSources.Contains(fs)); + for (int i = toBeRemoved.Count - 1; i >= 0; i--) + { + toBeRemoved[i].Remove(true); + } + fireSources = newFireSources; } diff --git a/Subsurface/Source/Map/MapEntity.cs b/Subsurface/Source/Map/MapEntity.cs index 59f7a50f7..281d9f506 100644 --- a/Subsurface/Source/Map/MapEntity.cs +++ b/Subsurface/Source/Map/MapEntity.cs @@ -172,7 +172,7 @@ namespace Barotrauma mapEntityList.Insert(i, this); } - public virtual void Draw(SpriteBatch spriteBatch, bool editing) {} + public virtual void Draw(SpriteBatch spriteBatch, bool editing, bool back=true) {} public override void Remove() { diff --git a/Subsurface/Source/Map/Structure.cs b/Subsurface/Source/Map/Structure.cs index 606ea60ae..56bec7748 100644 --- a/Subsurface/Source/Map/Structure.cs +++ b/Subsurface/Source/Map/Structure.cs @@ -284,7 +284,7 @@ namespace Barotrauma } - public override void Draw(SpriteBatch spriteBatch, bool editing) + public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) { if (prefab.sprite == null) return; diff --git a/Subsurface/Source/Map/WayPoint.cs b/Subsurface/Source/Map/WayPoint.cs index b04631f1a..cae9a77b7 100644 --- a/Subsurface/Source/Map/WayPoint.cs +++ b/Subsurface/Source/Map/WayPoint.cs @@ -61,7 +61,7 @@ namespace Barotrauma } - public override void Draw(SpriteBatch spriteBatch, bool editing) + public override void Draw(SpriteBatch spriteBatch, bool editing, bool back=true) { if (!editing && !GameMain.DebugDraw) return; diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index 98b0b11ff..e704debdb 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -207,12 +207,16 @@ namespace Barotrauma.Networking { myID = inc.ReadInt32(); gameStarted = inc.ReadBoolean(); - if (gameStarted && Screen.Selected != GameMain.GameScreen) - { - new GUIMessageBox("Please wait", "A round is already running. You will have to wait for a new round to start."); - } - bool hasCharacter = inc.ReadBoolean(); + bool allowSpectating = inc.ReadBoolean(); + + if (gameStarted && Screen.Selected != GameMain.GameScreen) + { + new GUIMessageBox("Please wait", + (allowSpectating) ? + "A round is already running, but you can spectate the game while waiting for a new one to start." : + "A round is already running and the admin has disabled spectating. You will have to wait for a new round to start."); + } if (gameStarted && !hasCharacter && myCharacter!=null) { @@ -221,6 +225,7 @@ namespace Barotrauma.Networking new GUIMessageBox("Connection timed out", "You were disconnected for too long and your Character was deleted. Please wait for another round to start."); } + GameMain.NetLobbyScreen.ClearPlayers(); //add the names of other connected clients to the lobby screen @@ -686,6 +691,8 @@ namespace Barotrauma.Networking client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered); + if (button != null) button.Enabled = false; + return false; } diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index ddfbaafd8..e58c7b9f2 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -362,6 +362,7 @@ namespace Barotrauma.Networking outmsg.Write(sender.ID); outmsg.Write(gameStarted); outmsg.Write(gameStarted && sender.Character!=null); + outmsg.Write(allowSpectating); //notify the client about other clients already logged in outmsg.Write((characterInfo == null) ? ConnectedClients.Count - 1 : ConnectedClients.Count); @@ -461,12 +462,13 @@ namespace Barotrauma.Networking Voting.RegisterVote(inc, ConnectedClients); break; case (byte)PacketTypes.SpectateRequest: - if (gameStarted) + if (gameStarted && allowSpectating) { var startMessage = CreateStartMessage(roundStartSeed, Submarine.Loaded, GameMain.GameSession.gameMode.Preset); server.SendMessage(startMessage, inc.SenderConnection, NetDeliveryMethod.ReliableUnordered); dataSender.Spectating = true; + CoroutineManager.StartCoroutine(SyncSpectator(dataSender)); } break; } @@ -605,11 +607,14 @@ namespace Barotrauma.Networking } - private void SendNetworkEvents() + private void SendNetworkEvents(List recipients = null) { if (NetworkEvent.Events.Count == 0) return; - List recipients = ConnectedClients.FindAll(c => c.Character != null || c.Spectating); + if (recipients == null) + { + recipients = ConnectedClients.FindAll(c => c.Character != null || c.Spectating); + } if (recipients.Count == 0) return; @@ -635,6 +640,41 @@ namespace Barotrauma.Networking NetworkEvent.Events.Clear(); } + private IEnumerable SyncSpectator(Client sender) + { + yield return new WaitForSeconds(3.0f); + + var existingEvents = NetworkEvent.Events; + NetworkEvent.Events.Clear(); + foreach (Hull hull in Hull.hullList) + { + if (!hull.FireSources.Any() && hull.Volume < 0.01f) continue; + new NetworkEvent(NetworkEventType.ImportantEntityUpdate, hull.ID, false); + } + + SendNetworkEvents(new List() { sender }); + + foreach (Character c in Character.CharacterList) + { + new NetworkEvent(NetworkEventType.EntityUpdate, c.ID, false); + if (c.Inventory != null) new NetworkEvent(NetworkEventType.InventoryUpdate, c.ID, false); + if (c.IsDead) new NetworkEvent(NetworkEventType.KillCharacter, c.ID, false); + } + + SendNetworkEvents(new List() { sender }); + + foreach (Item item in Item.ItemList) + { + if (item.body == null || item.body.Enabled == false) continue; + new NetworkEvent(NetworkEventType.DropItem, item.ID, false); + } + + SendNetworkEvents(new List() { sender }); + + + yield return CoroutineStatus.Success; + } + public bool StartGameClicked(GUIButton button, object obj) { diff --git a/Subsurface/Source/Networking/GameServerSettings.cs b/Subsurface/Source/Networking/GameServerSettings.cs index 401c665a4..7c5b05e3b 100644 --- a/Subsurface/Source/Networking/GameServerSettings.cs +++ b/Subsurface/Source/Networking/GameServerSettings.cs @@ -34,6 +34,8 @@ namespace Barotrauma.Networking private bool autoRestart; + private bool allowSpectating = true; + public bool AutoRestart { get { return (ConnectedClients.Count == 0) ? false : autoRestart; } @@ -65,6 +67,11 @@ namespace Barotrauma.Networking get { return banList; } } + public bool AllowSpectating + { + get { return allowSpectating; } + } + private void CreateSettingsFrame() { settingsFrame = new GUIFrame(new Rectangle(0,0,GameMain.GraphicsWidth,GameMain.GraphicsHeight), Color.Black*0.5f); @@ -94,6 +101,13 @@ namespace Barotrauma.Networking selectionTick.UserData = (SelectionMode)i; } + + var allowSpecBox = new GUITickBox(new Rectangle(0, 0, 20, 20), "Allow spectating", Alignment.Left, innerFrame); + allowSpecBox.Selected = true; + allowSpecBox.OnSelected = ToggleAllowSpectating; + + + var closeButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Close", Alignment.BottomRight, GUI.Style, innerFrame); closeButton.OnClicked = ToggleSettingsFrame; } @@ -144,6 +158,12 @@ namespace Barotrauma.Networking return true; } + private bool ToggleAllowSpectating(GUITickBox tickBox) + { + allowSpectating = tickBox.Selected; + return true; + } + public bool ToggleSettingsFrame(GUIButton button, object obj) { if (settingsFrame==null) diff --git a/Subsurface/Source/Particles/Particle.cs b/Subsurface/Source/Particles/Particle.cs index f335ba4b4..63ada622c 100644 --- a/Subsurface/Source/Particles/Particle.cs +++ b/Subsurface/Source/Particles/Particle.cs @@ -68,6 +68,7 @@ namespace Barotrauma.Particles public void Init(ParticlePrefab prefab, Vector2 position, Vector2 speed, float rotation, Hull hullGuess = null) { + this.prefab = prefab; spriteIndex = Rand.Int(prefab.Sprites.Count); @@ -77,7 +78,8 @@ namespace Barotrauma.Particles drawPosition = position; - velocity = speed; + + velocity = MathUtils.IsValid(speed) ? speed : Vector2.Zero; this.rotation = rotation + Rand.Range(prefab.StartRotationMin, prefab.StartRotationMax); prevRotation = rotation; @@ -172,12 +174,12 @@ namespace Barotrauma.Particles if (!gap.isHorizontal) { if (gap.Rect.X > position.X || gap.Rect.Right < position.X) continue; - if (Math.Sign(velocity.Y) != Math.Sign(gap.Rect.Y - position.Y)) continue; + if (Math.Sign(velocity.Y) != Math.Sign(gap.Rect.Y - (currentHull.Rect.Y-currentHull.Rect.Height))) continue; } else { if (gap.Rect.Y < position.Y || gap.Rect.Y - gap.Rect.Height > position.Y) continue; - if (Math.Sign(velocity.X) != Math.Sign(gap.Rect.X - position.X)) continue; + if (Math.Sign(velocity.X) != Math.Sign(gap.Rect.Center.X - currentHull.Rect.Center.X)) continue; } //Rectangle enlargedRect = new Rectangle(gap.Rect.X - 10, gap.Rect.Y + 10, gap.Rect.Width + 20, gap.Rect.Height + 20); @@ -221,9 +223,7 @@ namespace Barotrauma.Particles } private void OnWallCollision(Hull prevHull, Vector2 position) - { - float restitution = 0.5f; - + { if (position.Y < prevHull.Rect.Y - prevHull.Rect.Height) { position.Y = prevHull.Rect.Y - prevHull.Rect.Height + 1.0f; @@ -247,7 +247,7 @@ namespace Barotrauma.Particles velocity.X = -velocity.X; } - velocity *= restitution; + velocity *= prefab.Restitution; } public void Draw(SpriteBatch spriteBatch) diff --git a/Subsurface/Source/Particles/ParticleManager.cs b/Subsurface/Source/Particles/ParticleManager.cs index e63e8e780..00f52e95d 100644 --- a/Subsurface/Source/Particles/ParticleManager.cs +++ b/Subsurface/Source/Particles/ParticleManager.cs @@ -49,13 +49,19 @@ namespace Barotrauma.Particles public Particle CreateParticle(string prefabName, Vector2 position, float angle, float speed) { - return CreateParticle(prefabName, position, new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)) * speed, angle); + return CreateParticle(prefabName, position, new Vector2((float)Math.Cos(angle), (float)-Math.Sin(angle)) * speed, angle); } public Particle CreateParticle(string prefabName, Vector2 position, Vector2 speed, float rotation=0.0f, Hull hullGuess = null) { ParticlePrefab prefab = FindPrefab(prefabName); + if (prefab == null) + { + DebugConsole.ThrowError("Particle prefab ''" + prefabName+"'' not found!"); + return null; + } + return CreateParticle(prefab, position, speed, rotation, hullGuess); } diff --git a/Subsurface/Source/Particles/ParticlePrefab.cs b/Subsurface/Source/Particles/ParticlePrefab.cs index 7ac47323f..8b1b1e540 100644 --- a/Subsurface/Source/Particles/ParticlePrefab.cs +++ b/Subsurface/Source/Particles/ParticlePrefab.cs @@ -33,6 +33,8 @@ namespace Barotrauma.Particles public readonly bool DeleteOnCollision; public readonly bool CollidesWithWalls; + public readonly float Restitution; + public readonly Vector2 VelocityChange; public readonly DrawTargetType DrawTarget; @@ -87,6 +89,8 @@ namespace Barotrauma.Particles SizeChangeMax = SizeChangeMin; } + Restitution = ToolBox.GetAttributeFloat(element, "restitution", 0.5f); + switch (ToolBox.GetAttributeString(element, "blendstate", "alphablend")) { case "alpha": diff --git a/Subsurface/Source/Program.cs b/Subsurface/Source/Program.cs index dd2d14c37..41400c501 100644 --- a/Subsurface/Source/Program.cs +++ b/Subsurface/Source/Program.cs @@ -28,19 +28,19 @@ namespace Barotrauma { using (var game = new GameMain()) { -#if !DEBUG +//#if !DEBUG try { -#endif +//#endif game.Run(); -#if !DEBUG +//#if !DEBUG } catch (Exception e) { CrashDump(game, "crashreport.txt", e); } -#endif +//#endif } } diff --git a/Subsurface/Source/Screens/GameScreen.cs b/Subsurface/Source/Screens/GameScreen.cs index b8faa7b55..f53399678 100644 --- a/Subsurface/Source/Screens/GameScreen.cs +++ b/Subsurface/Source/Screens/GameScreen.cs @@ -255,7 +255,13 @@ namespace Barotrauma null, DepthStencilState.DepthRead, null, null, cam.Transform); GameMain.ParticleManager.Draw(spriteBatch, true, Particles.ParticleBlendState.AlphaBlend); + spriteBatch.End(); + spriteBatch.Begin(SpriteSortMode.Immediate, + BlendState.Additive, + null, DepthStencilState.DepthRead, null, null, + cam.Transform); + GameMain.ParticleManager.Draw(spriteBatch, true, Particles.ParticleBlendState.Additive); spriteBatch.End(); //---------------------------------------------------------------------------------------- diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index e49c6e13f..2aac01813 100644 Binary files a/Subsurface_Solution.v12.suo and b/Subsurface_Solution.v12.suo differ