diff --git a/Subsurface/Content/Characters/Crawler/crawler.xml b/Subsurface/Content/Characters/Crawler/crawler.xml index 38b7e8b3a..f34cde953 100644 --- a/Subsurface/Content/Characters/Crawler/crawler.xml +++ b/Subsurface/Content/Characters/Crawler/crawler.xml @@ -14,17 +14,17 @@ flip="true"> - + - + - + diff --git a/Subsurface/Content/Characters/Mantis/mantis.xml b/Subsurface/Content/Characters/Mantis/mantis.xml index e6101c656..31f0db1c2 100644 --- a/Subsurface/Content/Characters/Mantis/mantis.xml +++ b/Subsurface/Content/Characters/Mantis/mantis.xml @@ -16,22 +16,22 @@ flip="true"> - + - + - + - + @@ -44,7 +44,7 @@ - + diff --git a/Subsurface/Content/Characters/Moloch/moloch.xml b/Subsurface/Content/Characters/Moloch/moloch.xml index 05db8ab13..d9168a7ab 100644 --- a/Subsurface/Content/Characters/Moloch/moloch.xml +++ b/Subsurface/Content/Characters/Moloch/moloch.xml @@ -9,7 +9,7 @@ - + diff --git a/Subsurface/Content/Items/Clothes/clothes.xml b/Subsurface/Content/Items/Clothes/clothes.xml index e5cc154a9..e52fef947 100644 --- a/Subsurface/Content/Items/Clothes/clothes.xml +++ b/Subsurface/Content/Items/Clothes/clothes.xml @@ -52,5 +52,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Subsurface/Content/Items/Clothes/securitygear.png b/Subsurface/Content/Items/Clothes/securitygear.png new file mode 100644 index 000000000..d9e3c67c7 Binary files /dev/null and b/Subsurface/Content/Items/Clothes/securitygear.png differ diff --git a/Subsurface/Content/Items/Diving/divinggear.xml b/Subsurface/Content/Items/Diving/divinggear.xml index 27a88df32..13408a945 100644 --- a/Subsurface/Content/Items/Diving/divinggear.xml +++ b/Subsurface/Content/Items/Diving/divinggear.xml @@ -46,7 +46,7 @@ - + diff --git a/Subsurface/Content/Items/Electricity/poweritems.xml b/Subsurface/Content/Items/Electricity/poweritems.xml index fb0260648..69a93d797 100644 --- a/Subsurface/Content/Items/Electricity/poweritems.xml +++ b/Subsurface/Content/Items/Electricity/poweritems.xml @@ -1,11 +1,11 @@  - - - + + + @@ -17,33 +17,41 @@ - - - + + + + + + + + - + - + - + - - - - - + + + + + + + + + + + - - - \ No newline at end of file diff --git a/Subsurface/Content/Items/Tools/tools.xml b/Subsurface/Content/Items/Tools/tools.xml index 3edec139d..95cc3ae5b 100644 --- a/Subsurface/Content/Items/Tools/tools.xml +++ b/Subsurface/Content/Items/Tools/tools.xml @@ -32,10 +32,7 @@ - - - - + @@ -73,9 +70,7 @@ - - - + diff --git a/Subsurface/Content/Map/StructurePrefabs.xml b/Subsurface/Content/Map/StructurePrefabs.xml index fd28129fd..2dfff52c7 100644 --- a/Subsurface/Content/Map/StructurePrefabs.xml +++ b/Subsurface/Content/Map/StructurePrefabs.xml @@ -1,18 +1,18 @@ - - - - - - - - + + \ No newline at end of file diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 969af89cf..f5a58ec55 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -15,6 +15,7 @@ using System.Xml.Linq; namespace Subsurface { + class Character : Entity, IDamageable, IPropertyObject { public static List CharacterList = new List(); @@ -170,6 +171,12 @@ namespace Subsurface } } + public float Stun + { + get { return AnimController.StunTimer; } + set { StartStun(value); } + } + public float Health { get @@ -873,8 +880,7 @@ namespace Subsurface public AttackResult AddDamage(Vector2 simPosition, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound) { - AnimController.StunTimer = Math.Max(AnimController.StunTimer, stun); - + StartStun(stun); if (controlled == this) CharacterHUD.TakeDamage(); Limb closestLimb = null; @@ -901,14 +907,11 @@ namespace Subsurface return attackResult; } - public void Stun() + public void StartStun(float stunTimer) { - //for (int i = 0; i < selectedItems.Length; i++ ) - //{ - // if (selectedItems[i] == null) continue; - // selectedItems[i].Drop(); - // selectedItems[i] = null; - //} + if (stunTimer <= 0.0f) return; + + AnimController.StunTimer = Math.Max(AnimController.StunTimer, stunTimer); selectedConstruction = null; } @@ -1268,7 +1271,7 @@ namespace Subsurface } catch { return; } - AnimController.StunTimer = newStunTimer; + StartStun(newStunTimer); Health = newHealth; LargeUpdateTimer = 1; diff --git a/Subsurface/Source/Characters/HumanoidAnimController.cs b/Subsurface/Source/Characters/HumanoidAnimController.cs index bd4b58030..cc79e911a 100644 --- a/Subsurface/Source/Characters/HumanoidAnimController.cs +++ b/Subsurface/Source/Characters/HumanoidAnimController.cs @@ -125,8 +125,7 @@ namespace Subsurface //stun (= disable the animations) if the ragdoll receives a large enough impact if (strongestImpact > 0.0f) { - character.Stun(); - stunTimer = MathHelper.Clamp(strongestImpact * 0.5f, stunTimer, 5.0f); + character.StartStun(MathHelper.Min(strongestImpact * 0.5f, 5.0f)); } strongestImpact = 0.0f; diff --git a/Subsurface/Source/Characters/Limb.cs b/Subsurface/Source/Characters/Limb.cs index 741f0b130..d76166327 100644 --- a/Subsurface/Source/Characters/Limb.cs +++ b/Subsurface/Source/Characters/Limb.cs @@ -62,7 +62,7 @@ namespace Subsurface private Direction dir; - private Item wearingItem; + private Wearable wearingItem; private WearableSprite wearingItemSprite; private Vector2 animTargetPos; @@ -92,6 +92,7 @@ namespace Subsurface get { return body.Rotation; } } + //where an animcontroller is trying to pull the limb, only used for debug visualization public Vector2 AnimTargetPos { get { return animTargetPos; } @@ -156,7 +157,7 @@ namespace Subsurface // set { bleeding = MathHelper.Clamp(value, 0.0f, 100.0f); } //} - public Item WearingItem + public Wearable WearingItem { get { return wearingItem; } set { wearingItem = value; } @@ -238,7 +239,7 @@ namespace Subsurface armorSector.X = MathHelper.ToRadians(armorSector.X); armorSector.Y = MathHelper.ToRadians(armorSector.Y); - armorValue = Math.Max(ToolBox.GetAttributeFloat(element, "armor", 1.0f), 1.0f); + armorValue = Math.Max(ToolBox.GetAttributeFloat(element, "armor", 0.0f), 0.0f); body.BodyType = BodyType.Dynamic; body.FarseerBody.AngularDamping = LimbAngularDamping; @@ -290,27 +291,33 @@ namespace Subsurface DamageSoundType damageSoundType = (damageType == DamageType.Blunt) ? DamageSoundType.LimbBlunt : DamageSoundType.LimbSlash; bool hitArmor = false; - if (armorSector != Vector2.Zero) + float totalArmorValue = 0.0f; + + if (armorValue>0.0f && SectorHit(armorSector, simPosition)) { - float rot = body.Rotation; - if (Dir == -1) rot -= MathHelper.Pi; - - Vector2 armorLimits = new Vector2(rot-armorSector.X*Dir, rot-armorSector.Y*Dir); - - float mid = (armorLimits.X + armorLimits.Y) / 2.0f; - - float angleDiff = MathUtils.GetShortestAngle(MathUtils.VectorToAngle(simPosition - SimPosition), mid); - - if (Math.Abs(angleDiff) < (armorSector.Y - armorSector.X) / 2.0f) - { - hitArmor = true; - damageSoundType = DamageSoundType.LimbArmor; - amount /= armorValue; - bleedingAmount /= armorValue; - } + hitArmor = true; + totalArmorValue += armorValue; } - if (playSound && amount>0.0f) + if (wearingItem!=null && + wearingItem.ArmorValue>0.0f && + SectorHit(wearingItem.ArmorSectorLimits, simPosition)) + { + hitArmor = true; + totalArmorValue += wearingItem.ArmorValue; + } + + if (hitArmor) + { + totalArmorValue = Math.Max(totalArmorValue, 0.0f); + + damageSoundType = DamageSoundType.LimbArmor; + amount = Math.Max(0.0f, amount - totalArmorValue); + bleedingAmount = Math.Max(0.0f, bleedingAmount - totalArmorValue); ; + } + + + if (playSound) { AmbientSoundManager.PlayDamageSound(damageSoundType, amount, ConvertUnits.ToDisplayUnits(simPosition)); } @@ -338,6 +345,21 @@ namespace Subsurface return new AttackResult(amount, bleedingAmount, hitArmor); } + public bool SectorHit(Vector2 armorSector, Vector2 simPosition) + { + if (armorSector == Vector2.Zero) return false; + + float rot = body.Rotation; + if (Dir == -1) rot -= MathHelper.Pi; + + Vector2 armorLimits = new Vector2(rot - armorSector.X * Dir, rot - armorSector.Y * Dir); + + float mid = (armorLimits.X + armorLimits.Y) / 2.0f; + float angleDiff = MathUtils.GetShortestAngle(MathUtils.VectorToAngle(simPosition - SimPosition), mid); + + return (Math.Abs(angleDiff) < (armorSector.Y - armorSector.X) / 2.0f); + } + public void Update(float deltaTime) { if (LinearVelocity.X>100.0f) @@ -416,7 +438,7 @@ namespace Subsurface float depth = sprite.Depth - 0.000001f; - if (wearingItemSprite.DepthLimb==LimbType.None) + if (wearingItemSprite.DepthLimb!=LimbType.None) { Limb depthLimb = character.AnimController.GetLimb(wearingItemSprite.DepthLimb); if (depthLimb!=null) diff --git a/Subsurface/Source/Characters/StatusEffect.cs b/Subsurface/Source/Characters/StatusEffect.cs index 8854ba914..60fd2f13d 100644 --- a/Subsurface/Source/Characters/StatusEffect.cs +++ b/Subsurface/Source/Characters/StatusEffect.cs @@ -228,6 +228,7 @@ namespace Subsurface if (type == typeof(float)) { float floatValue = (float)value * deltaTime; + if (!setValue) floatValue += (float)property.GetValue(); property.TrySetValue(floatValue); } @@ -253,7 +254,6 @@ namespace Subsurface { DelayedEffect.List[i].Update(deltaTime); } - } - + } } } diff --git a/Subsurface/Source/GUI/GUI.cs b/Subsurface/Source/GUI/GUI.cs index 8ae08d3d6..274826e1c 100644 --- a/Subsurface/Source/GUI/GUI.cs +++ b/Subsurface/Source/GUI/GUI.cs @@ -49,7 +49,7 @@ namespace Subsurface graphicsDevice = graphics; sounds = new Sound[2]; - sounds[0] = Sound.Load("Content/Sounds/UI/UImsg.ogg"); + sounds[0] = Sound.Load("Content/Sounds/UI/UImsg.ogg", false); // create 1x1 texture for line drawing t = new Texture2D(graphicsDevice, 1, 1); diff --git a/Subsurface/Source/GameSession/GameSession.cs b/Subsurface/Source/GameSession/GameSession.cs index 0023de375..08b279630 100644 --- a/Subsurface/Source/GameSession/GameSession.cs +++ b/Subsurface/Source/GameSession/GameSession.cs @@ -138,7 +138,8 @@ namespace Subsurface } else if (GameMain.Client==null) - { + { + Submarine.Unload(); GameMain.LobbyScreen.Select(); } diff --git a/Subsurface/Source/Items/Components/Holdable/RangedWeapon.cs b/Subsurface/Source/Items/Components/Holdable/RangedWeapon.cs index fdc1c33b8..9af04c513 100644 --- a/Subsurface/Source/Items/Components/Holdable/RangedWeapon.cs +++ b/Subsurface/Source/Items/Components/Holdable/RangedWeapon.cs @@ -56,8 +56,6 @@ namespace Subsurface.Items.Components if (!character.GetInputState(InputType.SecondaryHeld) || reload > 0.0f) return false; isActive = true; reload = 1.0f; - - bool failed = DoesUseFail(character); List limbBodies = new List(); foreach (Limb l in character.AnimController.Limbs) @@ -68,6 +66,15 @@ namespace Subsurface.Items.Components Item[] containedItems = item.ContainedItems; if (containedItems == null || !containedItems.Any()) return false; + float degreeOfFailure = (100.0f - DegreeOfSuccess(character))/100.0f; + + degreeOfFailure *= degreeOfFailure; + + if (degreeOfFailure > Rand.Range(0.0f, 1.0f)) + { + ApplyStatusEffects(ActionType.OnFailure, 1.0f, character); + } + foreach (Item projectile in containedItems) { if (projectile == null) continue; @@ -76,35 +83,28 @@ namespace Subsurface.Items.Components //so that the player can't shoot himself Projectile projectileComponent= projectile.GetComponent(); if (projectileComponent == null) continue; - + projectile.body.ResetDynamics(); projectile.SetTransform(TransformedBarrelPos, - (item.body.Dir == 1.0f) ? item.body.Rotation : item.body.Rotation - MathHelper.Pi); + ((item.body.Dir == 1.0f) ? item.body.Rotation : item.body.Rotation - MathHelper.Pi) + + Rand.Range(-degreeOfFailure, degreeOfFailure)); projectile.Use(deltaTime); - - if (failed) - { - Vector2 modifiedVelocity = projectile.body.LinearVelocity; - modifiedVelocity.X *= Rand.Range(0.0f, 0.5f); - modifiedVelocity.Y *= Rand.Range(0.0f, 0.5f); - - projectile.body.LinearVelocity = modifiedVelocity; - projectile.body.ApplyTorque(projectile.body.Mass * Rand.Range(-10.0f, 10.0f)); + projectile.body.ApplyTorque(projectile.body.Mass * degreeOfFailure * Rand.Range(-10.0f, 10.0f)); //recoil - //item.body.ApplyLinearImpulse( - // new Vector2((float)Math.Cos(projectile.body.Rotation), (float)Math.Sin(projectile.body.Rotation)) * item.body.Mass * -10.0f); - } - else - { + item.body.ApplyLinearImpulse( + new Vector2((float)Math.Cos(projectile.body.Rotation), (float)Math.Sin(projectile.body.Rotation)) * item.body.Mass * -50.0f); + + //else + //{ projectileComponent.ignoredBodies = limbBodies; //recoil //item.body.ApplyLinearImpulse( // new Vector2((float)Math.Cos(projectile.body.Rotation), (float)Math.Sin(projectile.body.Rotation)) * -item.body.Mass); - } + //} item.RemoveContained(projectile); diff --git a/Subsurface/Source/Items/Components/Holdable/RepairTool.cs b/Subsurface/Source/Items/Components/Holdable/RepairTool.cs index 39f393c83..5332654d7 100644 --- a/Subsurface/Source/Items/Components/Holdable/RepairTool.cs +++ b/Subsurface/Source/Items/Components/Holdable/RepairTool.cs @@ -104,13 +104,21 @@ namespace Subsurface.Items.Components if (character == null) return false; if (!character.GetInputState(InputType.SecondaryHeld)) return false; - if (DoesUseFail(character)) return false; + //if (DoesUseFail(character)) return false; isActive = true; Vector2 targetPosition = item.body.SimPosition; //targetPosition = targetPosition.X, -targetPosition.Y); + float degreeOfSuccess = DegreeOfSuccess(character); + + if (Rand.Range(0.0f, 1.0f) > degreeOfSuccess * degreeOfSuccess) + { + ApplyStatusEffects(ActionType.OnFailure, 1.0f, character); + return false; + } + targetPosition += new Vector2( (float)Math.Cos(item.body.Rotation), (float)Math.Sin(item.body.Rotation)) * range * item.body.Dir; @@ -118,6 +126,7 @@ namespace Subsurface.Items.Components List ignoredBodies = new List(); foreach (Limb limb in character.AnimController.Limbs) { + if (Rand.Range(0.0f, 1.0f) > degreeOfSuccess) continue; ignoredBodies.Add(limb.body.FarseerBody); } diff --git a/Subsurface/Source/Items/Components/ItemComponent.cs b/Subsurface/Source/Items/Components/ItemComponent.cs index 1888c1c6d..2a1119e5b 100644 --- a/Subsurface/Source/Items/Components/ItemComponent.cs +++ b/Subsurface/Source/Items/Components/ItemComponent.cs @@ -426,24 +426,44 @@ namespace Subsurface.Items.Components return true; } - protected bool DoesUseFail(Character character) + /// + /// Returns 0.0f-1.0f based on how well the character can use the itemcomponent + /// + /// 0.5f if all the skills meet the skill requirements exactly, 1.0f if they're way above and 0.0f if way less + protected float DegreeOfSuccess(Character character) { - foreach (Skill skill in requiredSkills) - { - int characterLevel = character.GetSkillLevel(skill.Name); - if (characterLevel > skill.Level) continue; + if (requiredSkills.Count == 0) return 100.0f; - if (Rand.Int(characterLevel) - skill.Level < 0) - { - item.ApplyStatusEffects(ActionType.OnFailure, 1.0f, character); - //Item.ApplyStatusEffects(); - return true; - } + float[] skillSuccess = new float[requiredSkills.Count]; + + for (int i = 0; i < requiredSkills.Count; i++ ) + { + int characterLevel = character.GetSkillLevel(requiredSkills[i].Name); + + skillSuccess[i] = (characterLevel - requiredSkills[i].Level); } - return false; + float average = skillSuccess.Average(); + + return (average+100.0f)/2.0f; } + //public bool CheckFailure(Character character) + //{ + // foreach (Skill skill in requiredSkills) + // { + // int characterLevel = character.GetSkillLevel(skill.Name); + // if (characterLevel > skill.Level) continue; + + // item.ApplyStatusEffects(ActionType.OnFailure, 1.0f, character); + // //Item.ApplyStatusEffects(); + // return true; + + // } + + // return false; + //} + public bool HasRequiredContainedItems(bool addMessage) { List requiredContained = requiredItems.FindAll(ri=> ri.Type == RelatedItem.RelationType.Contained); diff --git a/Subsurface/Source/Items/Components/Power/Powered.cs b/Subsurface/Source/Items/Components/Power/Powered.cs index 78d841bf8..2ca91e3d8 100644 --- a/Subsurface/Source/Items/Components/Power/Powered.cs +++ b/Subsurface/Source/Items/Components/Power/Powered.cs @@ -72,7 +72,7 @@ namespace Subsurface.Items.Components { if (powerOnSound == null) { - powerOnSound = Sound.Load("Content/Items/Electricity/powerOn.ogg"); + powerOnSound = Sound.Load("Content/Items/Electricity/powerOn.ogg", false); } if (sparkSounds == null) @@ -81,7 +81,7 @@ namespace Subsurface.Items.Components string dir = Path.GetDirectoryName(item.Prefab.ConfigFile) + "\\"; for (int i = 0; i < 4; i++) { - sparkSounds[i] = Sound.Load("Content/Items/Electricity/zap" + (i + 1) + ".ogg"); + sparkSounds[i] = Sound.Load("Content/Items/Electricity/zap" + (i + 1) + ".ogg", false); } } } diff --git a/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs b/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs index 6bdbb62c6..18806c7e3 100644 --- a/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs +++ b/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs @@ -71,6 +71,35 @@ namespace Subsurface.Items.Components return true; } + public override bool Use(float deltaTime, Character character = null) + { + if (character == null || character!=user) return false; + + var powered = item.GetComponent(); + if (powered != null) + { + if (powered.Voltage < 0.1f) return false; + } + + float degreeOfSuccess = DegreeOfSuccess(character); + if (Rand.Range(0.0f, 0.5f) < degreeOfSuccess) return false; + + item.ApplyStatusEffects(ActionType.OnFailure, 1.0f, character); + + //Vector2 baseVel = Rand.Vector(300.0f); + //for (int i = 0; i < 10; i++) + //{ + // var particle = GameMain.ParticleManager.CreateParticle("spark", item.Position, + // baseVel + Rand.Vector(100.0f), 0.0f); + + // if (particle != null) particle.Size *= Rand.Range(0.5f, 1.0f); + //} + + //character.AddDamage(item.SimPosition, DamageType.None, Math.Abs(degreeOfSuccess-100.0f)/10.0f, 0.0f, 3.0f, false); + + return true; + } + public override void Load(XElement element) { base.Load(element); diff --git a/Subsurface/Source/Items/Components/Wearable.cs b/Subsurface/Source/Items/Components/Wearable.cs index 94daa00b9..6b9d18378 100644 --- a/Subsurface/Source/Items/Components/Wearable.cs +++ b/Subsurface/Source/Items/Components/Wearable.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.Xna.Framework; +using System; using System.IO; using System.Linq; using System.Xml.Linq; @@ -26,6 +27,34 @@ namespace Subsurface.Items.Components LimbType[] limbType; Limb[] limb; + private float armorValue; + + private Vector2 armorSector; + + [HasDefaultValue(0.0f, false)] + public float ArmorValue + { + get { return armorValue; } + set { armorValue = MathHelper.Clamp(value, 0.0f, 100.0f); } + } + + [HasDefaultValue("0.0,360.0", false)] + public string ArmorSector + { + get { return ToolBox.Vector2ToString(armorSector); } + set + { + armorSector = ToolBox.ParseToVector2(value); + armorSector.X = MathHelper.ToRadians(armorSector.X); + armorSector.Y = MathHelper.ToRadians(armorSector.Y); + } + } + + public Vector2 ArmorSectorLimits + { + get { return armorSector; } + } + public Wearable (Item item, XElement element) : base(item, element) { @@ -76,7 +105,7 @@ namespace Subsurface.Items.Components if (equipLimb == null) continue; //something is already on the limb -> unequip it - if (equipLimb.WearingItem != null && equipLimb.WearingItem != item) + if (equipLimb.WearingItem != null && equipLimb.WearingItem != this) { equipLimb.WearingItem.Unequip(character); } @@ -88,7 +117,7 @@ namespace Subsurface.Items.Components isActive = true; limb[i] = equipLimb; - equipLimb.WearingItem = item; + equipLimb.WearingItem = this; equipLimb.WearingItemSprite = wearableSprite[i]; } } @@ -111,7 +140,7 @@ namespace Subsurface.Items.Components Limb equipLimb = character.AnimController.GetLimb(limbType[i]); if (equipLimb == null) continue; - if (equipLimb.WearingItem != item) continue; + if (equipLimb.WearingItem != this) continue; limb[i] = null; equipLimb.WearingItem = null; diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs index 4481045ba..07bcbdde3 100644 --- a/Subsurface/Source/Items/Item.cs +++ b/Subsurface/Source/Items/Item.cs @@ -1256,7 +1256,6 @@ namespace Subsurface { ic.Remove(); } - itemList.Remove(this); foreach (Item it in itemList) diff --git a/Subsurface/Source/Map/Explosion.cs b/Subsurface/Source/Map/Explosion.cs index 111117337..2946127ce 100644 --- a/Subsurface/Source/Map/Explosion.cs +++ b/Subsurface/Source/Map/Explosion.cs @@ -19,6 +19,8 @@ namespace Subsurface public float CameraShake; + private bool sparks, shockwave, flames; + //public Explosion(Vector2 position, float range, float damage, float structureDamage, float stun = 0.0f, float force = 0.0f) //{ // this.position = position; @@ -36,6 +38,10 @@ namespace Subsurface force = ToolBox.GetAttributeFloat(element, "force", 0.0f); + sparks = ToolBox.GetAttributeBool(element, "sparks", true); + shockwave = ToolBox.GetAttributeBool(element, "shockwave", true); + flames = ToolBox.GetAttributeBool(element, "flames", true); + CameraShake = attack.Range*10.0f; } @@ -48,16 +54,25 @@ namespace Subsurface { Vector2 displayPosition = ConvertUnits.ToDisplayUnits(simPosition); - GameMain.ParticleManager.CreateParticle("shockwave", displayPosition, - Vector2.Zero, 0.0f); + if (shockwave) + { + GameMain.ParticleManager.CreateParticle("shockwave", displayPosition, + Vector2.Zero, 0.0f); + } + for (int i = 0; i < attack.Range * 10; i++) { - GameMain.ParticleManager.CreateParticle("spark", displayPosition, - Rand.Vector(Rand.Range(500.0f, 800.0f)), 0.0f); - - GameMain.ParticleManager.CreateParticle("explosionfire", displayPosition + Rand.Vector(50f), - Rand.Vector(Rand.Range(50f, 100.0f)), 0.0f); + if (sparks) + { + GameMain.ParticleManager.CreateParticle("spark", displayPosition, + Rand.Vector(Rand.Range(500.0f, 800.0f)), 0.0f); + } + if (flames) + { + GameMain.ParticleManager.CreateParticle("explosionfire", displayPosition + Rand.Vector(50f), + Rand.Vector(Rand.Range(50f, 100.0f)), 0.0f); + } } float displayRange = ConvertUnits.ToDisplayUnits(attack.Range); diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index 2c42bc697..822026e1d 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -607,7 +607,6 @@ namespace Subsurface foreach (Item item in Item.itemList) { - System.Diagnostics.Debug.WriteLine(item.ID); foreach (ItemComponent ic in item.components) { ic.OnMapLoaded(); @@ -634,6 +633,8 @@ namespace Subsurface public static void Unload() { if (loaded == null) return; + + Sound.OnGameEnd(); loaded.Remove(); diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index 67f8a6358..986e32237 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -436,6 +436,9 @@ namespace Subsurface.Networking userID = inc.ReadInt32(); userPassword = inc.ReadString(); version = inc.ReadString(); +#if DEBUG + version = GameMain.Version.ToString(); +#endif packageName = inc.ReadString(); packageHash = inc.ReadString(); name = inc.ReadString(); diff --git a/Subsurface/Source/Properties.cs b/Subsurface/Source/Properties.cs index e27bdf52a..c6aed3039 100644 --- a/Subsurface/Source/Properties.cs +++ b/Subsurface/Source/Properties.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.Globalization; using System.Linq; +using System.Linq.Expressions; +using System.Reflection; using System.Xml.Linq; +using System.ComponentModel; namespace Subsurface @@ -37,12 +39,13 @@ namespace Subsurface this.isSaveable = isSaveable; } } - + class ObjectProperty { readonly PropertyDescriptor property; + readonly PropertyInfo propertyInfo; readonly object obj; - + public string Name { get { return property.Name; } @@ -56,6 +59,7 @@ namespace Subsurface public ObjectProperty(PropertyDescriptor property, object obj) { this.property = property; + propertyInfo = property.ComponentType.GetProperty(property.Name); this.obj = obj; } @@ -65,7 +69,7 @@ namespace Subsurface if (property.PropertyType == typeof(string)) { - property.SetValue(obj, value); + propertyInfo.SetValue(obj, value, null); } else if (property.PropertyType == typeof(float)) { @@ -73,19 +77,19 @@ namespace Subsurface if (float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out floatVal)) { - property.SetValue(obj, floatVal); + propertyInfo.SetValue(obj, floatVal, null); } } else if (property.PropertyType == typeof(bool)) { - property.SetValue(obj, (value.ToLower()=="true")); + propertyInfo.SetValue(obj, (value.ToLower() == "true"), null); } else if (property.PropertyType == typeof(int)) { int intVal = 0; if (int.TryParse(value, out intVal)) { - property.SetValue(obj, intVal); + propertyInfo.SetValue(obj, intVal, null); } } else @@ -114,7 +118,47 @@ namespace Subsurface if (obj == null || property == null) return false; try { - property.SetValue(obj, value); + propertyInfo.SetValue(obj, value, null); + } + catch + { + return false; + } + return true; + } + + public bool TrySetValue(float value) + { + try + { + propertyInfo.SetValue(obj, value, null); + } + catch + { + return false; + } + + return true; + } + + public bool TrySetValue(bool value) + { + try + { + propertyInfo.SetValue(obj, value, null); + } + catch + { + return false; + } + return true; + } + + public bool TrySetValue(int value) + { + try + { + propertyInfo.SetValue(obj, value, null); } catch { @@ -129,7 +173,7 @@ namespace Subsurface try { - return property.GetValue(obj); + return propertyInfo.GetValue(obj, null); } catch { diff --git a/Subsurface/Source/Screens/GameScreen.cs b/Subsurface/Source/Screens/GameScreen.cs index 5fde178e5..83e81e44b 100644 --- a/Subsurface/Source/Screens/GameScreen.cs +++ b/Subsurface/Source/Screens/GameScreen.cs @@ -80,8 +80,7 @@ namespace Subsurface GameMain.ParticleManager.Update((float)deltaTime); StatusEffect.UpdateAll((float)deltaTime); - - + Physics.accumulator = Math.Min(Physics.accumulator, Physics.step * 4); while (Physics.accumulator >= Physics.step) { @@ -147,7 +146,7 @@ namespace Subsurface public void DrawMap(GraphicsDevice graphics, SpriteBatch spriteBatch) { GameMain.LightManager.DrawLightmap(graphics, spriteBatch, cam); - + //---------------------------------------------------------------------------------------- //1. draw the background, characters and the parts of the submarine that are behind them //---------------------------------------------------------------------------------------- diff --git a/Subsurface/Source/Screens/LobbyScreen.cs b/Subsurface/Source/Screens/LobbyScreen.cs index a458f9e78..286a8fecc 100644 --- a/Subsurface/Source/Screens/LobbyScreen.cs +++ b/Subsurface/Source/Screens/LobbyScreen.cs @@ -73,6 +73,7 @@ namespace Subsurface GUIButton button = new GUIButton(new Rectangle(0, 70, 100, 30), "Map", null, Alignment.Left, GUI.Style, leftPanel); button.UserData = PanelTab.Map; button.OnClicked = SelectRightPanel; + SelectRightPanel(button, button.UserData); button = new GUIButton(new Rectangle(0, 110, 100, 30), "Crew", null, Alignment.Left, GUI.Style, leftPanel); button.UserData = PanelTab.Crew; @@ -149,8 +150,6 @@ namespace Subsurface gameMode = GameMain.GameSession.gameMode as SinglePlayerMode; - selectedRightPanel = (int)PanelTab.Crew; - //Map.Unload(); UpdateCharacterLists(); diff --git a/Subsurface/Source/Sounds/AmbientSoundManager.cs b/Subsurface/Source/Sounds/AmbientSoundManager.cs index 84de54632..b2890ef65 100644 --- a/Subsurface/Source/Sounds/AmbientSoundManager.cs +++ b/Subsurface/Source/Sounds/AmbientSoundManager.cs @@ -71,22 +71,22 @@ namespace Subsurface { - startDrone = Sound.Load("Content/Sounds/startDrone.ogg"); + startDrone = Sound.Load("Content/Sounds/startDrone.ogg", false); startDrone.Play(); yield return CoroutineStatus.Running; - waterAmbiences[0] = Sound.Load("Content/Sounds/Water/WaterAmbience1.ogg"); + waterAmbiences[0] = Sound.Load("Content/Sounds/Water/WaterAmbience1.ogg", false); yield return CoroutineStatus.Running; - waterAmbiences[1] = Sound.Load("Content/Sounds/Water/WaterAmbience2.ogg"); + waterAmbiences[1] = Sound.Load("Content/Sounds/Water/WaterAmbience2.ogg", false); yield return CoroutineStatus.Running; - flowSounds[0] = Sound.Load("Content/Sounds/Water/FlowSmall.ogg"); + flowSounds[0] = Sound.Load("Content/Sounds/Water/FlowSmall.ogg", false); yield return CoroutineStatus.Running; - flowSounds[1] = Sound.Load("Content/Sounds/Water/FlowMedium.ogg"); + flowSounds[1] = Sound.Load("Content/Sounds/Water/FlowMedium.ogg", false); yield return CoroutineStatus.Running; - flowSounds[2] = Sound.Load("Content/Sounds/Water/FlowLarge.ogg"); + flowSounds[2] = Sound.Load("Content/Sounds/Water/FlowLarge.ogg", false); yield return CoroutineStatus.Running; XDocument doc = ToolBox.TryLoadXml("Content/Sounds/sounds.xml"); @@ -124,7 +124,7 @@ namespace Subsurface { yield return CoroutineStatus.Running; - Sound sound = Sound.Load(ToolBox.GetAttributeString(element, "file", "")); + Sound sound = Sound.Load(ToolBox.GetAttributeString(element, "file", ""), false); if (sound == null) continue; DamageSoundType damageSoundType = DamageSoundType.None; @@ -155,13 +155,10 @@ namespace Subsurface { UpdateMusic(); - if (startDrone!=null) + if (startDrone!=null && !startDrone.IsPlaying) { - if (!startDrone.IsPlaying) - { - startDrone.Remove(); - startDrone = null; - } + startDrone.Remove(); + startDrone = null; } float ambienceVolume = 0.6f; diff --git a/Subsurface/Source/Sounds/Sound.cs b/Subsurface/Source/Sounds/Sound.cs index ac74d1272..4e831a597 100644 --- a/Subsurface/Source/Sounds/Sound.cs +++ b/Subsurface/Source/Sounds/Sound.cs @@ -21,6 +21,8 @@ namespace Subsurface string filePath; private int alSourceId; + + private bool destroyOnGameEnd; //public float Volume @@ -28,6 +30,25 @@ namespace Subsurface // set { SoundManager.Volume(sourceIndex, value); } //} + private Sound(string file, bool destroyOnGameEnd) + { + filePath = file; + + foreach (Sound loadedSound in loadedSounds) + { + if (loadedSound.filePath == file) oggSound = loadedSound.oggSound; + } + + if (oggSound == null) + { + oggSound = OggSound.Load(file); + } + + this.destroyOnGameEnd = destroyOnGameEnd; + + loadedSounds.Add(this); + } + public string FilePath { get { return filePath; } @@ -43,32 +64,15 @@ namespace Subsurface SoundManager.Init(); } - public static Sound Load(string file) + public static Sound Load(string file, bool destroyOnGameEnd = true) { if (!File.Exists(file)) { DebugConsole.ThrowError("File ''" + file + "'' not found!"); return null; } - - Sound s = new Sound(); - - s.filePath = file; - - foreach (Sound loadedSound in loadedSounds) - { - if (loadedSound.filePath == file) s.oggSound = loadedSound.oggSound; - } - - if (s.oggSound == null) - { - s.oggSound = OggSound.Load(file); - } - - loadedSounds.Add(s); - - return s; + return new Sound(file, destroyOnGameEnd); } public int Play(float volume = 1.0f) @@ -212,12 +216,27 @@ namespace Subsurface //{ // SoundManager.Stop(this); //} + + public static void OnGameEnd() + { + List removableSounds = loadedSounds.FindAll(s => s.destroyOnGameEnd); + + foreach (Sound sound in removableSounds) + { + sound.Remove(); + } + } public void Remove() { loadedSounds.Remove(this); - System.Diagnostics.Debug.WriteLine(AlBufferId); + System.Diagnostics.Debug.WriteLine("Removing sound " + filePath + " (buffer id" + AlBufferId + ")"); + + if (alSourceId>0 && SoundManager.IsPlaying(alSourceId)) + { + SoundManager.Stop(alSourceId); + } foreach (Sound s in loadedSounds) { diff --git a/Subsurface/Subsurface.csproj b/Subsurface/Subsurface.csproj index 9ee136e1e..ef3785d5f 100644 --- a/Subsurface/Subsurface.csproj +++ b/Subsurface/Subsurface.csproj @@ -335,6 +335,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Subsurface_Solution.sln b/Subsurface_Solution.sln index 786e0b01e..895b06759 100644 --- a/Subsurface_Solution.sln +++ b/Subsurface_Solution.sln @@ -396,7 +396,4 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection EndGlobal diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index 72d4d8b01..4ea7d0b8e 100644 Binary files a/Subsurface_Solution.v12.suo and b/Subsurface_Solution.v12.suo differ