diff --git a/Subsurface/Characters/Attack.cs b/Subsurface/Characters/Attack.cs index 650f17a03..ad88c766c 100644 --- a/Subsurface/Characters/Attack.cs +++ b/Subsurface/Characters/Attack.cs @@ -68,7 +68,7 @@ namespace Subsurface damage = ToolBox.GetAttributeFloat(element, "damage", 0.0f); - structureDamage = ToolBox.GetAttributeFloat(element, "damage", 0.0f); + structureDamage = ToolBox.GetAttributeFloat(element, "structuredamage", 0.0f); bleedingDamage = ToolBox.GetAttributeFloat(element, "bleedingdamage", 0.0f); stun = ToolBox.GetAttributeFloat(element, "stun", 0.0f); diff --git a/Subsurface/Characters/Character.cs b/Subsurface/Characters/Character.cs index 297ffb9d6..cb5f938dc 100644 --- a/Subsurface/Characters/Character.cs +++ b/Subsurface/Characters/Character.cs @@ -14,7 +14,7 @@ using Subsurface.Particles; namespace Subsurface { - class Character : Entity, IDamageable + class Character : Entity, IDamageable, IPropertyObject { public static List characterList = new List(); @@ -40,12 +40,14 @@ namespace Subsurface public byte largeUpdateTimer; public readonly Dictionary properties; + public Dictionary ObjectProperties + { + get { return properties; } + } protected Key selectKeyHit; - protected Key actionKeyHit; - protected Key actionKeyDown; - protected Key secondaryKeyHit; - protected Key secondaryKeyDown; + protected Key actionKeyHit, actionKeyDown; + protected Key secondaryKeyHit, secondaryKeyDown; private Item selectedConstruction; private Item[] selectedItems; @@ -59,6 +61,9 @@ namespace Subsurface protected float oxygen; protected float drowningTime; + protected float health; + protected float maxHealth; + protected Item closestItem; protected bool isDead; @@ -73,12 +78,21 @@ namespace Subsurface protected float soundTimer; protected float soundInterval; + private float bleeding; private float blood; private Sound[] sounds; //which AIstate each sound is for private AIController.AiState[] soundStates; + public string Name + { + get + { + return speciesName; + } + } + public Inventory Inventory { get { return inventory; } @@ -122,13 +136,19 @@ namespace Subsurface { get { - float totalHealth = 0.0f; - foreach (Limb l in animController.limbs) - { - totalHealth += (l.MaxHealth - l.Damage); + return health; + //float totalHealth = 0.0f; + //foreach (Limb l in animController.limbs) + //{ + // totalHealth += (l.MaxHealth - l.Damage); - } - return totalHealth/animController.limbs.Count(); + //} + //return totalHealth/animController.limbs.Count(); + } + set + { + health = MathHelper.Clamp(value, 0.0f, maxHealth); + if (health==0.0f) Kill(); } } @@ -301,6 +321,9 @@ namespace Subsurface //limb.prevPosition = ConvertUnits.ToDisplayUnits(position); } + maxHealth = ToolBox.GetAttributeFloat(doc.Root, "health", 100.0f); + health = maxHealth; + needsAir = ToolBox.GetAttributeBool(doc.Root, "needsair", false); drowningTime = ToolBox.GetAttributeFloat(doc.Root, "drowningtime", 10.0f); @@ -331,10 +354,10 @@ namespace Subsurface animController.FindHull(); - if (info.ID >= 0) - { - ID = info.ID; - } + //if (info.ID >= 0) + //{ + // ID = info.ID; + //} characterList.Add(this); } @@ -343,7 +366,7 @@ namespace Subsurface /// /// Control the characte /// - public void Control(Camera cam, bool forcePick=false) + public void Control(float deltaTime, Camera cam, bool forcePick=false) { if (isDead) return; @@ -370,15 +393,15 @@ namespace Subsurface if (selectedItems[i] == null) continue; if (i == 1 && selectedItems[0] == selectedItems[1]) continue; - if (actionKeyDown.State) selectedItems[i].Use(this); - if (secondaryKeyDown.State && selectedItems[i] != null) selectedItems[i].SecondaryUse(this); + if (actionKeyDown.State) selectedItems[i].Use(deltaTime, this); + if (secondaryKeyDown.State && selectedItems[i] != null) selectedItems[i].SecondaryUse(deltaTime, this); } if (selectedConstruction != null) { - if (actionKeyDown.State) selectedConstruction.Use(this); - if (secondaryKeyDown.State) selectedConstruction.SecondaryUse(this); + if (actionKeyDown.State) selectedConstruction.Use(deltaTime, this); + if (secondaryKeyDown.State) selectedConstruction.SecondaryUse(deltaTime, this); } if (IsNetworkPlayer) @@ -509,8 +532,8 @@ namespace Subsurface } if (controlled == this) ControlLocalPlayer(cam); - - Control(cam); + + Control(deltaTime, cam); UpdateSightRange(); aiTarget.SoundRange = 0.0f; @@ -543,10 +566,10 @@ namespace Subsurface soundTimer = soundInterval; } - foreach (Limb limb in animController.limbs) - { - Blood = blood - limb.Bleeding * deltaTime * 0.1f; - } + //foreach (Limb limb in animController.limbs) + //{ + Blood = blood - bleeding * deltaTime; + //} if (aiController != null) aiController.Update(deltaTime); } @@ -587,19 +610,25 @@ namespace Subsurface } - private static GUIProgressBar drowningBar; + private static GUIProgressBar drowningBar, bloodBar; public void DrawHud(SpriteBatch spriteBatch, Camera cam) { if (drowningBar==null) { - int width = 200, height = 20; - drowningBar = new GUIProgressBar(new Rectangle(Game1.GraphicsWidth / 2 - width / 2, 20, width, height), Color.Blue, 1.0f); + int width = 100, height = 20; + drowningBar = new GUIProgressBar(new Rectangle(20, Game1.GraphicsHeight/2, width, height), Color.Blue, 1.0f); + + bloodBar = new GUIProgressBar(new Rectangle(20, Game1.GraphicsHeight / 2 + 30, width, height), Color.Red, 1.0f); } drowningBar.BarSize = Controlled.Oxygen / 100.0f; if (drowningBar.BarSize < 1.0f) drowningBar.Draw(spriteBatch); + bloodBar.BarSize = Blood / 100.0f; + if (bloodBar.BarSize < 1.0f) + bloodBar.Draw(spriteBatch); + if (Controlled.Inventory != null) Controlled.Inventory.Draw(spriteBatch); @@ -674,7 +703,11 @@ namespace Subsurface closestLimb.body.ApplyForce(pull*Math.Min(amount*100.0f, 100.0f)); - return closestLimb.AddDamage(position, damageType, amount, bleedingAmount, playSound); + AttackResult attackResult = closestLimb.AddDamage(position, damageType, amount, bleedingAmount, playSound); + health -= attackResult.damage; + bleeding += attackResult.bleeding; + + return attackResult; } @@ -705,12 +738,14 @@ namespace Subsurface centerOfMass /= totalMass; + health = 0.0f; + foreach (Limb limb in animController.limbs) { Vector2 diff = centerOfMass - limb.SimPosition; if (diff == Vector2.Zero) continue; limb.body.ApplyLinearImpulse(diff * 10.0f); - limb.Damage = 100.0f; + // limb.Damage = 100.0f; } AmbientSoundManager.PlayDamageSound(DamageSoundType.Implode, 50.0f, torso.body.FarseerBody); @@ -739,7 +774,7 @@ namespace Subsurface if (isDead) return; //if the game is run by a client, characters are only killed when the server says so - if (Game1.client != null) + if (Game1.Client != null) { if (networkMessage) { @@ -751,14 +786,14 @@ namespace Subsurface } } - if (Game1.server != null) + if (Game1.Server != null) { new NetworkEvent(NetworkEventType.KillCharacter, ID, false); } - if (Game1.gameSession.crewManager!=null) + if (Game1.GameSession!=null && Game1.GameSession.crewManager != null) { - Game1.gameSession.crewManager.KillCharacter(this); + Game1.GameSession.crewManager.KillCharacter(this); } isDead = true; @@ -876,9 +911,9 @@ namespace Subsurface else if (type == NetworkEventType.KillCharacter) { Kill(true); - if (Game1.client != null && controlled == this) + if (Game1.Client != null && controlled == this) { - Game1.client.AddChatMessage("YOU HAVE DIED. Your chat messages will only be visible to other dead players.", ChatMessageType.Dead); + Game1.Client.AddChatMessage("YOU HAVE DIED. Your chat messages will only be visible to other dead players.", ChatMessageType.Dead); } return; } @@ -970,7 +1005,7 @@ namespace Subsurface if (controlled == this) controlled = null; - if (Game1.client!=null && Game1.client.Character == this) Game1.client.Character = null; + if (Game1.Client!=null && Game1.Client.Character == this) Game1.Client.Character = null; if (aiTarget != null) aiTarget.Remove(); diff --git a/Subsurface/Characters/CharacterInfo.cs b/Subsurface/Characters/CharacterInfo.cs index e6ae2ab79..17f4177e2 100644 --- a/Subsurface/Characters/CharacterInfo.cs +++ b/Subsurface/Characters/CharacterInfo.cs @@ -1,4 +1,5 @@ -using System.Xml.Linq; +using Microsoft.Xna.Framework; +using System.Xml.Linq; namespace Subsurface { @@ -6,27 +7,28 @@ namespace Subsurface class CharacterInfo { - //the name of the character (e.q. Urist McEngineer) public string name; public readonly string file; - public int ID; + public readonly int headSpriteId; + + //public int ID; public Gender gender; public int salary; - public string GenderString() - { - return gender.ToString(); - } + //public string GenderString() + //{ + // return gender.ToString(); + //} public CharacterInfo(string file, string name = "", Gender gender = Gender.None) { this.file = file; - ID = -1; + //ID = -1; XDocument doc = ToolBox.TryLoadXml(file); if (doc == null) return; @@ -35,7 +37,7 @@ namespace Subsurface if (ToolBox.GetAttributeBool(doc.Root, "genders", false)) { - if (gender==Gender.None) + if (gender == Gender.None) { float femaleRatio = ToolBox.GetAttributeFloat(doc.Root, "femaleratio", 0.5f); this.gender = (Game1.random.NextDouble() < femaleRatio) ? Gender.Female : Gender.Male; @@ -45,7 +47,21 @@ namespace Subsurface this.gender = gender; } } - + + Vector2 headSpriteRange = ToolBox.GetAttributeVector2(doc.Root, "headid", Vector2.Zero); + if (headSpriteRange == Vector2.Zero) + { + headSpriteRange = ToolBox.GetAttributeVector2( + doc.Root, + this.gender == Gender.Female ? "femaleheadid" : "maleheadid", + Vector2.Zero); + } + + if (headSpriteRange != Vector2.Zero) + { + headSpriteId = Game1.localRandom.Next((int)headSpriteRange.X, (int)headSpriteRange.Y + 1); + } + if (!string.IsNullOrEmpty(name)) { this.name = name; @@ -69,8 +85,30 @@ namespace Subsurface this.name += ToolBox.GetRandomLine(lastNamePath); } } - + } + public CharacterInfo(XElement element) + { + name = element.Name.ToString(); + + string genderStr = ToolBox.GetAttributeString(element, "gender", "male").ToLower(); + gender = (genderStr == "male") ? Gender.Male : Gender.Female; + + salary = ToolBox.GetAttributeInt(element, "salary", 1000); + } + + public virtual XElement Save(XElement parentElement) + { + XElement componentElement = new XElement("character"); + + componentElement.Add( + new XAttribute("name", name), + new XAttribute("gender", gender == Gender.Male ? "male" : "female"), + new XAttribute("salary", salary), + new XAttribute("headspriteid", headSpriteId)); + + parentElement.Add(componentElement); + return componentElement; } } } diff --git a/Subsurface/Characters/DelayedEffect.cs b/Subsurface/Characters/DelayedEffect.cs index 1ecb3098c..8813d017f 100644 --- a/Subsurface/Characters/DelayedEffect.cs +++ b/Subsurface/Characters/DelayedEffect.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using Microsoft.Xna.Framework; +using System.Collections.Generic; using System.Xml.Linq; namespace Subsurface @@ -11,12 +12,10 @@ namespace Subsurface float timer; - private Item item; - - private Character character; - - private Limb limb; + Vector2 position; + List targets; + public float Timer { get { return timer; } @@ -28,15 +27,14 @@ namespace Subsurface delay = ToolBox.GetAttributeFloat(element, "delay", 1.0f); } - public override void Apply(ActionType type, float deltaTime, Item item, Character character = null, Limb limb = null) + public override void Apply(ActionType type, float deltaTime, Vector2 position, List targets) { if (this.type != type) return; - - this.item = item; - this.character = character; - this.limb = limb; - + timer = delay; + this.position = position; + + this.targets = targets; list.Add(this); } @@ -47,7 +45,7 @@ namespace Subsurface if (timer > 0.0f) return; - base.Apply(1.0f, character, item, limb); + base.Apply(1.0f, position, targets); list.Remove(this); } diff --git a/Subsurface/Characters/Limb.cs b/Subsurface/Characters/Limb.cs index 5a15b2c70..39e57402f 100644 --- a/Subsurface/Characters/Limb.cs +++ b/Subsurface/Characters/Limb.cs @@ -41,9 +41,9 @@ namespace Subsurface public readonly bool ignoreCollisions; - private readonly float maxHealth; - private float damage; - private float bleeding; + //private readonly float maxHealth; + //private float damage; + //private float bleeding; public readonly float impactTolerance; @@ -122,26 +122,26 @@ namespace Subsurface get { return refJointIndex; } } - public float Damage - { - get { return damage; } - set - { - damage = Math.Max(value, 0.0f); - if (damage >=maxHealth) character.Kill(); - } - } + //public float Damage + //{ + // get { return damage; } + // set + // { + // damage = Math.Max(value, 0.0f); + // if (damage >=maxHealth) character.Kill(); + // } + //} - public float MaxHealth - { - get { return maxHealth; } - } + //public float MaxHealth + //{ + // get { return maxHealth; } + //} - public float Bleeding - { - get { return bleeding; } - set { bleeding = MathHelper.Clamp(value, 0.0f, 100.0f); } - } + //public float Bleeding + //{ + // get { return bleeding; } + // set { bleeding = MathHelper.Clamp(value, 0.0f, 100.0f); } + //} public Item WearingItem { @@ -208,7 +208,7 @@ namespace Subsurface steerForce = ToolBox.GetAttributeFloat(element, "steerforce", 0.0f); - maxHealth = Math.Max(ToolBox.GetAttributeFloat(element, "health", 100.0f),1.0f); + //maxHealth = Math.Max(ToolBox.GetAttributeFloat(element, "health", 100.0f),1.0f); armorSector = ToolBox.GetAttributeVector2(element, "armorsector", Vector2.Zero); armorSector.X = MathHelper.ToRadians(armorSector.X); @@ -227,7 +227,11 @@ namespace Subsurface string spritePath = subElement.Attribute("texture").Value; if (character.info!=null) + { spritePath = spritePath.Replace("[GENDER]", (character.info.gender == Gender.Female) ? "f" : ""); + spritePath = spritePath.Replace("[HEADID]", character.info.headSpriteId.ToString()); + } + sprite = new Sprite(subElement, "", spritePath); break; @@ -277,7 +281,7 @@ namespace Subsurface { hitArmor = true; damageSoundType = DamageSoundType.LimbArmor; - damage /= armorValue; + amount /= armorValue; bleedingAmount /= armorValue; } } @@ -287,8 +291,8 @@ namespace Subsurface AmbientSoundManager.PlayDamageSound(damageSoundType, amount, position); } - Bleeding += bleedingAmount; - Damage += amount; + //Bleeding += bleedingAmount; + //Damage += amount; float bloodAmount = hitArmor ? 0 : (int)Math.Min((int)(amount * 2.0f), 20); //if (closestLimb.Damage>=100.0f) @@ -366,18 +370,18 @@ namespace Subsurface soundTimer -= deltaTime; - if (ToolBox.RandomFloat(0.0f, 1000.0f) < Bleeding) - { - Game1.particleManager.CreateParticle( - !inWater ? "blood" : "waterblood", - SimPosition, Vector2.Zero); - } + //if (ToolBox.RandomFloat(0.0f, 1000.0f) < Bleeding) + //{ + // Game1.particleManager.CreateParticle( + // !inWater ? "blood" : "waterblood", + // SimPosition, Vector2.Zero); + //} } public void Draw(SpriteBatch spriteBatch, bool debugDraw) { - Color color = new Color(1.0f, 1.0f - damage / maxHealth, 1.0f - damage / maxHealth); + Color color = Color.White;// new Color(1.0f, 1.0f - damage / maxHealth, 1.0f - damage / maxHealth); body.Dir = Dir; body.Draw(spriteBatch, sprite, color); diff --git a/Subsurface/Characters/Ragdoll.cs b/Subsurface/Characters/Ragdoll.cs index 42d5b4e92..48809eb49 100644 --- a/Subsurface/Characters/Ragdoll.cs +++ b/Subsurface/Characters/Ragdoll.cs @@ -298,7 +298,7 @@ namespace Subsurface if (impact > l.impactTolerance) { - l.Damage += (impact-l.impactTolerance*0.1f); + character.Health -= (impact-l.impactTolerance*0.1f); strongestImpact = Math.Max(strongestImpact, impact - l.impactTolerance); } } diff --git a/Subsurface/Characters/StatusEffect.cs b/Subsurface/Characters/StatusEffect.cs index 2fa7fca9c..2101943e2 100644 --- a/Subsurface/Characters/StatusEffect.cs +++ b/Subsurface/Characters/StatusEffect.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.Xna.Framework; +using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; @@ -8,12 +9,12 @@ namespace Subsurface class StatusEffect { [Flags] - public enum Target + public enum TargetType { - This = 1, Parent = 2, Character = 4, Contained = 8, Nearby = 16 + This = 1, Parent = 2, Character = 4, Contained = 8, Nearby = 16, UseTarget=32 } - private Target targets; + private TargetType targetTypes; private string[] targetNames; public string[] propertyNames; @@ -29,9 +30,9 @@ namespace Subsurface private Sound sound; - public Target Targets + public TargetType Targets { - get { return targets; } + get { return targetTypes; } } public string[] TargetNames @@ -91,7 +92,7 @@ namespace Subsurface string[] Flags = attribute.Value.Split(','); foreach (string s in Flags) { - targets |= (Target)Enum.Parse(typeof(Target), s, true); + targetTypes |= (TargetType)Enum.Parse(typeof(TargetType), s, true); } break; @@ -142,43 +143,75 @@ namespace Subsurface } - public virtual void Apply(ActionType type, float deltaTime, Item item, Character character = null, Limb limb = null) - { - if (this.type == type) Apply(deltaTime, character, item); + //public virtual void Apply(ActionType type, float deltaTime, Item item, Character character = null) + //{ + // if (this.type == type) Apply(deltaTime, character, item); + //} + public virtual void Apply(ActionType type, float deltaTime, Vector2 position, IPropertyObject target) + { + if (!targetNames.Contains(target.Name)) return; + + List targets = new List(); + targets.Add(target); + + if (this.type == type) Apply(deltaTime, position, targets); } - - protected virtual void Apply(float deltaTime, Character character, Item item, Limb limb = null) + public virtual void Apply(ActionType type, float deltaTime, Vector2 position, List targets) { - if (explosion != null) explosion.Explode(item.SimPosition); + if (this.type == type) Apply(deltaTime, position, targets); + } + + protected virtual void Apply(float deltaTime, Vector2 position, List targets) + { + if (explosion != null) explosion.Explode(position); + + if (sound != null) sound.Play(1.0f, 1000.0f, position); - if (sound != null) sound.Play(1.0f, 1000.0f, item.body.FarseerBody); - for (int i = 0; i < propertyNames.Count(); i++) { ObjectProperty property; - - if (character!=null && character.properties.TryGetValue(propertyNames[i], out property)) + foreach (IPropertyObject target in targets) { - ApplyToProperty(property, propertyEffects[i], deltaTime); - } - - if (item == null) continue; - - if (item.properties.TryGetValue(propertyNames[i], out property)) - { - ApplyToProperty(property, propertyEffects[i], deltaTime); - } - - foreach (ItemComponent ic in item.components) - { - if (!ic.properties.TryGetValue(propertyNames[i], out property)) continue; - ApplyToProperty(property, propertyEffects[i], deltaTime); + if (targetNames!=null && !targetNames.Contains(target.Name)) continue; + if (!target.ObjectProperties.TryGetValue(propertyNames[i], out property)) continue; + + ApplyToProperty(property, propertyEffects[i], deltaTime); } } } + //protected virtual void Apply(float deltaTime, Character character, Item item) + //{ + // if (explosion != null) explosion.Explode(item.SimPosition); + + // if (sound != null) sound.Play(1.0f, 1000.0f, item.body.FarseerBody); + + // for (int i = 0; i < propertyNames.Count(); i++) + // { + // ObjectProperty property; + + // if (character!=null && character.properties.TryGetValue(propertyNames[i], out property)) + // { + // ApplyToProperty(property, propertyEffects[i], deltaTime); + // } + + // if (item == null) continue; + + // if (item.properties.TryGetValue(propertyNames[i], out property)) + // { + // ApplyToProperty(property, propertyEffects[i], deltaTime); + // } + + // foreach (ItemComponent ic in item.components) + // { + // if (!ic.properties.TryGetValue(propertyNames[i], out property)) continue; + // ApplyToProperty(property, propertyEffects[i], deltaTime); + // } + // } + //} + protected void ApplyToProperty(ObjectProperty property, object value, float deltaTime) { if (disableDeltaTime) deltaTime = 1.0f; diff --git a/Subsurface/Content/Characters/Crawler/crawler.xml b/Subsurface/Content/Characters/Crawler/crawler.xml index f51510ed6..c2151cd42 100644 --- a/Subsurface/Content/Characters/Crawler/crawler.xml +++ b/Subsurface/Content/Characters/Crawler/crawler.xml @@ -26,7 +26,7 @@ - + diff --git a/Subsurface/Content/Characters/Human/fhead.png b/Subsurface/Content/Characters/Human/fhead1.png similarity index 100% rename from Subsurface/Content/Characters/Human/fhead.png rename to Subsurface/Content/Characters/Human/fhead1.png diff --git a/Subsurface/Content/Characters/Human/fhead2.png b/Subsurface/Content/Characters/Human/fhead2.png new file mode 100644 index 000000000..caac6f99a Binary files /dev/null and b/Subsurface/Content/Characters/Human/fhead2.png differ diff --git a/Subsurface/Content/Characters/Human/head.png b/Subsurface/Content/Characters/Human/head1.png similarity index 100% rename from Subsurface/Content/Characters/Human/head.png rename to Subsurface/Content/Characters/Human/head1.png diff --git a/Subsurface/Content/Characters/Human/head3.png b/Subsurface/Content/Characters/Human/head3.png new file mode 100644 index 000000000..58e8b9c86 Binary files /dev/null and b/Subsurface/Content/Characters/Human/head3.png differ diff --git a/Subsurface/Content/Characters/Human/head4.png b/Subsurface/Content/Characters/Human/head4.png new file mode 100644 index 000000000..65e524fed Binary files /dev/null and b/Subsurface/Content/Characters/Human/head4.png differ diff --git a/Subsurface/Content/Characters/Human/human.xml b/Subsurface/Content/Characters/Human/human.xml index 102159d70..d587c6d68 100644 --- a/Subsurface/Content/Characters/Human/human.xml +++ b/Subsurface/Content/Characters/Human/human.xml @@ -1,5 +1,5 @@  - + @@ -8,7 +8,7 @@ - + diff --git a/Subsurface/Content/Items/Clothes/captainhat.png b/Subsurface/Content/Items/Clothes/captainhat.png new file mode 100644 index 000000000..732da7578 Binary files /dev/null and b/Subsurface/Content/Items/Clothes/captainhat.png differ diff --git a/Subsurface/Content/Items/Clothes/clothes.xml b/Subsurface/Content/Items/Clothes/clothes.xml new file mode 100644 index 000000000..0dfb9fcf3 --- /dev/null +++ b/Subsurface/Content/Items/Clothes/clothes.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/Subsurface/Content/Items/Diving/divinggear.xml b/Subsurface/Content/Items/Diving/divinggear.xml index cdd318394..0c5b41dc6 100644 --- a/Subsurface/Content/Items/Diving/divinggear.xml +++ b/Subsurface/Content/Items/Diving/divinggear.xml @@ -11,11 +11,13 @@ - + + + diff --git a/Subsurface/Content/Items/OxygenTank/item.xml b/Subsurface/Content/Items/Diving/item.xml similarity index 100% rename from Subsurface/Content/Items/OxygenTank/item.xml rename to Subsurface/Content/Items/Diving/item.xml diff --git a/Subsurface/Content/Items/OxygenTank/oxygentank.png b/Subsurface/Content/Items/Diving/oxygentank.png similarity index 100% rename from Subsurface/Content/Items/OxygenTank/oxygentank.png rename to Subsurface/Content/Items/Diving/oxygentank.png diff --git a/Subsurface/Content/Items/Reactor/reactor.xml b/Subsurface/Content/Items/Reactor/reactor.xml index 685838c6a..d794b8eee 100644 --- a/Subsurface/Content/Items/Reactor/reactor.xml +++ b/Subsurface/Content/Items/Reactor/reactor.xml @@ -11,7 +11,7 @@ - + diff --git a/Subsurface/Content/Items/Tools/fueltank.png b/Subsurface/Content/Items/Tools/fueltank.png new file mode 100644 index 000000000..f26b70ebe Binary files /dev/null and b/Subsurface/Content/Items/Tools/fueltank.png differ diff --git a/Subsurface/Content/Items/Tools/plasmacutter.png b/Subsurface/Content/Items/Tools/plasmacutter.png new file mode 100644 index 000000000..25fdfaa60 Binary files /dev/null and b/Subsurface/Content/Items/Tools/plasmacutter.png differ diff --git a/Subsurface/Content/Items/Tools/tools.xml b/Subsurface/Content/Items/Tools/tools.xml index ecf919bda..d6ca8fe5f 100644 --- a/Subsurface/Content/Items/Tools/tools.xml +++ b/Subsurface/Content/Items/Tools/tools.xml @@ -7,16 +7,64 @@ - + - + - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + @@ -46,7 +46,7 @@ - + diff --git a/Subsurface/Content/Particles/prefabs.xml b/Subsurface/Content/Particles/prefabs.xml index 8c9e90b53..a977a81bb 100644 --- a/Subsurface/Content/Particles/prefabs.xml +++ b/Subsurface/Content/Particles/prefabs.xml @@ -70,4 +70,15 @@ inwater="false" deleteonhit="true" velocitychange="0.0, 0.5"/> + + diff --git a/Subsurface/Content/Sounds/Music/Enter the Maze.ogg b/Subsurface/Content/Sounds/Music/Enter the Maze.ogg new file mode 100644 index 000000000..a2db0ebd2 Binary files /dev/null and b/Subsurface/Content/Sounds/Music/Enter the Maze.ogg differ diff --git a/Subsurface/Content/Sounds/Music/Unseen Horrors.ogg b/Subsurface/Content/Sounds/Music/Unseen Horrors.ogg new file mode 100644 index 000000000..b057c40cb Binary files /dev/null and b/Subsurface/Content/Sounds/Music/Unseen Horrors.ogg differ diff --git a/Subsurface/Content/Sounds/sounds.xml b/Subsurface/Content/Sounds/sounds.xml index c9c2fa3b6..e5f706f98 100644 --- a/Subsurface/Content/Sounds/sounds.xml +++ b/Subsurface/Content/Sounds/sounds.xml @@ -25,4 +25,8 @@ + + + + \ No newline at end of file diff --git a/Subsurface/Content/randomevents.xml b/Subsurface/Content/randomevents.xml index 8ff17ce89..fbe619158 100644 --- a/Subsurface/Content/randomevents.xml +++ b/Subsurface/Content/randomevents.xml @@ -3,13 +3,15 @@ + difficulty="30" + minamount="2" maxamount="3" + starttimemin="5" starttimemax="10" + musictype="monster"/> + difficulty="50" + starttimemin="5" starttimemax="10" + musictype="monster"/> \ No newline at end of file diff --git a/Subsurface/DebugConsole.cs b/Subsurface/DebugConsole.cs index a4c2e7dd0..772eb006c 100644 --- a/Subsurface/DebugConsole.cs +++ b/Subsurface/DebugConsole.cs @@ -148,8 +148,8 @@ namespace Subsurface { WayPoint spawnPoint = WayPoint.GetRandom(WayPoint.SpawnType.Human); Character.Controlled = new Character("Content/Characters/Human/human.xml", (spawnPoint == null) ? Vector2.Zero : spawnPoint.SimPosition); - if (Game1.gameSession != null) Game1.gameSession.crewManager.AddCharacter(Character.Controlled); - if (Game1.gameSession != null) Game1.gameSession.crewManager.SelectCharacter(Character.Controlled); + if (Game1.GameSession != null) Game1.GameSession.crewManager.AddCharacter(Character.Controlled); + if (Game1.GameSession != null) Game1.GameSession.crewManager.SelectCharacter(Character.Controlled); } else { @@ -159,42 +159,42 @@ namespace Subsurface break; case "startserver": - if (Game1.server==null) - Game1.server = new GameServer(); + if (Game1.Server==null) + Game1.Server = new GameServer(); break; case "kick": - if (Game1.server == null) break; - Game1.server.KickPlayer(commands[1]); + if (Game1.Server == null) break; + Game1.Server.KickPlayer(commands[1]); break; case "startclient": if (commands.Length == 1) return; - if (Game1.client == null) + if (Game1.Client == null) { - Game1.client = new GameClient("Name"); - Game1.client.ConnectToServer(commands[1]); + Game1.Client = new GameClient("Name"); + Game1.Client.ConnectToServer(commands[1]); } break; case "mainmenuscreen": case "mainmenu": case "menu": - Game1.mainMenuScreen.Select(); + Game1.MainMenuScreen.Select(); break; case "gamescreen": case "game": - Game1.gameScreen.Select(); + Game1.GameScreen.Select(); break; case "editmapscreen": case "editmap": - case "edit": - Game1.editMapScreen.Select(); + case "edit": + Game1.EditMapScreen.Select(); break; case "editcharacter": case "editchar": - Game1.editCharacterScreen.Select(); + Game1.EditCharacterScreen.Select(); break; case "editwater": case "water": - if (Game1.client== null) + if (Game1.Client== null) { Hull.EditWater = !Hull.EditWater; } @@ -206,15 +206,27 @@ namespace Subsurface break; case "lobbyscreen": case "lobby": - Game1.lobbyScreen.Select(); + Game1.LobbyScreen.Select(); break; case "savemap": - Map.Loaded.SaveAs("Content/SavedMaps/" + commands[1]); + if (commands.Length < 2) break; + Map.SaveCurrent("Content/SavedMaps/" + commands[1]); NewMessage("map saved", Color.Green); break; case "loadmap": + if (commands.Length < 2) break; Map.Load("Content/SavedMaps/" + commands[1]); break; + case "savegame": + SaveUtil.SaveGame(SaveUtil.SaveFolder+"save"); + break; + case "loadgame": + SaveUtil.LoadGame(SaveUtil.SaveFolder + "save"); + break; + case "messagebox": + if (commands.Length < 3) break; + new GUIMessageBox(commands[1], commands[2]); + break; case "debugdraw": Hull.DebugDraw = !Hull.DebugDraw; Ragdoll.DebugDraw = !Ragdoll.DebugDraw; diff --git a/Subsurface/Events/PropertyTask.cs b/Subsurface/Events/PropertyTask.cs index c972e2a2d..33220132c 100644 --- a/Subsurface/Events/PropertyTask.cs +++ b/Subsurface/Events/PropertyTask.cs @@ -8,9 +8,11 @@ public delegate bool IsFinishedHandler(); private IsFinishedHandler IsFinishedChecker; - public PropertyTask(TaskManager taskManager, Item item, IsFinishedHandler isFinished, float priority, string name) - : base(taskManager, priority, name) + public PropertyTask(Item item, IsFinishedHandler isFinished, float priority, string name) + : base(priority, name) { + if (taskManager == null) return; + this.item = item; IsFinishedChecker = isFinished; diff --git a/Subsurface/Events/RepairTask.cs b/Subsurface/Events/RepairTask.cs index 7175c4253..9e132bfae 100644 --- a/Subsurface/Events/RepairTask.cs +++ b/Subsurface/Events/RepairTask.cs @@ -4,9 +4,11 @@ { Item item; - public RepairTask(TaskManager taskManager, Item item, float priority, string name) - : base(taskManager, priority, name) + public RepairTask(Item item, float priority, string name) + : base(priority, name) { + if (taskManager == null) return; + this.item = item; taskManager.TaskStarted(this); diff --git a/Subsurface/Events/ScriptedEvent.cs b/Subsurface/Events/ScriptedEvent.cs index 831aed4fd..97db8b975 100644 --- a/Subsurface/Events/ScriptedEvent.cs +++ b/Subsurface/Events/ScriptedEvent.cs @@ -30,7 +30,7 @@ namespace Subsurface protected bool isStarted; protected bool isFinished; - + public string Name { get { return name; } @@ -46,6 +46,12 @@ namespace Subsurface get { return commonness; } } + public string MusicType + { + get; + set; + } + public bool IsStarted { get { return isStarted; } @@ -69,6 +75,10 @@ namespace Subsurface difficulty = ToolBox.GetAttributeInt(element, "difficulty", 1); commonness = ToolBox.GetAttributeInt(element, "commonness", 1); + + MusicType = ToolBox.GetAttributeString(element, "musictype", "default"); + + if (element.Attribute("starttime") != null) { startTimeMax = ToolBox.GetAttributeInt(element, "starttime", 1); diff --git a/Subsurface/Events/ScriptedTask.cs b/Subsurface/Events/ScriptedTask.cs index 45ef1e0de..996b2ab5c 100644 --- a/Subsurface/Events/ScriptedTask.cs +++ b/Subsurface/Events/ScriptedTask.cs @@ -6,9 +6,13 @@ private bool prevStarted; - public ScriptedTask(TaskManager taskManager, ScriptedEvent scriptedEvent) - : base(taskManager, scriptedEvent.Difficulty, scriptedEvent.Name) + public ScriptedTask(ScriptedEvent scriptedEvent) + : base(scriptedEvent.Difficulty, scriptedEvent.Name) { + if (taskManager == null) return; + + this.musicType = scriptedEvent.MusicType; + this.scriptedEvent = scriptedEvent; scriptedEvent.Init(); } diff --git a/Subsurface/Events/Task.cs b/Subsurface/Events/Task.cs index 08dd5dade..004245bdd 100644 --- a/Subsurface/Events/Task.cs +++ b/Subsurface/Events/Task.cs @@ -8,6 +8,8 @@ namespace Subsurface private float priority; + protected string musicType; + protected TaskManager taskManager; protected bool isFinished; @@ -22,14 +24,22 @@ namespace Subsurface get { return priority; } } + public string MusicType + { + get { return musicType; } + } + public bool IsFinished { get { return isFinished; } } - public Task(TaskManager taskManager, float priority, string name) + public Task(float priority, string name) { - this.taskManager = taskManager; + if (Game1.GameSession==null || Game1.GameSession.taskManager == null) return; + + taskManager = Game1.GameSession.taskManager; + musicType = "repair"; this.priority = priority; this.name = name; diff --git a/Subsurface/Events/TaskManager.cs b/Subsurface/Events/TaskManager.cs index f039eee2b..2e4c8f524 100644 --- a/Subsurface/Events/TaskManager.cs +++ b/Subsurface/Events/TaskManager.cs @@ -6,10 +6,29 @@ namespace Subsurface { class TaskManager { + const float CriticalPriority = 50.0f; + private List tasks; private GUIListBox taskListBox; + public List Tasks + { + get { return tasks; } + } + + public bool CriticalTasks + { + get + { + foreach (Task task in tasks) + { + if (task.Priority >= CriticalPriority) return true; + } + return false; + } + } + public TaskManager(GameSession session) { tasks = new List(); @@ -45,7 +64,7 @@ namespace Subsurface for (int i = 0; i < scriptedEventCount; i++) { ScriptedEvent scriptedEvent = ScriptedEvent.LoadRandom(); - AddTask(new ScriptedTask(this, scriptedEvent)); + AddTask(new ScriptedTask(scriptedEvent)); } } diff --git a/Subsurface/GUI/GUI.cs b/Subsurface/GUI/GUI.cs index f0a743c63..f53eedb3c 100644 --- a/Subsurface/GUI/GUI.cs +++ b/Subsurface/GUI/GUI.cs @@ -269,13 +269,29 @@ namespace Subsurface // new Vector2(10, 30), Color.White); - if (Character.Controlled != null) Character.Controlled.DrawHud(spriteBatch, cam); + if (Character.Controlled != null && cam!=null) Character.Controlled.DrawHud(spriteBatch, cam); DrawMessages(spriteBatch, (float)deltaTime); + + if (GUIMessageBox.messageBoxes.Count>0) + { + var messageBox = GUIMessageBox.messageBoxes.Peek(); + if (messageBox != null) messageBox.Draw(spriteBatch); + } + DebugConsole.Draw(spriteBatch); } + public static void Update(float deltaTime) + { + if (GUIMessageBox.messageBoxes.Count > 0) + { + var messageBox = GUIMessageBox.messageBoxes.Peek(); + if (messageBox != null) messageBox.Update(deltaTime); + } + } + public static void AddMessage(string message, Color color, float lifeTime = 3.0f) { Vector2 currPos = new Vector2(Game1.GraphicsWidth / 2.0f, Game1.GraphicsHeight * 0.7f); diff --git a/Subsurface/GUI/GUIButton.cs b/Subsurface/GUI/GUIButton.cs index eed7ce64d..427484084 100644 --- a/Subsurface/GUI/GUIButton.cs +++ b/Subsurface/GUI/GUIButton.cs @@ -51,7 +51,7 @@ namespace Subsurface public override void Draw(SpriteBatch spriteBatch) { - if (rect.Contains(PlayerInput.GetMouseState.Position) && Enabled) + if (rect.Contains(PlayerInput.GetMouseState.Position) && Enabled && (MouseOn == this || IsParentOf(MouseOn))) { state = ComponentState.Hover; if (PlayerInput.GetMouseState.LeftButton == ButtonState.Pressed) @@ -66,8 +66,7 @@ namespace Subsurface if (OnClicked != null) { if (OnClicked(this, UserData)) state = ComponentState.Selected; - } - + } } } else @@ -87,7 +86,7 @@ namespace Subsurface DrawChildren(spriteBatch); - if (!Enabled) GUI.DrawRectangle(spriteBatch, rect, Color.Gray*0.5f*alpha, true); + if (!Enabled) GUI.DrawRectangle(spriteBatch, rect, Color.Gray*0.5f, true); } } } diff --git a/Subsurface/GUI/GUIComponent.cs b/Subsurface/GUI/GUIComponent.cs index 0c8b1e7ef..bea9cc29b 100644 --- a/Subsurface/GUI/GUIComponent.cs +++ b/Subsurface/GUI/GUIComponent.cs @@ -142,14 +142,27 @@ namespace Subsurface return null; } + public bool IsParentOf(GUIComponent component) + { + foreach (GUIComponent child in children) + { + if (child == component) return true; + if (child.IsParentOf(component)) return true; + } + + return false; + } + public virtual void Draw(SpriteBatch spriteBatch) { - Color newColor = color; - if (state == ComponentState.Selected) newColor = selectedColor; - if (state == ComponentState.Hover) newColor = hoverColor; - GUI.DrawRectangle(spriteBatch, rect, newColor*alpha, true); - DrawChildren(spriteBatch); + + //Color newColor = color; + //if (state == ComponentState.Selected) newColor = selectedColor; + //if (state == ComponentState.Hover) newColor = hoverColor; + + //GUI.DrawRectangle(spriteBatch, rect, newColor*alpha, true); + //DrawChildren(spriteBatch); } public virtual void Update(float deltaTime) diff --git a/Subsurface/GUI/GUIFrame.cs b/Subsurface/GUI/GUIFrame.cs index 33c18c969..ecfee361d 100644 --- a/Subsurface/GUI/GUIFrame.cs +++ b/Subsurface/GUI/GUIFrame.cs @@ -27,5 +27,17 @@ namespace Subsurface parent.AddChild(this); } + public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch) + { + base.Draw(spriteBatch); + + Color newColor = color; + if (state == ComponentState.Selected) newColor = selectedColor; + if (state == ComponentState.Hover) newColor = hoverColor; + + GUI.DrawRectangle(spriteBatch, rect, newColor * alpha, true); + DrawChildren(spriteBatch); + } + } } diff --git a/Subsurface/GUI/GUIListBox.cs b/Subsurface/GUI/GUIListBox.cs index ff20dd83c..8f5db6ddc 100644 --- a/Subsurface/GUI/GUIListBox.cs +++ b/Subsurface/GUI/GUIListBox.cs @@ -117,7 +117,7 @@ namespace Subsurface public override void Update(float deltaTime) { base.Update(deltaTime); - + scrollBar.Update(deltaTime); } @@ -188,7 +188,7 @@ namespace Subsurface public override void Draw(SpriteBatch spriteBatch) { - + base.Draw(spriteBatch); GUI.DrawRectangle(spriteBatch, rect, color*alpha, true); int x = rect.X, y = rect.Y; @@ -206,7 +206,6 @@ namespace Subsurface } } - for (int i = 0; i < children.Count; i++ ) { GUIComponent child = children[i]; @@ -232,7 +231,7 @@ namespace Subsurface if (CheckSelected() != selected.UserData) selected = null; } } - else if (child.Rect.Contains(PlayerInput.GetMouseState.Position) && enabled) + else if (enabled && (MouseOn==this || ( MouseOn!=null && this.IsParentOf(MouseOn))) && child.Rect.Contains(PlayerInput.GetMouseState.Position)) { child.State = ComponentState.Hover; if (PlayerInput.LeftButtonClicked()) diff --git a/Subsurface/GUI/GUIMessageBox.cs b/Subsurface/GUI/GUIMessageBox.cs index f11d31889..1676c778f 100644 --- a/Subsurface/GUI/GUIMessageBox.cs +++ b/Subsurface/GUI/GUIMessageBox.cs @@ -3,27 +3,29 @@ using System.Collections.Generic; namespace Subsurface { - class GUIMessageBox + class GUIMessageBox : GUIFrame { public static Queue messageBoxes = new Queue(); const int DefaultWidth=400, DefaultHeight=200; - public delegate bool OnClickedHandler(GUIButton button, object obj); - public OnClickedHandler OnClicked; + //public delegate bool OnClickedHandler(GUIButton button, object obj); + //public OnClickedHandler OnClicked; - GUIFrame frame; + //GUIFrame frame; GUIButton[] buttons; public GUIMessageBox(string header, string text) : this(header, text, new string[] {"OK"}) - { } - - public GUIMessageBox(string header, string text, string[] buttons, Alignment textAlignment = (Alignment.Left |Alignment.Top)) { - frame = new GUIFrame(new Rectangle(Game1.GraphicsWidth/2-DefaultWidth/2, Game1.GraphicsHeight/2-DefaultHeight/2, DefaultWidth, DefaultHeight), - GUI.style.backGroundColor, Alignment.CenterX, GUI.style); - frame.Padding = GUI.style.smallPadding; + this.buttons[0].OnClicked = OkClicked; + } + + public GUIMessageBox(string header, string text, string[] buttons, Alignment textAlignment = (Alignment.Left | Alignment.Top)) + : base(new Rectangle(Game1.GraphicsWidth / 2 - DefaultWidth / 2, Game1.GraphicsHeight / 2 - DefaultHeight / 2, DefaultWidth, DefaultHeight), + GUI.style.backGroundColor, Alignment.CenterX, GUI.style) + { + Padding = GUI.style.smallPadding; if (buttons == null || buttons.Length == 0) { @@ -31,24 +33,25 @@ namespace Subsurface return; } - new GUITextBlock(new Rectangle(0, 5, 0, 30), header, Color.Transparent, Color.White, textAlignment, frame, true); - new GUITextBlock(new Rectangle(0,50,0,DefaultHeight-70),text, Color.Transparent, Color.White, textAlignment, frame, true); + new GUITextBlock(new Rectangle(0, 0, 0, 30), header, Color.Transparent, Color.White, textAlignment, this, true); + new GUITextBlock(new Rectangle(0, 30, 0, DefaultHeight - 70), text, Color.Transparent, Color.White, textAlignment, this, true); int x = 0; this.buttons = new GUIButton[buttons.Length]; - for (int i=0; i protected override void Initialize() { - // TODO: Add your initialization logic here base.Initialize(); particleManager = new ParticleManager("Content/Particles/prefabs.xml", Cam); @@ -145,15 +144,15 @@ namespace Subsurface AmbientSoundManager.Init("Content/Sounds/Sounds.xml"); Map.PreloadMaps("Content/SavedMaps"); - gameScreen = new GameScreen(graphics.GraphicsDevice); - mainMenuScreen = new MainMenuScreen(this); - lobbyScreen = new LobbyScreen(); - netLobbyScreen = new NetLobbyScreen(); - editMapScreen = new EditMapScreen(); - editCharacterScreen = new EditCharacterScreen(); + GameScreen = new GameScreen(graphics.GraphicsDevice); + MainMenuScreen = new MainMenuScreen(this); + LobbyScreen = new LobbyScreen(); + NetLobbyScreen = new NetLobbyScreen(); + EditMapScreen = new EditMapScreen(); + EditCharacterScreen = new EditCharacterScreen(); - mainMenuScreen.Select(); + MainMenuScreen.Select(); } /// @@ -179,19 +178,22 @@ namespace Subsurface PlayerInput.Update(deltaTime); + //if (PlayerInput.KeyDown(Keys.Escape)) Quit(); DebugConsole.Update(this, (float)deltaTime); - if (!DebugConsole.IsOpen || server != null || client != null) Screen.Selected.Update(deltaTime); + if (!DebugConsole.IsOpen || Server != null || Client != null) Screen.Selected.Update(deltaTime); - if (server != null) + GUI.Update((float)deltaTime); + + if (Server != null) { - server.Update(); + Server.Update(); } - else if (client != null) + else if (Client != null) { - client.Update(); + Client.Update(); } else { @@ -219,7 +221,7 @@ namespace Subsurface protected override void OnExiting(object sender, EventArgs args) { - if (client != null) client.Disconnect(); + if (Client != null) Client.Disconnect(); base.OnExiting(sender, args); } diff --git a/Subsurface/GameSession/CrewManager.cs b/Subsurface/GameSession/CrewManager.cs index 78daf7c79..ea3d019e0 100644 --- a/Subsurface/GameSession/CrewManager.cs +++ b/Subsurface/GameSession/CrewManager.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using System.Xml.Linq; namespace Subsurface { @@ -25,7 +26,7 @@ namespace Subsurface set { money = (int)Math.Max(value, 0.0f); } } - public CrewManager(GameSession session) + public CrewManager() { characters = new List(); characterInfos = new List(); @@ -39,19 +40,17 @@ namespace Subsurface money = 10000; } - private string CreateSaveFile(string mapName) + public CrewManager(XElement element) + : this() { - string path = "Content/Data/Saves/"; + money = ToolBox.GetAttributeInt(element, "money", 0); - string name = Path.GetFileNameWithoutExtension(mapName); - - int i = 0; - while (File.Exists(path+name + i)) + foreach (XElement subElement in element.Elements()) { - i++; - } + if (subElement.Name.ToString().ToLower()!="character") continue; - return path + name + i; + characterInfos.Add(new CharacterInfo(subElement)); + } } public bool SelectCharacter(object selection) @@ -89,7 +88,7 @@ namespace Subsurface GUITextBlock textBlock = new GUITextBlock( new Rectangle(40,0,0,25), name, - Color.Transparent, Color.Black, + Color.Transparent, Color.White, Alignment.Left, Alignment.Left, frame); @@ -98,6 +97,11 @@ namespace Subsurface new GUIImage(new Rectangle(-10,-10,0,0), character.animController.limbs[0].sprite, Alignment.Left, frame); } + public void Update(float deltaTime) + { + guiFrame.Update(deltaTime); + } + public void KillCharacter(Character killedCharacter) { GUIComponent characterBlock = listBox.GetChild(killedCharacter) as GUIComponent; @@ -138,5 +142,19 @@ namespace Subsurface { guiFrame.Draw(spriteBatch); } + + public void Save(XElement parentElement) + { + XElement element = new XElement("crew"); + + element.Add(new XAttribute("money", money)); + + foreach (CharacterInfo ci in characterInfos) + { + ci.Save(element); + } + + parentElement.Add(element); + } } } diff --git a/Subsurface/GameSession/GameMode.cs b/Subsurface/GameSession/GameMode.cs index 6cbe9a703..ab7e72f67 100644 --- a/Subsurface/GameSession/GameMode.cs +++ b/Subsurface/GameSession/GameMode.cs @@ -75,7 +75,7 @@ namespace Subsurface if (endMessage != "" || this.endMessage == null) this.endMessage = endMessage; - Game1.gameSession.EndShift(null, null); + Game1.GameSession.EndShift(null, null); } public static void Init() diff --git a/Subsurface/GameSession/GameSession.cs b/Subsurface/GameSession/GameSession.cs index 47b8fd635..6dda2ee69 100644 --- a/Subsurface/GameSession/GameSession.cs +++ b/Subsurface/GameSession/GameSession.cs @@ -4,6 +4,9 @@ using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; +using System.Text; +using System.Collections.Generic; +using System.Xml.Linq; namespace Subsurface { @@ -18,6 +21,8 @@ namespace Subsurface public readonly GameMode gameMode; + private GUIFrame guiRoot; + private GUIListBox chatBox; private GUITextBox textBox; @@ -25,57 +30,85 @@ namespace Subsurface private GUIButton endShiftButton; - string saveFile; + private string savePath; + private Map selectedMap; + private int day; - public string SaveFile - { - get { return saveFile; } - } - public int Day { get { return day; } } - public GameSession(string selectedMapFile, bool save, TimeSpan gameDuration, GameMode gameMode = null) + public GameSession(Map selectedMap, TimeSpan gameDuration, GameMode gameMode = null) { taskManager = new TaskManager(this); - crewManager = new CrewManager(this); + crewManager = new CrewManager(); hireManager = new HireManager(); + savePath = SaveUtil.CreateSavePath(SaveUtil.SaveFolder); + hireManager.GenerateCharacters("Content/Characters/Human/human.xml", 10); + guiRoot = new GUIFrame(new Rectangle(0,0,Game1.GraphicsWidth,Game1.GraphicsWidth), Color.Transparent); + int width = 350, height = 100; - chatBox = new GUIListBox(new Rectangle( - Game1.GraphicsWidth - (int)GUI.style.smallPadding.X - width, - Game1.GraphicsHeight - (int)GUI.style.smallPadding.W*2 - 25 - height, - width, height), - Color.White * 0.5f); + if (Game1.Client!=null || Game1.Server!=null) + { + chatBox = new GUIListBox(new Rectangle( + Game1.GraphicsWidth - (int)GUI.style.smallPadding.X - width, + Game1.GraphicsHeight - (int)GUI.style.smallPadding.W*2 - 25 - height, + width, height), + Color.White * 0.5f, guiRoot); - endShiftButton = new GUIButton(new Rectangle(Game1.GraphicsWidth - 240, 20, 100, 25), "End shift", Color.White, Alignment.CenterX, null); - endShiftButton.OnClicked = EndShift; + textBox = new GUITextBox( + new Rectangle(chatBox.Rect.X, chatBox.Rect.Y + chatBox.Rect.Height + (int)GUI.style.smallPadding.W, chatBox.Rect.Width, 25), + Color.White * 0.5f, Color.Black, Alignment.Bottom, Alignment.Left, guiRoot); + textBox.OnEnter = EnterChatMessage; + } - timerBar = new GUIProgressBar(new Rectangle(Game1.GraphicsWidth - 120, 20, 100, 25), Color.Gold, 0.0f, null); + if (Game1.Client==null) + { + endShiftButton = new GUIButton(new Rectangle(Game1.GraphicsWidth - 240, 20, 100, 25), "End shift", Color.White, Alignment.Left | Alignment.Top, guiRoot); + endShiftButton.OnClicked = EndShift; + } + + timerBar = new GUIProgressBar(new Rectangle(Game1.GraphicsWidth - 120, 20, 100, 25), Color.Gold, 0.0f, guiRoot); - textBox = new GUITextBox( - new Rectangle(chatBox.Rect.X, chatBox.Rect.Y + chatBox.Rect.Height + (int)GUI.style.smallPadding.W, chatBox.Rect.Width, 25), - Color.White * 0.5f, Color.Black, Alignment.Bottom, Alignment.Left); - textBox.OnEnter = EnterChatMessage; this.gameMode = gameMode; - if (this.gameMode != null) this.gameMode.Start(Game1.netLobbyScreen.GameDuration); + if (this.gameMode != null) this.gameMode.Start(Game1.NetLobbyScreen.GameDuration); startTime = DateTime.Now; - endTime = startTime + gameDuration; + endTime = startTime + gameDuration; - if (!save) return; - - CreateSaveFile(selectedMapFile); - - day = 1; + this.selectedMap = selectedMap; + //if (!save) return; + + //CreateSaveFile(selectedMapFile); + + day = 1; + } + + public GameSession(string filePath) + : this(null, new TimeSpan(0,0,0,0)) + { + XDocument doc = ToolBox.TryLoadXml(filePath); + if (doc == null) return; + + day = ToolBox.GetAttributeInt(doc.Root,"day",1); + + foreach (XElement subElement in doc.Root.Elements()) + { + if (subElement.Name.ToString().ToLower()=="crew") + { + crewManager = new CrewManager(subElement); + } + } + + savePath = filePath; } public bool TryHireCharacter(CharacterInfo characterInfo) @@ -99,32 +132,58 @@ namespace Subsurface { if (crewManager.characterInfos.Count == 0) return; + if (Map.Loaded!=selectedMap) selectedMap.Load(); + crewManager.StartShift(); taskManager.StartShift(scriptedEventCount); } public bool EndShift(GUIButton button, object obj) { - if (Game1.server!=null) + if (Game1.Server!=null) { string endMessage = gameMode.EndMessage; - Game1.server.EndGame(endMessage); + Game1.Server.EndGame(endMessage); } - else if (Game1.client==null) + else if (Game1.Client==null) { - if (saveFile == null) return false; + StringBuilder sb = new StringBuilder(); + List casualties = crewManager.characters.FindAll(c => c.IsDead); - Map.Loaded.SaveAs(Path.GetDirectoryName(saveFile) + "/"+ Path.GetFileName(saveFile)); + if (casualties.Any()) + { + sb.Append("Casualties: \n"); + foreach (Character c in casualties) + { + sb.Append(" - " + c.info.name + "\n"); + } + } + else + { + sb.Append("No casualties!"); + } + + new GUIMessageBox("Day #" + day + " is over!\n", sb.ToString()); + + + //if (saveFile == null) return false; + + //Map.Loaded.SaveAs(saveFile); crewManager.EndShift(); - Game1.lobbyScreen.Select(); + Game1.LobbyScreen.Select(); day++; } + for (int i = Character.characterList.Count - 1; i >= 0; i--) + { + Character.characterList.RemoveAt(i); + } + taskManager.EndShift(); return true; @@ -132,46 +191,46 @@ namespace Subsurface private void CreateSaveFile(string mapName) { - string path = "Content/Data/Saves/"; + //string path = "Content/Data/Saves/"; - if (!Directory.Exists(path)) - { - Directory.CreateDirectory(path); - } + //if (!Directory.Exists(path)) + //{ + // Directory.CreateDirectory(path); + //} - string name = Path.GetFileNameWithoutExtension(mapName); - string extension = Path.GetExtension(mapName); + //string name = Path.GetFileNameWithoutExtension(mapName); + //string extension = Path.GetExtension(mapName); - int i = 0; - while (File.Exists(path + name + i + extension)) - { - i++; - } + //int i = 0; + //while (File.Exists(path + name + i + extension)) + //{ + // i++; + //} - saveFile = path + name + i+extension; + //saveFile = path + name + i+extension; - try - { - File.Copy(mapName, saveFile); - } - catch (Exception e) - { - DebugConsole.ThrowError("Copying map file ''" + mapName + "'' to ''" + saveFile + "'' failed", e); - } + //try + //{ + // File.Copy(mapName, saveFile); + //} + //catch (Exception e) + //{ + // DebugConsole.ThrowError("Copying map file ''" + mapName + "'' to ''" + saveFile + "'' failed", e); + //} } public bool EnterChatMessage(GUITextBox textBox, string message) { if (string.IsNullOrWhiteSpace(message)) return false; - if (Game1.server!=null) + if (Game1.Server!=null) { - Game1.server.SendChatMessage(message); + Game1.Server.SendChatMessage(message); } - else if (Game1.client!=null) + else if (Game1.Client!=null) { - Game1.client.SendChatMessage(Game1.client.Name + ": " + message); + Game1.Client.SendChatMessage(Game1.Client.Name + ": " + message); } textBox.Deselect(); @@ -197,8 +256,14 @@ namespace Subsurface public void Update(float deltaTime) { taskManager.Update(deltaTime); + if (endShiftButton!=null) endShiftButton.Enabled = !taskManager.CriticalTasks; - textBox.Update(deltaTime); + + guiRoot.Update(deltaTime); + crewManager.Update(deltaTime); + //endShiftButton.Update(deltaTime); + + //textBox.Update(deltaTime); if (gameMode != null) gameMode.Update(); @@ -222,15 +287,33 @@ namespace Subsurface public void Draw(SpriteBatch spriteBatch) { + guiRoot.Draw(spriteBatch); crewManager.Draw(spriteBatch); taskManager.Draw(spriteBatch); - chatBox.Draw(spriteBatch); - textBox.Draw(spriteBatch); + //chatBox.Draw(spriteBatch); + //textBox.Draw(spriteBatch); - timerBar.Draw(spriteBatch); + //timerBar.Draw(spriteBatch); - if (Game1.client == null) endShiftButton.Draw(spriteBatch); + //if (Game1.Client == null) endShiftButton.Draw(spriteBatch); + } + + public void Save(string filePath) + { + XDocument doc = new XDocument( + new XElement((XName)"Gamesession")); + + doc.Root.Add(new XAttribute("day", day)); + + try + { + doc.Save(filePath); + } + catch + { + DebugConsole.ThrowError("Saving gamesession to ''" + filePath + "'' failed!"); + } } } } diff --git a/Subsurface/GameSession/TraitorMode.cs b/Subsurface/GameSession/TraitorMode.cs index 0557c6c45..e114f9fbb 100644 --- a/Subsurface/GameSession/TraitorMode.cs +++ b/Subsurface/GameSession/TraitorMode.cs @@ -40,21 +40,21 @@ namespace Subsurface if (traitor==null || target ==null) { - int clientCount = Game1.server.connectedClients.Count(); + int clientCount = Game1.Server.connectedClients.Count(); if (clientCount < 2) return; int traitorIndex = Game1.localRandom.Next(clientCount); - traitor = Game1.server.connectedClients[traitorIndex]; + traitor = Game1.Server.connectedClients[traitorIndex]; int targetIndex = 0; while (targetIndex==traitorIndex) { targetIndex = Game1.localRandom.Next(clientCount); } - target = Game1.server.connectedClients[targetIndex]; + target = Game1.Server.connectedClients[targetIndex]; - Game1.server.NewTraitor(traitor, target); + Game1.Server.NewTraitor(traitor, target); } else { diff --git a/Subsurface/IPropertyObject.cs b/Subsurface/IPropertyObject.cs index 618fad5c2..be8de376d 100644 --- a/Subsurface/IPropertyObject.cs +++ b/Subsurface/IPropertyObject.cs @@ -4,6 +4,11 @@ namespace Subsurface { interface IPropertyObject { + string Name + { + get; + } + Dictionary ObjectProperties { get; diff --git a/Subsurface/Items/Components/Container.cs b/Subsurface/Items/Components/Container.cs index 3e4e74a9e..288470e32 100644 --- a/Subsurface/Items/Components/Container.cs +++ b/Subsurface/Items/Components/Container.cs @@ -115,54 +115,20 @@ namespace Subsurface.Items.Components foreach (StatusEffect effect in ri.statusEffects) { - if (effect.Targets.HasFlag(StatusEffect.Target.This)) effect.Apply(ActionType.OnContaining, deltaTime, item); - if (effect.Targets.HasFlag(StatusEffect.Target.Contained)) effect.Apply(ActionType.OnContaining, deltaTime, contained); + if (effect.Targets.HasFlag(StatusEffect.TargetType.This)) effect.Apply(ActionType.OnContaining, deltaTime, item.SimPosition, item.AllPropertyObjects); + if (effect.Targets.HasFlag(StatusEffect.TargetType.Contained)) effect.Apply(ActionType.OnContaining, deltaTime, item.SimPosition, contained.AllPropertyObjects); } contained.ApplyStatusEffects(ActionType.OnContained, deltaTime); } - //if (hideItems) return; - - //Vector2 transformedItemPos; - //Vector2 transformedItemInterval = itemInterval; - ////float transformedItemRotation = itemRotation; - //if (item.body==null) - //{ - // transformedItemPos = new Vector2(item.Rect.X, item.Rect.Y); - // transformedItemPos = ConvertUnits.ToSimUnits(transformedItemPos) + itemPos; - //} - //else - //{ - // Matrix transform = Matrix.CreateRotationZ(item.body.Rotation); - - // transformedItemPos = item.body.Position + Vector2.Transform(itemPos, transform); - // transformedItemInterval = Vector2.Transform(transformedItemInterval, transform); - // //transformedItemRotation += item.body.Rotation; - //} - - //foreach (Item containedItem in inventory.items) - //{ - // if (containedItem == null) continue; - - // Vector2 itemDist = (transformedItemPos - containedItem.body.Position); - // Vector2 force = (itemDist - containedItem.body.LinearVelocity * 0.1f) * containedItem.body.Mass * 60.0f; - - // containedItem.body.ApplyForce(force); - - // containedItem.body.SmoothRotate(itemRotation); - - // transformedItemPos += transformedItemInterval; - //} - - } public override void Draw(SpriteBatch spriteBatch) { base.Draw(spriteBatch); - if (hideItems) return; + if (hideItems || (item.body!=null && !item.body.Enabled)) return; Vector2 transformedItemPos = itemPos; Vector2 transformedItemInterval = itemInterval; @@ -175,6 +141,8 @@ namespace Subsurface.Items.Components } else { + //item.body.Enabled = true; + Matrix transform = Matrix.CreateRotationZ(item.body.Rotation); if (item.body.Dir==-1.0f) @@ -184,9 +152,7 @@ namespace Subsurface.Items.Components } transformedItemPos = Vector2.Transform(transformedItemPos, transform); transformedItemInterval = Vector2.Transform(transformedItemInterval, transform); - - - + transformedItemPos += ConvertUnits.ToDisplayUnits(item.body.Position); currentRotation += item.body.Rotation; @@ -230,7 +196,7 @@ namespace Subsurface.Items.Components if (inventory.TryPutItem(item)) { isActive = true; - if (hideItems) item.body.Enabled = false; + if (hideItems || (item.body!=null && !item.body.Enabled)) item.body.Enabled = false; item.container = this.item; diff --git a/Subsurface/Items/Components/Controller.cs b/Subsurface/Items/Components/Controller.cs index e5b455468..1e4f2c072 100644 --- a/Subsurface/Items/Components/Controller.cs +++ b/Subsurface/Items/Components/Controller.cs @@ -134,14 +134,14 @@ namespace Subsurface.Items.Components } } - public override bool Use(Character activator = null) + public override bool Use(float deltaTime, Character activator = null) { character = activator; foreach (MapEntity e in item.linkedTo) { Item linkedItem = e as Item; if (linkedItem == null) continue; - linkedItem.Use(activator); + linkedItem.Use(deltaTime, activator); } ApplyStatusEffects(ActionType.OnUse, 1.0f, character); @@ -149,7 +149,7 @@ namespace Subsurface.Items.Components return true; } - public override void SecondaryUse(Character character = null) + public override void SecondaryUse(float deltaTime, Character character = null) { if (character == null) return; @@ -157,7 +157,7 @@ namespace Subsurface.Items.Components { Item linkedItem = e as Item; if (linkedItem == null) continue; - linkedItem.SecondaryUse(character); + linkedItem.SecondaryUse(deltaTime, character); } } diff --git a/Subsurface/Items/Components/Door.cs b/Subsurface/Items/Components/Door.cs index 2f5b47d9e..aa6bd1cbd 100644 --- a/Subsurface/Items/Components/Door.cs +++ b/Subsurface/Items/Components/Door.cs @@ -19,6 +19,21 @@ namespace Subsurface.Items.Components ConvexHull convexHull; ConvexHull convexHull2; + private float stuck; + public float Stuck + { + get { return stuck; } + set + { + if (isOpen) return; + stuck = MathHelper.Clamp(value, 0.0f, 100.0f); + if (stuck == 0.0f) isStuck = false; + if (stuck == 100.0f) isStuck = true; + } + } + + private bool isStuck; + Gap LinkedGap { get @@ -35,8 +50,9 @@ namespace Subsurface.Items.Components return linkedGap; } } - + bool isOpen; + float openState; [HasDefaultValue("0.0,0.0,0.0,0.0", false)] @@ -199,7 +215,7 @@ namespace Subsurface.Items.Components { base.Move(amount); - linkedGap.Move(amount); + LinkedGap.Move(amount); body.SetTransform(body.Position + ConvertUnits.ToSimUnits(amount), 0.0f); @@ -217,9 +233,12 @@ namespace Subsurface.Items.Components public override void Update(float deltaTime, Camera cam) { - OpenState += deltaTime * ((isOpen) ? 3.0f : -3.0f); + if (!isStuck) + { + OpenState += deltaTime * ((isOpen) ? 3.0f : -3.0f); + LinkedGap.Open = openState; + } - LinkedGap.Open = openState; item.SendSignal((isOpen) ? "1" : "0", "state_out"); } diff --git a/Subsurface/Items/Components/Holdable.cs b/Subsurface/Items/Components/Holdable.cs index 84b375006..47d054880 100644 --- a/Subsurface/Items/Components/Holdable.cs +++ b/Subsurface/Items/Components/Holdable.cs @@ -166,7 +166,7 @@ namespace Subsurface.Items.Components return true; } - public override bool Use(Character character = null) + public override bool Use(float deltaTime, Character character = null) { if (!attachable || item.body==null) return false; @@ -213,7 +213,7 @@ namespace Subsurface.Items.Components public override void OnMapLoaded() { - if (attached) Use(); + if (attached) Use(1.0f); } } } diff --git a/Subsurface/Items/Components/ItemComponent.cs b/Subsurface/Items/Components/ItemComponent.cs index e57b3c3b9..5e7763ff8 100644 --- a/Subsurface/Items/Components/ItemComponent.cs +++ b/Subsurface/Items/Components/ItemComponent.cs @@ -9,6 +9,7 @@ using Microsoft.Xna.Framework.Graphics; using Subsurface.Networking; using Subsurface.Items.Components; using System.IO; +using System.Globalization; namespace Subsurface { @@ -17,6 +18,8 @@ namespace Subsurface public readonly Sound sound; public readonly ActionType type; + public string volumeProperty; + public readonly float range; public ItemSound(Sound sound, ActionType type, float range) @@ -143,6 +146,7 @@ namespace Subsurface switch (subElement.Name.ToString().ToLower()) { case "requireditem": + case "requireditems": RelatedItem ri = RelatedItem.Load(subElement); if (ri != null) requiredItems.Add(ri); break; @@ -172,8 +176,9 @@ namespace Subsurface Sound sound = Sound.Load(filePath); float range = ToolBox.GetAttributeFloat(subElement, "range", 800.0f); - - sounds.Add(new ItemSound(sound, type, range)); + ItemSound itemSound = new ItemSound(sound, type, range); + itemSound.volumeProperty = ToolBox.GetAttributeString(subElement, "volume", ""); + sounds.Add(itemSound); break; } @@ -193,16 +198,30 @@ namespace Subsurface int index = Game1.localRandom.Next(matchingSounds.Count); itemSound = sounds[index]; + if (itemSound.volumeProperty != "") + { + ObjectProperty op = null; + if (properties.TryGetValue(itemSound.volumeProperty.ToLower(), out op)) + { + float newVolume = 0.0f; + float.TryParse(op.GetValue().ToString(), NumberStyles.Any, CultureInfo.InvariantCulture, out newVolume); + volume = MathHelper.Clamp(newVolume, 0.0f, 1.0f); + } + + } + if (loop) loopingSound = itemSound; } - + if (loop) { + //if (loopingSound != null && loopingSound.volumeProperty != "") volume = float.Parse(properties[loopingSound.volumeProperty].GetValue().ToString()); loopingSoundIndex = loopingSound.sound.Loop(loopingSoundIndex, volume, position, loopingSound.range); } else { + itemSound.sound.Play(volume, itemSound.range, position); } } @@ -246,13 +265,13 @@ namespace Subsurface //called when the item is equipped and left mouse button is pressed //returns true if the item was used succesfully (not out of ammo, reloading, etc) - public virtual bool Use(Character character = null) + public virtual bool Use(float deltaTime, Character character = null) { return false; } //called when the item is equipped and right mouse button is pressed - public virtual void SecondaryUse(Character character = null) { } + public virtual void SecondaryUse(float deltaTime, Character character = null) { } //called when the item is placed in a "limbslot" public virtual void Equip(Character character) { } @@ -272,7 +291,13 @@ namespace Subsurface return false; } - public virtual void Remove() { } + public virtual void Remove() + { + if (loopingSound!=null) + { + Sounds.SoundManager.Stop(loopingSoundIndex); + } + } public bool HasRequiredContainedItems(bool addMessage) { @@ -329,12 +354,21 @@ namespace Subsurface return true; } - public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null, Limb limb = null) + public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null) { foreach (StatusEffect effect in statusEffects) { if (effect.type != type) continue; - item.ApplyStatusEffect(effect, type, deltaTime, character, limb); + item.ApplyStatusEffect(effect, type, deltaTime, character); + } + } + + public void ApplyStatusEffects(ActionType type, float deltaTime, Vector2 position, IPropertyObject target) + { + foreach (StatusEffect effect in statusEffects) + { + if (effect.type != type) continue; + effect.Apply(type, deltaTime, position, target); } } diff --git a/Subsurface/Items/Components/OxygenGenerator.cs b/Subsurface/Items/Components/OxygenGenerator.cs index f060f2be8..75e6bcc13 100644 --- a/Subsurface/Items/Components/OxygenGenerator.cs +++ b/Subsurface/Items/Components/OxygenGenerator.cs @@ -8,13 +8,15 @@ namespace Subsurface.Items.Components { PropertyTask powerUpTask; + float powerDownTimer; + bool running; List ventList; public bool IsRunning() { - return running && item.Condition>0.0f; + return (running && item.Condition>0.0f); } public OxygenGenerator(Item item, XElement element) @@ -38,13 +40,18 @@ namespace Subsurface.Items.Components if (voltage < minVoltage) { + powerDownTimer += deltaTime; running = false; - if (powerUpTask==null || powerUpTask.IsFinished) + if ((powerUpTask==null || powerUpTask.IsFinished) && powerDownTimer>5.0f) { - powerUpTask = new PropertyTask(Game1.gameSession.taskManager, item, IsRunning, 30.0f, "Turn on the oxygen generator"); + powerUpTask = new PropertyTask(item, IsRunning, 50.0f, "Turn on the oxygen generator"); } return; } + else + { + powerDownTimer = 0.0f; + } running = true; @@ -53,9 +60,15 @@ namespace Subsurface.Items.Components UpdateVents(deltaOxygen); + voltage = 0.0f; } + public override void UpdateBroken(float deltaTime, Camera cam) + { + powerDownTimer += deltaTime; + } + private void GetVents() { foreach (MapEntity entity in item.linkedTo) diff --git a/Subsurface/Items/Components/Pickable.cs b/Subsurface/Items/Components/Pickable.cs index c466126aa..2815ecd97 100644 --- a/Subsurface/Items/Components/Pickable.cs +++ b/Subsurface/Items/Components/Pickable.cs @@ -48,7 +48,7 @@ namespace Subsurface.Items.Components if (!picker.HasSelectedItem(item) && item.body!=null) item.body.Enabled = false; this.picker = picker; - ApplyStatusEffects(ActionType.OnPicked, 1.0f, picker, null); + ApplyStatusEffects(ActionType.OnPicked, 1.0f, picker); //foreach (StatusEffect effect in item.Prefab.statusEffects) //{ diff --git a/Subsurface/Items/Components/Powered.cs b/Subsurface/Items/Components/Powered.cs index e3651ccc4..1546f95a0 100644 --- a/Subsurface/Items/Components/Powered.cs +++ b/Subsurface/Items/Components/Powered.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Xml.Linq; namespace Subsurface.Items.Components @@ -62,7 +63,7 @@ namespace Subsurface.Items.Components { if (connection.name=="power_in") { - if (!float.TryParse(signal, out voltage)) + if (!float.TryParse(signal, NumberStyles.Any, CultureInfo.InvariantCulture, out voltage)) { voltage = 0.0f; } diff --git a/Subsurface/Items/Components/Projectile.cs b/Subsurface/Items/Components/Projectile.cs index 8857103a7..6a2f04b70 100644 --- a/Subsurface/Items/Components/Projectile.cs +++ b/Subsurface/Items/Components/Projectile.cs @@ -75,11 +75,11 @@ namespace Subsurface.Items.Components //} - public override bool Use(Character character = null) + public override bool Use(float deltaTime, Character character = null) { if (character != null && !characterUsable) return false; - ApplyStatusEffects(ActionType.OnUse, 1.0f, character); + //ApplyStatusEffects(ActionType.OnUse, 1.0f, character); Debug.WriteLine(item.body.Rotation); diff --git a/Subsurface/Items/Components/RangedWeapon.cs b/Subsurface/Items/Components/RangedWeapon.cs index c82aeb818..5affe69de 100644 --- a/Subsurface/Items/Components/RangedWeapon.cs +++ b/Subsurface/Items/Components/RangedWeapon.cs @@ -14,10 +14,11 @@ namespace Subsurface.Items.Components private Vector2 barrelPos; - //[Initable(new Vector2(0.0f, 0.0f))] - public Vector2 BarrelPos + [HasDefaultValue("0.0,0.0", false)] + public string BarrelPos { - get { return new Vector2(barrelPos.X * item.body.Dir, barrelPos.Y); } + get { return ToolBox.Vector2ToString(ConvertUnits.ToDisplayUnits(barrelPos)); } + set { barrelPos = ConvertUnits.ToSimUnits(ToolBox.ParseToVector2(value)); } } public Vector2 TransformedBarrelPos @@ -25,7 +26,9 @@ namespace Subsurface.Items.Components get { Matrix bodyTransform = Matrix.CreateRotationZ(item.body.Rotation); - return (Vector2.Transform(BarrelPos, bodyTransform) + item.body.Position); + Vector2 flippedPos = barrelPos; + if (item.body.Dir < 0.0f) flippedPos.X = -flippedPos.X; + return (Vector2.Transform(flippedPos, bodyTransform) + item.body.Position); } } @@ -47,7 +50,7 @@ namespace Subsurface.Items.Components } } - public override bool Use(Character character = null) + public override bool Use(float deltaTime, Character character = null) { if (character == null) return false; if (!character.SecondaryKeyDown.State || reload > 0.0f) return false; @@ -78,7 +81,7 @@ namespace Subsurface.Items.Components projectile.SetTransform(TransformedBarrelPos, (item.body.Dir == 1.0f) ? item.body.Rotation : item.body.Rotation - MathHelper.Pi); - projectile.Use(); + projectile.Use(deltaTime); item.RemoveContained(projectile); //recoil diff --git a/Subsurface/Items/Components/Reactor.cs b/Subsurface/Items/Components/Reactor.cs index ca44980b5..d47887699 100644 --- a/Subsurface/Items/Components/Reactor.cs +++ b/Subsurface/Items/Components/Reactor.cs @@ -108,9 +108,8 @@ namespace Subsurface.Items.Components public override void Update(float deltaTime, Camera cam) { - ApplyStatusEffects(ActionType.OnActive, deltaTime, null); - - + //ApplyStatusEffects(ActionType.OnActive, deltaTime, null); + fissionRate = Math.Min(fissionRate, AvailableFuel); float heat = 100 * fissionRate; @@ -128,7 +127,7 @@ namespace Subsurface.Items.Components { if (powerUpTask==null || powerUpTask.IsFinished) { - powerUpTask = new PropertyTask(Game1.gameSession.taskManager, item, IsRunning, 20.0f, "Power up the reactor"); + powerUpTask = new PropertyTask(item, IsRunning, 50.0f, "Power up the reactor"); } } @@ -208,7 +207,7 @@ namespace Subsurface.Items.Components { if (item.Condition <= 0.0f) return; - new RepairTask(Game1.gameSession.taskManager, item, 50.0f, "Reactor meltdown!"); + new RepairTask(item, 60.0f, "Reactor meltdown!"); item.Condition = 0.0f; fissionRate = 0.0f; coolingRate = 0.0f; diff --git a/Subsurface/Items/Components/RepairTool.cs b/Subsurface/Items/Components/RepairTool.cs index dd0012aaa..9571498ba 100644 --- a/Subsurface/Items/Components/RepairTool.cs +++ b/Subsurface/Items/Components/RepairTool.cs @@ -5,6 +5,7 @@ using FarseerPhysics; using FarseerPhysics.Dynamics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using Subsurface.Particles; namespace Subsurface.Items.Components { @@ -16,29 +17,49 @@ namespace Subsurface.Items.Components Vector2 pickedPosition; + Vector2 barrelPos; + float structureFixAmount, limbFixAmount; - [HasDefaultValue(100.0f, false)] + [HasDefaultValue(0.0f, false)] public float Range { get { return ConvertUnits.ToDisplayUnits(range); } set { range = ConvertUnits.ToSimUnits(value); } } - [HasDefaultValue(1.0f, false)] + [HasDefaultValue(0.0f, false)] public float StructureFixAmount { get { return structureFixAmount; } set { structureFixAmount = value; } } - [HasDefaultValue(1.0f, false)] + [HasDefaultValue(0.0f, false)] public float LimbFixAmount { get { return limbFixAmount; } set { limbFixAmount = value; } } + [HasDefaultValue("0.0,0.0", false)] + public string BarrelPos + { + get { return ToolBox.Vector2ToString(ConvertUnits.ToDisplayUnits(barrelPos)); } + set { barrelPos = ConvertUnits.ToSimUnits(ToolBox.ParseToVector2(value)); } + } + + public Vector2 TransformedBarrelPos + { + get + { + Matrix bodyTransform = Matrix.CreateRotationZ(item.body.Rotation); + Vector2 flippedPos = barrelPos; + if (item.body.Dir < 0.0f) flippedPos.X = -flippedPos.X; + return (Vector2.Transform(flippedPos, bodyTransform) + item.body.Position); + } + } + public RepairTool(Item item, XElement element) : base(item, element) { @@ -69,16 +90,18 @@ namespace Subsurface.Items.Components //} - public override bool Use(Character character = null) + public override bool Use(float deltaTime, Character character = null) { if (character == null) return false; + isActive = true; + Vector2 targetPosition = item.body.Position; //targetPosition = targetPosition.X, -targetPosition.Y); targetPosition += new Vector2( - (float)Math.Cos(item.body.Rotation) * range, - (float)Math.Sin(item.body.Rotation) * range) * item.body.Dir; + (float)Math.Cos(item.body.Rotation), + (float)Math.Sin(item.body.Rotation)) * range * item.body.Dir; List ignoredBodies = new List(); foreach (Limb limb in character.animController.limbs) @@ -86,13 +109,12 @@ namespace Subsurface.Items.Components ignoredBodies.Add(limb.body.FarseerBody); } - - Body targetBody = Map.PickBody(item.body.Position, targetPosition, ignoredBodies); + Body targetBody = Map.PickBody(TransformedBarrelPos, targetPosition, ignoredBodies); pickedPosition = Map.LastPickedPosition; - if (targetBody==null || targetBody.UserData==null) return false; + if (targetBody==null || targetBody.UserData==null) return true; - ApplyStatusEffects(ActionType.OnUse, 1.0f, character); + //ApplyStatusEffects(ActionType.OnUse, 1.0f, character); Structure targetStructure; @@ -100,45 +122,70 @@ namespace Subsurface.Items.Components Item targetItem; if ((targetStructure = (targetBody.UserData as Structure)) != null) { - if (!fixableEntities.Contains(targetStructure.Name)) return false; + if (!fixableEntities.Contains(targetStructure.Name)) return true; int sectionIndex = targetStructure.FindSectionIndex(ConvertUnits.ToDisplayUnits(pickedPosition)); - if (sectionIndex < 0) return false; + if (sectionIndex < 0) return true; targetStructure.HighLightSection(sectionIndex); - if (character.SecondaryKeyDown.State) - { - targetStructure.AddDamage(sectionIndex, -structureFixAmount); - isActive = true; - } + } else if ((targetLimb = (targetBody.UserData as Limb)) != null) { if (character.SecondaryKeyDown.State) { - targetLimb.Damage -= limbFixAmount; - isActive = true; + targetLimb.character.Health += limbFixAmount; + //isActive = true; } } - else if ((targetItem = (targetBody.UserData as Item)) !=null) + else if ((targetItem = (targetBody.UserData as Item)) != null) { - targetItem.Condition -= structureFixAmount; + //targetItem.Condition -= structureFixAmount; + targetItem.IsHighlighted = true; + + foreach (StatusEffect effect in statusEffects) + { + //if (Array.IndexOf(effect.TargetNames, targetItem.Name) == -1) continue; + effect.Apply(ActionType.OnUse, deltaTime, item.SimPosition, targetItem.AllPropertyObjects); + //targetItem.ApplyStatusEffect(effect, ActionType.OnUse, deltaTime); + } + //ApplyStatusEffects(ActionType.OnUse, 1.0f, null, targ); } + //if (character.SecondaryKeyDown.State) + //{ + // IPropertyObject propertyObject = targetBody.UserData as IPropertyObject; + // if (propertyObject!=null) ApplyStatusEffects(ActionType.OnUse, 1.0f, item.SimPosition, propertyObject); + // //isActive = true; + //} + return true; } + public override void Update(float deltaTime, Camera cam) + { + base.Update(deltaTime, cam); + + //isActive = true; + } + public override void Draw(SpriteBatch spriteBatch) { if (!isActive) return; - Vector2 startPos = ConvertUnits.ToDisplayUnits(item.body.Position); - Vector2 endPos = ConvertUnits.ToDisplayUnits(pickedPosition); - endPos = new Vector2(endPos.X + Game1.localRandom.Next(-2, 2), endPos.Y + Game1.localRandom.Next(-2, 2)); + Vector2 particleSpeed = new Vector2( + (float)Math.Cos(item.body.Rotation), + (float)Math.Sin(item.body.Rotation)) *item.body.Dir * 5.0f; - GUI.DrawLine(spriteBatch, startPos, endPos, Color.Orange, 0.0f); + Game1.particleManager.CreateParticle("weld", TransformedBarrelPos, particleSpeed); + + //Vector2 startPos = ConvertUnits.ToDisplayUnits(item.body.Position); + //Vector2 endPos = ConvertUnits.ToDisplayUnits(pickedPosition); + //endPos = new Vector2(endPos.X + Game1.localRandom.Next(-2, 2), endPos.Y + Game1.localRandom.Next(-2, 2)); + + //GUI.DrawLine(spriteBatch, startPos, endPos, Color.Orange, 0.0f); isActive = false; } diff --git a/Subsurface/Items/Components/Rope.cs b/Subsurface/Items/Components/Rope.cs index 2d89415d5..0f541e78a 100644 --- a/Subsurface/Items/Components/Rope.cs +++ b/Subsurface/Items/Components/Rope.cs @@ -40,8 +40,8 @@ namespace Subsurface.Items.Components { Vector2 barrelPos = Vector2.Zero; - RangedWeapon weapon = item.GetComponent(); - if (weapon != null) barrelPos = weapon.BarrelPos; + //RangedWeapon weapon = item.GetComponent(); + //if (weapon != null) barrelPos = weapon.barrelPos; return barrelPos; } @@ -120,7 +120,7 @@ namespace Subsurface.Items.Components } - public override void SecondaryUse(Character character = null) + public override void SecondaryUse(float deltaTime, Character character = null) { if (reload > 0.0f) return; diff --git a/Subsurface/Items/Components/Signal/Wire.cs b/Subsurface/Items/Components/Signal/Wire.cs index ced4a556c..56553d701 100644 --- a/Subsurface/Items/Components/Signal/Wire.cs +++ b/Subsurface/Items/Components/Signal/Wire.cs @@ -142,7 +142,7 @@ namespace Subsurface.Items.Components //} } - public override bool Use(Character character = null) + public override bool Use(float deltaTime, Character character = null) { if (newNodePos!= Vector2.Zero && nodes.Count>0 && Vector2.Distance(newNodePos, nodes[nodes.Count - 1]) > nodeDistance) { @@ -155,7 +155,7 @@ namespace Subsurface.Items.Components return true; } - public override void SecondaryUse(Character character = null) + public override void SecondaryUse(float deltaTime, Character character = null) { if (nodes.Count > 1) { diff --git a/Subsurface/Items/Components/Throwable.cs b/Subsurface/Items/Components/Throwable.cs index bf21e5e73..78faa506f 100644 --- a/Subsurface/Items/Components/Throwable.cs +++ b/Subsurface/Items/Components/Throwable.cs @@ -25,7 +25,7 @@ namespace Subsurface.Items.Components //throwForce = ToolBox.GetAttributeFloat(element, "throwforce", 1.0f); } - public override bool Use(Character character = null) + public override bool Use(float deltaTime, Character character = null) { if (character == null) return false; if (!character.SecondaryKeyDown.State || throwing) return false; @@ -36,7 +36,7 @@ namespace Subsurface.Items.Components return true; } - public override void SecondaryUse(Character character = null) + public override void SecondaryUse(float deltaTime, Character character = null) { if (throwing) return; throwPos = 0.25f; @@ -54,7 +54,7 @@ namespace Subsurface.Items.Components { Update(deltaTime, cam); } - + public override void Update(float deltaTime, Camera cam) { if (!item.body.Enabled) return; @@ -68,11 +68,11 @@ namespace Subsurface.Items.Components AnimController ac = picker.animController; - ac.HoldItem(deltaTime, cam, item, handlePos, new Vector2(throwPos, 0.0f), Vector2.Zero, holdAngle); + ac.HoldItem(deltaTime, cam, item, handlePos, new Vector2(throwPos, 0.0f), aimPos, holdAngle); if (!throwing) return; - throwPos +=0.1f; + throwPos += deltaTime*5.0f; Vector2 throwVector = ConvertUnits.ToSimUnits(picker.CursorPosition) - item.body.Position; throwVector = Vector2.Normalize(throwVector); diff --git a/Subsurface/Items/Components/Turret.cs b/Subsurface/Items/Components/Turret.cs index aca69bcdf..a5d5d3d31 100644 --- a/Subsurface/Items/Components/Turret.cs +++ b/Subsurface/Items/Components/Turret.cs @@ -123,7 +123,7 @@ namespace Subsurface.Items.Components //cam.OffsetAmount = prefab.OffsetOnSelected; } - public override void SecondaryUse(Character character = null) + public override void SecondaryUse(float deltaTime, Character character = null) { if (character == null) return; Vector2 centerPos = new Vector2(item.Rect.X + barrelPos.X, item.Rect.Y - barrelPos.Y); @@ -142,7 +142,7 @@ namespace Subsurface.Items.Components } } - public override bool Use(Character character = null) + public override bool Use(float deltaTime, Character character = null) { if (reload > 0.0f) return false; @@ -202,7 +202,7 @@ namespace Subsurface.Items.Components //if (useSounds.Count() > 0) useSounds[Game1.localRandom.Next(useSounds.Count())].Play(1.0f, 800.0f, item.body.FarseerBody); - projectileComponent.Use(); + projectileComponent.Use(deltaTime); item.RemoveContained(projectile); return true; diff --git a/Subsurface/Items/Components/Wearable.cs b/Subsurface/Items/Components/Wearable.cs index 8f59f09f6..db693fd27 100644 --- a/Subsurface/Items/Components/Wearable.cs +++ b/Subsurface/Items/Components/Wearable.cs @@ -115,22 +115,14 @@ namespace Subsurface.Items.Components Item[] containedItems = item.ContainedItems; + ApplyStatusEffects(ActionType.OnWearing, deltaTime, picker); - for (int i = 0; i < limb.Length; i++) + if (containedItems == null) return; + for (int j = 0; j AllPropertyObjects + { + get + { + List pobjects = new List(); + pobjects.Add(this); + foreach (ItemComponent ic in components) + { + pobjects.Add(ic); + } + return pobjects; + } + } + List highlightText; public List HighlightText @@ -308,18 +322,18 @@ namespace Subsurface } - public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null, Limb limb = null) + public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null) { foreach (ItemComponent ic in components) { foreach (StatusEffect effect in ic.statusEffects) { - ApplyStatusEffect(effect, type, deltaTime, character, limb); + ApplyStatusEffect(effect, type, deltaTime, character); } } } - public void ApplyStatusEffect(StatusEffect effect, ActionType type, float deltaTime, Character character = null, Limb limb = null) + public void ApplyStatusEffect(StatusEffect effect, ActionType type, float deltaTime, Character character = null) { if (condition == 0.0f) return; @@ -334,9 +348,11 @@ namespace Subsurface } } + List targets = new List(); + if (containedItems!=null) { - if (effect.Targets.HasFlag(StatusEffect.Target.Contained)) + if (effect.Targets.HasFlag(StatusEffect.TargetType.Contained)) { foreach (Item containedItem in containedItems) { @@ -344,7 +360,8 @@ namespace Subsurface if (effect.TargetNames != null && !effect.TargetNames.Contains(containedItem.Name)) continue; hasTargets = true; - effect.Apply(type, deltaTime, containedItem); + targets.Add(containedItem); + //effect.Apply(type, deltaTime, containedItem); //containedItem.ApplyStatusEffect(effect, type, deltaTime, containedItem); } } @@ -353,19 +370,27 @@ namespace Subsurface if (hasTargets) { - if (effect.Targets.HasFlag(StatusEffect.Target.This)) - effect.Apply(type, deltaTime, this); + if (effect.Targets.HasFlag(StatusEffect.TargetType.This)) + { + foreach (var pobject in AllPropertyObjects) + { + targets.Add(pobject); + } + } + //effect.Apply(type, deltaTime, this); //ApplyStatusEffect(effect, type, deltaTime, this); - if (effect.Targets.HasFlag(StatusEffect.Target.Character)) - effect.Apply(type, deltaTime, null, character, limb); + if (effect.Targets.HasFlag(StatusEffect.TargetType.Character)) targets.Add(character); + //effect.Apply(type, deltaTime, null, character); //ApplyStatusEffect(effect, type, deltaTime, null, character, limb); - if (container != null && effect.Targets.HasFlag(StatusEffect.Target.Parent)) - { - effect.Apply(type, deltaTime, container); - //container.ApplyStatusEffect(effect, type, deltaTime, container); - } + if (container != null && effect.Targets.HasFlag(StatusEffect.TargetType.Parent)) targets.Add(container); + //{ + // effect.Apply(type, deltaTime, container); + // //container.ApplyStatusEffect(effect, type, deltaTime, container); + //} + + effect.Apply(type, deltaTime, SimPosition, targets); } } @@ -388,7 +413,7 @@ namespace Subsurface ic.Update(deltaTime, cam); ic.PlaySound(ActionType.OnActive, 1.0f, Position, true); - ic.ApplyStatusEffects(ActionType.OnActive, 1.0f, null); + ic.ApplyStatusEffects(ActionType.OnActive, deltaTime, null); } else { @@ -712,28 +737,28 @@ namespace Subsurface } - public void Use(Character character = null) + public void Use(float deltaTime, Character character = null) { if (condition == 0.0f) return; foreach (ItemComponent ic in components) { if (!ic.HasRequiredContainedItems(character == Character.Controlled)) continue; - if (ic.Use(character)) + if (ic.Use(deltaTime, character)) { ic.PlaySound(ActionType.OnUse, 1.0f, Position); - ic.ApplyStatusEffects(ActionType.OnUse, 1.0f, character); + ic.ApplyStatusEffects(ActionType.OnUse, deltaTime, character); } } } - public void SecondaryUse(Character character = null) + public void SecondaryUse(float deltaTime, Character character = null) { foreach (ItemComponent ic in components) { if (!ic.HasRequiredContainedItems(character == Character.Controlled)) continue; - ic.SecondaryUse(character); + ic.SecondaryUse(deltaTime, character); } } diff --git a/Subsurface/Map/Map.cs b/Subsurface/Map/Map.cs index b167034e8..64dd2ca72 100644 --- a/Subsurface/Map/Map.cs +++ b/Subsurface/Map/Map.cs @@ -1,14 +1,14 @@ -using System; +using FarseerPhysics; +using FarseerPhysics.Collision; +using FarseerPhysics.Dynamics; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Xml.Linq; -using FarseerPhysics; -using FarseerPhysics.Dynamics; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; -using FarseerPhysics.Collision; namespace Subsurface { @@ -62,6 +62,8 @@ namespace Subsurface { get { + if (mapHash != null) return mapHash; + XDocument doc = OpenDoc(filePath); mapHash = new MapHash(doc); @@ -286,8 +288,7 @@ namespace Subsurface try { - //string docString = doc.ToString(); - ToolBox.CompressStringToFile(filePath+".gz", doc.ToString()); + SaveUtil.CompressStringToFile(filePath, doc.ToString()); } catch { @@ -295,7 +296,18 @@ namespace Subsurface } - doc.Save(filePath); + //doc.Save(filePath); + } + + public static void SaveCurrent(string savePath) + { + if (loaded==null) + { + loaded = new Map(savePath); + return; + } + + loaded.SaveAs(savePath); } public static void PreloadMaps(string mapFolder) @@ -342,7 +354,15 @@ namespace Subsurface public Map(string filePath, string mapHash="") { this.filePath = filePath; - name = Path.GetFileNameWithoutExtension(filePath); + try + { + name = Path.GetFileNameWithoutExtension(filePath); + } + catch (Exception e) + { + DebugConsole.ThrowError("Error loading map " + filePath + "!", e); + } + if (mapHash != "") { @@ -380,7 +400,7 @@ namespace Subsurface if (extension == ".gz") { - Stream stream = ToolBox.DecompressFiletoStream(file); + Stream stream = SaveUtil.DecompressFiletoStream(file); if (stream == null) { DebugConsole.ThrowError("Loading map ''" + file + "'' failed!"); @@ -496,7 +516,7 @@ namespace Subsurface public static void Unload() { - if (loaded==null)return; + if (loaded == null) return; loaded.Clear(); loaded = null; } @@ -505,12 +525,12 @@ namespace Subsurface { filePath = ""; - if (Game1.gameScreen.Cam != null) Game1.gameScreen.Cam.TargetPos = Vector2.Zero; + if (Game1.GameScreen.Cam != null) Game1.GameScreen.Cam.TargetPos = Vector2.Zero; Entity.RemoveAll(); - if (Game1.gameSession!=null) - Game1.gameSession.crewManager.EndShift(); + if (Game1.GameSession!=null) + Game1.GameSession.crewManager.EndShift(); PhysicsBody.list.Clear(); diff --git a/Subsurface/Map/Structure.cs b/Subsurface/Map/Structure.cs index d80521510..0bb628ef3 100644 --- a/Subsurface/Map/Structure.cs +++ b/Subsurface/Map/Structure.cs @@ -345,7 +345,7 @@ namespace Subsurface { if (!prefab.HasBody || prefab.IsPlatform) return; - if (Game1.client==null) + if (Game1.Client==null) SetDamage(sectionIndex, sections[sectionIndex].damage + damage); diff --git a/Subsurface/Networking/GameClient.cs b/Subsurface/Networking/GameClient.cs index 5c52a6b20..eae49a78e 100644 --- a/Subsurface/Networking/GameClient.cs +++ b/Subsurface/Networking/GameClient.cs @@ -134,11 +134,11 @@ namespace Subsurface.Networking int existingClients = inc.ReadInt32(); for (int i = 1; i <= existingClients; i++) { - Game1.netLobbyScreen.AddPlayer(inc.ReadString()); + Game1.NetLobbyScreen.AddPlayer(inc.ReadString()); } //add the name of own client to the lobby screen - Game1.netLobbyScreen.AddPlayer(name); + Game1.NetLobbyScreen.AddPlayer(name); CanStart = true; } @@ -147,7 +147,7 @@ namespace Subsurface.Networking string msg = inc.ReadString(); DebugConsole.ThrowError(msg); - Game1.mainMenuScreen.Select(); + Game1.MainMenuScreen.Select(); } break; case NetIncomingMessageType.StatusChanged: @@ -172,8 +172,8 @@ namespace Subsurface.Networking if (myCharacter.IsDead) { Character.Controlled = null; - Game1.gameScreen.Cam.TargetPos = Vector2.Zero; - Game1.gameScreen.Cam.Zoom = 1.0f; + Game1.GameScreen.Cam.TargetPos = Vector2.Zero; + Game1.GameScreen.Cam.Zoom = 1.0f; } else { @@ -228,7 +228,7 @@ namespace Subsurface.Networking string mapName = inc.ReadString(); string mapHash = inc.ReadString(); - Game1.netLobbyScreen.TrySelectMap(mapName, mapHash); + Game1.NetLobbyScreen.TrySelectMap(mapName, mapHash); //Map.Load(mapFile); @@ -240,8 +240,8 @@ namespace Subsurface.Networking TimeSpan duration = new TimeSpan(0,(int)durationMinutes,0); //int gameModeIndex = inc.ReadInt32(); - Game1.gameSession = new GameSession("", false, duration); - Game1.gameSession.StartShift(1); + Game1.GameSession = new GameSession(Map.Loaded, duration); + Game1.GameSession.StartShift(1); myCharacter = ReadCharacterData(inc); Character.Controlled = myCharacter; @@ -254,7 +254,7 @@ namespace Subsurface.Networking gameStarted = true; - Game1.gameScreen.Select(); + Game1.GameScreen.Select(); AddChatMessage("Press TAB to chat", ChatMessageType.Server); @@ -268,7 +268,7 @@ namespace Subsurface.Networking Client otherClient = new Client(); otherClient.name = inc.ReadString(); - Game1.netLobbyScreen.AddPlayer(otherClient.name); + Game1.NetLobbyScreen.AddPlayer(otherClient.name); //string newPlayerName = inc.ReadString(); //int newPlayerID = inc.ReadInt32(); @@ -285,7 +285,7 @@ namespace Subsurface.Networking string leavingName = inc.ReadString(); AddChatMessage(inc.ReadString(), ChatMessageType.Server); - Game1.netLobbyScreen.RemovePlayer(leavingName); + Game1.NetLobbyScreen.RemovePlayer(leavingName); break; case (byte)PacketTypes.KickedOut: @@ -293,7 +293,7 @@ namespace Subsurface.Networking DebugConsole.ThrowError(msg); - Game1.mainMenuScreen.Select(); + Game1.MainMenuScreen.Select(); break; case (byte)PacketTypes.Chatmessage: @@ -307,13 +307,13 @@ namespace Subsurface.Networking break; case (byte)PacketTypes.UpdateNetLobby: if (gameStarted) continue; - Game1.netLobbyScreen.ReadData(inc); + Game1.NetLobbyScreen.ReadData(inc); break; case (byte)PacketTypes.Traitor: string targetName = inc.ReadString(); - Game1.gameSession.NewChatMessage("You are an agent of Ordo Europae", messageColor[(int)ChatMessageType.Server]); - Game1.gameSession.NewChatMessage("Your secret task is to assassinate " + targetName + "!", messageColor[(int)ChatMessageType.Server]); + Game1.GameSession.NewChatMessage("You are an agent of Ordo Europae", messageColor[(int)ChatMessageType.Server]); + Game1.GameSession.NewChatMessage("Your secret task is to assassinate " + targetName + "!", messageColor[(int)ChatMessageType.Server]); break; } @@ -325,9 +325,9 @@ namespace Subsurface.Networking { Map.Unload(); - Game1.netLobbyScreen.Select(); + Game1.NetLobbyScreen.Select(); - if (Game1.gameSession!=null) Game1.gameSession.EndShift(null, null); + if (Game1.GameSession!=null) Game1.GameSession.EndShift(null, null); DebugConsole.ThrowError(endMessage); diff --git a/Subsurface/Networking/GameServer.cs b/Subsurface/Networking/GameServer.cs index a4b782e35..8704f091b 100644 --- a/Subsurface/Networking/GameServer.cs +++ b/Subsurface/Networking/GameServer.cs @@ -119,7 +119,7 @@ namespace Subsurface.Networking else { - Game1.netLobbyScreen.AddPlayer(sender.name); + Game1.NetLobbyScreen.AddPlayer(sender.name); // Notify the client that they have logged in outmsg = Server.CreateMessage(); @@ -271,12 +271,12 @@ namespace Subsurface.Networking int seed = DateTime.Now.Millisecond; Game1.random = new Random(seed); - Map selectedMap = Game1.netLobbyScreen.SelectedMap as Map; + Map selectedMap = Game1.NetLobbyScreen.SelectedMap as Map; - selectedMap.Load(); + //selectedMap.Load(); - Game1.gameSession = new GameSession("", false, Game1.netLobbyScreen.GameDuration, Game1.netLobbyScreen.SelectedMode); - Game1.gameSession.StartShift(1); + Game1.GameSession = new GameSession(selectedMap, Game1.NetLobbyScreen.GameDuration, Game1.NetLobbyScreen.SelectedMode); + Game1.GameSession.StartShift(1); //EventManager.SelectEvent(Game1.netLobbyScreen.SelectedEvent); foreach (Client client in connectedClients) @@ -307,10 +307,10 @@ namespace Subsurface.Networking msg.Write(seed); - msg.Write(Game1.netLobbyScreen.SelectedMap.Name); - msg.Write(Game1.netLobbyScreen.SelectedMap.MapHash.MD5Hash); + msg.Write(Game1.NetLobbyScreen.SelectedMap.Name); + msg.Write(Game1.NetLobbyScreen.SelectedMap.MapHash.MD5Hash); - msg.Write(Game1.netLobbyScreen.GameDuration.TotalMinutes); + msg.Write(Game1.NetLobbyScreen.GameDuration.TotalMinutes); WriteCharacterData(msg, client.name, client.character); @@ -331,9 +331,9 @@ namespace Subsurface.Networking gameStarted = true; - Game1.gameScreen.Cam.TargetPos = Vector2.Zero; + Game1.GameScreen.Cam.TargetPos = Vector2.Zero; - Game1.gameScreen.Select(); + Game1.GameScreen.Select(); return true; } @@ -362,7 +362,7 @@ namespace Subsurface.Networking } } - Game1.netLobbyScreen.Select(); + Game1.NetLobbyScreen.Select(); DebugConsole.ThrowError(endMessage); } @@ -394,7 +394,7 @@ namespace Subsurface.Networking outmsg.Write(client.name); outmsg.Write(msg); - Game1.netLobbyScreen.RemovePlayer(client.name); + Game1.NetLobbyScreen.RemovePlayer(client.name); if (Server.Connections.Count > 0) { @@ -435,7 +435,7 @@ namespace Subsurface.Networking { NetOutgoingMessage msg = Server.CreateMessage(); msg.Write((byte)PacketTypes.UpdateNetLobby); - Game1.netLobbyScreen.WriteData(msg); + Game1.NetLobbyScreen.WriteData(msg); if (Server.Connections.Count > 0) { diff --git a/Subsurface/Networking/NetworkEvent.cs b/Subsurface/Networking/NetworkEvent.cs index 5544e590a..688c727b0 100644 --- a/Subsurface/Networking/NetworkEvent.cs +++ b/Subsurface/Networking/NetworkEvent.cs @@ -53,11 +53,11 @@ namespace Subsurface.Networking { if (isClient) { - if (Game1.server != null) return; + if (Game1.Server != null) return; } else { - if (Game1.server == null) return; + if (Game1.Server == null) return; } eventType = type; diff --git a/Subsurface/Networking/NetworkMember.cs b/Subsurface/Networking/NetworkMember.cs index be8c68799..bc4bad54f 100644 --- a/Subsurface/Networking/NetworkMember.cs +++ b/Subsurface/Networking/NetworkMember.cs @@ -37,8 +37,8 @@ namespace Subsurface.Networking public void AddChatMessage(string message, ChatMessageType messageType) { - Game1.netLobbyScreen.NewChatMessage(message, messageColor[(int)messageType]); - if (Game1.gameSession != null) Game1.gameSession.NewChatMessage(message, messageColor[(int)messageType]); + Game1.NetLobbyScreen.NewChatMessage(message, messageColor[(int)messageType]); + if (Game1.GameSession != null) Game1.GameSession.NewChatMessage(message, messageColor[(int)messageType]); GUI.PlayMessageSound(); } diff --git a/Subsurface/SaveUtil.cs b/Subsurface/SaveUtil.cs new file mode 100644 index 000000000..397d46e52 --- /dev/null +++ b/Subsurface/SaveUtil.cs @@ -0,0 +1,185 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Text; + +namespace Subsurface +{ + class SaveUtil + { + public const string SaveFolder = "Content/SavedMaps/"; + + public delegate void ProgressDelegate(string sMessage); + + public static void SaveGame(string directory) + { + if (Directory.Exists(directory)) + { + Directory.Delete(directory, true); + } + + Directory.CreateDirectory(directory); + + Map.Loaded.SaveAs(directory+"\\map.gz"); + + Game1.GameSession.Save(directory+"\\gamesession.xml"); + //Game1.GameSession.crewManager.Save(directory+"\\crew.xml"); + + CompressDirectory(directory, directory+".save", null); + + Directory.Delete(directory, true); + } + + public static void LoadGame(string filePath) + { + DecompressToDirectory(filePath+".save", Path.GetDirectoryName(filePath)+"\\temp", null); + + Map.Load(Path.GetDirectoryName(filePath) + "\\temp\\map.gz"); + Game1.GameSession = new GameSession(Path.GetDirectoryName(filePath) + "\\temp\\gamesession.gz"); + + } + + public static string CreateSavePath(string saveFolder, string fileName="save") + { + if (!Directory.Exists(saveFolder)) + { + DebugConsole.ThrowError("Save folder ''"+saveFolder+"'' not found. Created new folder"); + Directory.CreateDirectory(saveFolder); + } + + string extension = ".save"; + + int i = 0; + while (File.Exists(saveFolder + fileName + i + extension)) + { + i++; + } + + return saveFolder + fileName + i + extension; + } + + public static void CompressStringToFile(string fileName, string value) + { + // A. + // Write string to temporary file. + string temp = Path.GetTempFileName(); + File.WriteAllText(temp, value); + + // B. + // Read file into byte array buffer. + byte[] b; + using (FileStream f = new FileStream(temp, FileMode.Open)) + { + b = new byte[f.Length]; + f.Read(b, 0, (int)f.Length); + } + + // C. + // Use GZipStream to write compressed bytes to target file. + using (FileStream f2 = new FileStream(fileName, FileMode.Create)) + using (GZipStream gz = new GZipStream(f2, CompressionMode.Compress, false)) + { + gz.Write(b, 0, b.Length); + } + } + + public static Stream DecompressFiletoStream(string fileName) + { + if (!File.Exists(fileName)) + { + DebugConsole.ThrowError("File ''"+fileName+" doesn't exist!"); + return null; + } + + using (FileStream originalFileStream = new FileStream(fileName, FileMode.Open)) + { + MemoryStream decompressedFileStream = new MemoryStream(); + + using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress)) + { + decompressionStream.CopyTo(decompressedFileStream); + return decompressedFileStream; + } + } + } + + public static void CompressFile(string sDir, string sRelativePath, GZipStream zipStream) + { + //Compress file name + char[] chars = sRelativePath.ToCharArray(); + zipStream.Write(BitConverter.GetBytes(chars.Length), 0, sizeof(int)); + foreach (char c in chars) + zipStream.Write(BitConverter.GetBytes(c), 0, sizeof(char)); + + //Compress file content + byte[] bytes = File.ReadAllBytes(Path.Combine(sDir, sRelativePath)); + zipStream.Write(BitConverter.GetBytes(bytes.Length), 0, sizeof(int)); + zipStream.Write(bytes, 0, bytes.Length); + } + + public static bool DecompressFile(string sDir, GZipStream zipStream, ProgressDelegate progress) + { + //Decompress file name + byte[] bytes = new byte[sizeof(int)]; + int Readed = zipStream.Read(bytes, 0, sizeof(int)); + if (Readed < sizeof(int)) + return false; + + int iNameLen = BitConverter.ToInt32(bytes, 0); + bytes = new byte[sizeof(char)]; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < iNameLen; i++) + { + zipStream.Read(bytes, 0, sizeof(char)); + char c = BitConverter.ToChar(bytes, 0); + sb.Append(c); + } + string sFileName = sb.ToString(); + if (progress != null) + progress(sFileName); + + //Decompress file content + bytes = new byte[sizeof(int)]; + zipStream.Read(bytes, 0, sizeof(int)); + int iFileLen = BitConverter.ToInt32(bytes, 0); + + bytes = new byte[iFileLen]; + zipStream.Read(bytes, 0, bytes.Length); + + string sFilePath = Path.Combine(sDir, sFileName); + string sFinalDir = Path.GetDirectoryName(sFilePath); + if (!Directory.Exists(sFinalDir)) + Directory.CreateDirectory(sFinalDir); + + using (FileStream outFile = new FileStream(sFilePath, FileMode.Create, FileAccess.Write, FileShare.None)) + outFile.Write(bytes, 0, iFileLen); + + return true; + } + + public static void CompressDirectory(string sInDir, string sOutFile, ProgressDelegate progress) + { + string[] sFiles = Directory.GetFiles(sInDir, "*.*", SearchOption.AllDirectories); + int iDirLen = sInDir[sInDir.Length - 1] == Path.DirectorySeparatorChar ? sInDir.Length : sInDir.Length + 1; + + using (FileStream outFile = new FileStream(sOutFile, FileMode.Create, FileAccess.Write, FileShare.None)) + using (GZipStream str = new GZipStream(outFile, CompressionMode.Compress)) + foreach (string sFilePath in sFiles) + { + string sRelativePath = sFilePath.Substring(iDirLen); + if (progress != null) + progress(sRelativePath); + CompressFile(sInDir, sRelativePath, str); + } + } + + public static void DecompressToDirectory(string sCompressedFile, string sDir, ProgressDelegate progress) + { + using (FileStream inFile = new FileStream(sCompressedFile, FileMode.Open, FileAccess.Read, FileShare.None)) + using (GZipStream zipStream = new GZipStream(inFile, CompressionMode.Decompress, true)) + while (DecompressFile(sDir, zipStream, progress)) ; + } + } +} diff --git a/Subsurface/Screens/EditCharacterScreen.cs b/Subsurface/Screens/EditCharacterScreen.cs index efe93490c..d5e05605e 100644 --- a/Subsurface/Screens/EditCharacterScreen.cs +++ b/Subsurface/Screens/EditCharacterScreen.cs @@ -74,7 +74,7 @@ namespace Subsurface if (physicsEnabled) { - editingCharacter.Control(cam); + editingCharacter.Control(1.0f, cam); } else { diff --git a/Subsurface/Screens/EditMapScreen.cs b/Subsurface/Screens/EditMapScreen.cs index 5e775503d..bce806af2 100644 --- a/Subsurface/Screens/EditMapScreen.cs +++ b/Subsurface/Screens/EditMapScreen.cs @@ -94,7 +94,7 @@ namespace Subsurface public override void Select() { base.Select(); - + GUIComponent.MouseOn = null; characterMode = false; //CreateDummyCharacter(); @@ -197,7 +197,7 @@ namespace Subsurface } dummyCharacter.ControlLocalPlayer(cam, false); - dummyCharacter.Control(cam); + dummyCharacter.Control((float)deltaTime, cam); } else { diff --git a/Subsurface/Screens/GameScreen.cs b/Subsurface/Screens/GameScreen.cs index 0444d78f5..989b60c86 100644 --- a/Subsurface/Screens/GameScreen.cs +++ b/Subsurface/Screens/GameScreen.cs @@ -38,7 +38,7 @@ namespace Subsurface { base.Select(); - if (Game1.gameSession == null) Game1.gameSession = new GameSession("",false, TimeSpan.Zero); + //if (Game1.gameSession == null) Game1.gameSession = new GameSession("",false, TimeSpan.Zero); foreach (MapEntity entity in MapEntity.mapEntityList) entity.IsHighlighted = false; @@ -57,7 +57,18 @@ namespace Subsurface AmbientSoundManager.Update(); - Game1.gameSession.Update((float)deltaTime); + //Vector2 targetMovement = Vector2.Zero; + //if (PlayerInput.KeyDown(Keys.I)) targetMovement.Y += 1.0f; + //if (PlayerInput.KeyDown(Keys.K)) targetMovement.Y -= 1.0f; + //if (PlayerInput.KeyDown(Keys.J)) targetMovement.X -= 1.0f; + //if (PlayerInput.KeyDown(Keys.L)) targetMovement.X += 1.0f; + + //foreach (MapEntity e in Structure.mapEntityList) + //{ + // e.Move(targetMovement); + //} + + if (Game1.GameSession!=null) Game1.GameSession.Update((float)deltaTime); //EventManager.Update(gameTime); Character.UpdateAll(cam, (float)deltaTime); @@ -107,7 +118,7 @@ namespace Subsurface //---------------------------------------------------------------------------------------- spriteBatch.Begin(); - if (Game1.gameSession != null) Game1.gameSession.Draw(spriteBatch); + if (Game1.GameSession != null) Game1.GameSession.Draw(spriteBatch); //EventManager.DrawInfo(spriteBatch); diff --git a/Subsurface/Screens/LobbyScreen.cs b/Subsurface/Screens/LobbyScreen.cs index 5477bbc9f..f2233466a 100644 --- a/Subsurface/Screens/LobbyScreen.cs +++ b/Subsurface/Screens/LobbyScreen.cs @@ -96,7 +96,7 @@ namespace Subsurface { base.Select(); - Map.Unload(); + //Map.Unload(); UpdateCharacterLists(); @@ -105,7 +105,7 @@ namespace Subsurface private void UpdateCharacterLists() { characterList.ClearChildren(); - foreach (CharacterInfo c in Game1.gameSession.crewManager.characterInfos) + foreach (CharacterInfo c in Game1.GameSession.crewManager.characterInfos) { GUITextBlock textBlock = new GUITextBlock( new Rectangle(0, 0, 0, 25), @@ -117,7 +117,7 @@ namespace Subsurface } hireList.ClearChildren(); - foreach (CharacterInfo c in Game1.gameSession.hireManager.availableCharacters) + foreach (CharacterInfo c in Game1.GameSession.hireManager.availableCharacters) { GUIFrame frame = new GUIFrame( new Rectangle(0, 0, 0, 25), @@ -144,18 +144,27 @@ namespace Subsurface } } + public override void Update(double deltaTime) + { + base.Update(deltaTime); + + leftPanel.Update((float)deltaTime); + rightPanel[selectedRightPanel].Update((float)deltaTime); + shiftPanel.Update((float)deltaTime); + } + public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch) { - if (characterList.CountChildren != Game1.gameSession.crewManager.characterInfos.Count - || hireList.CountChildren != Game1.gameSession.hireManager.availableCharacters.Count) + if (characterList.CountChildren != Game1.GameSession.crewManager.characterInfos.Count + || hireList.CountChildren != Game1.GameSession.hireManager.availableCharacters.Count) { UpdateCharacterLists(); } graphics.Clear(Color.CornflowerBlue); - Game1.gameScreen.DrawMap(graphics, spriteBatch); + Game1.GameScreen.DrawMap(graphics, spriteBatch); spriteBatch.Begin(); @@ -182,20 +191,20 @@ namespace Subsurface private string GetMoney() { - return "Money: " + ((Game1.gameSession == null) ? "" : Game1.gameSession.crewManager.Money.ToString()); + return "Money: " + ((Game1.GameSession == null) ? "" : Game1.GameSession.crewManager.Money.ToString()); } private string GetDay() { - return "Day #" + ((Game1.gameSession == null) ? "" : Game1.gameSession.Day.ToString()); + return "Day #" + ((Game1.GameSession == null) ? "" : Game1.GameSession.Day.ToString()); } private float GetWeekProgress() { - if (Game1.gameSession == null) return 0.0f; + if (Game1.GameSession == null) return 0.0f; - return (float)((Game1.gameSession.Day - 1) % 7) / 7.0f; + return (float)((Game1.GameSession.Day - 1) % 7) / 7.0f; } private bool HireCharacter(object selection) @@ -206,20 +215,21 @@ namespace Subsurface if (characterInfo == null) return false; - Game1.gameSession.TryHireCharacter(characterInfo); + Game1.GameSession.TryHireCharacter(characterInfo); return false; } private bool StartShift(GUIButton button, object selection) { - Map.Load(Game1.gameSession.SaveFile); + + //Map.Load(Game1.GameSession.SaveFile); - Game1.gameSession.StartShift(); + Game1.GameSession.StartShift(); //EventManager.StartShift(); - Game1.gameScreen.Select(); + Game1.GameScreen.Select(); return true; } diff --git a/Subsurface/Screens/MainMenu.cs b/Subsurface/Screens/MainMenu.cs index 7037e87ef..7e9ef24f1 100644 --- a/Subsurface/Screens/MainMenu.cs +++ b/Subsurface/Screens/MainMenu.cs @@ -55,23 +55,20 @@ namespace Subsurface new GUITextBlock(new Rectangle(0, 30, 0, 30), "Selected map:", Color.Transparent, Color.Black, Alignment.Left, menuTabs[(int)Tabs.NewGame]); mapList = new GUIListBox(new Rectangle(0, 60, 200, 400), Color.White, menuTabs[1]); - //string[] mapFilePaths = Map.GetMapFilePaths(); - //if (mapFilePaths!=null) - //{ - foreach (Map map in Map.SavedMaps) - { - GUITextBlock textBlock = new GUITextBlock( - new Rectangle(0, 0, 0, 25), - map.Name, - GUI.style, - Alignment.Left, - Alignment.Left, - mapList); - textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f); - textBlock.UserData = map; - } - if (Map.SavedMaps.Count > 0) mapList.Select(Map.SavedMaps[0]); - //} + foreach (Map map in Map.SavedMaps) + { + GUITextBlock textBlock = new GUITextBlock( + new Rectangle(0, 0, 0, 25), + map.Name, + GUI.style, + Alignment.Left, + Alignment.Left, + mapList); + textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f); + textBlock.UserData = map; + } + if (Map.SavedMaps.Count > 0) mapList.Select(Map.SavedMaps[0]); + button = new GUIButton(new Rectangle(0, 0, 100, 30), "Start", GUI.style, Alignment.Right | Alignment.Bottom, menuTabs[(int)Tabs.NewGame]); button.OnClicked = StartGame; @@ -112,8 +109,8 @@ namespace Subsurface private bool HostServerClicked(GUIButton button, object obj) { - Game1.netLobbyScreen.isServer = true; - Game1.netLobbyScreen.Select(); + Game1.NetLobbyScreen.isServer = true; + Game1.NetLobbyScreen.Select(); return true; } @@ -132,7 +129,7 @@ namespace Subsurface { graphics.Clear(Color.CornflowerBlue); - Game1.gameScreen.DrawMap(graphics, spriteBatch); + Game1.GameScreen.DrawMap(graphics, spriteBatch); spriteBatch.Begin(); @@ -150,9 +147,9 @@ namespace Subsurface if (selectedMap == null) return false; - Game1.gameSession = new GameSession(selectedMap.FilePath, true, TimeSpan.Zero); + Game1.GameSession = new GameSession(selectedMap, TimeSpan.Zero); - Game1.lobbyScreen.Select(); + Game1.LobbyScreen.Select(); return true; } @@ -162,15 +159,15 @@ namespace Subsurface if (string.IsNullOrEmpty(nameBox.Text)) return false; if (string.IsNullOrEmpty(ipBox.Text)) return false; - Game1.client = new GameClient(nameBox.Text); - if (Game1.client.ConnectToServer(ipBox.Text)) + Game1.Client = new GameClient(nameBox.Text); + if (Game1.Client.ConnectToServer(ipBox.Text)) { - Game1.netLobbyScreen.Select(); + Game1.NetLobbyScreen.Select(); return true; } else { - Game1.client = null; + Game1.Client = null; return false; } } diff --git a/Subsurface/Screens/NetLobbyScreen.cs b/Subsurface/Screens/NetLobbyScreen.cs index 4c68283c5..4992832d9 100644 --- a/Subsurface/Screens/NetLobbyScreen.cs +++ b/Subsurface/Screens/NetLobbyScreen.cs @@ -6,6 +6,7 @@ using Subsurface.Networking; using FarseerPhysics; using FarseerPhysics.Factories; using FarseerPhysics.Dynamics; +using System.IO; namespace Subsurface { @@ -122,7 +123,7 @@ namespace Subsurface { infoFrame.ClearChildren(); - if (isServer && Game1.server == null) Game1.server = new GameServer(); + if (isServer && Game1.Server == null) Game1.Server = new GameServer(); textBox.Select(); @@ -132,7 +133,7 @@ namespace Subsurface new GUITextBlock(new Rectangle(0, 30, 0, 30), "Selected map:", Color.Transparent, Color.Black, Alignment.Left, infoFrame); mapList = new GUIListBox(new Rectangle(0, 60, 200, 200), Color.White, infoFrame); mapList.OnSelected = SelectMap; - mapList.Enabled = (Game1.server!=null); + mapList.Enabled = (Game1.Server!=null); if (Map.SavedMaps.Count>0) { @@ -157,7 +158,7 @@ namespace Subsurface new GUITextBlock(new Rectangle(220, 30, 0, 30), "Selected game mode: ", Color.Transparent, Color.Black, Alignment.Left, infoFrame); modeList = new GUIListBox(new Rectangle(220, 60, 200, 200), Color.White, infoFrame); - modeList.Enabled = (Game1.server != null); + modeList.Enabled = (Game1.Server != null); //modeList.OnSelected = new GUIListBox.OnSelectedHandler(SelectEvent); foreach (GameMode mode in GameMode.list) @@ -180,16 +181,16 @@ namespace Subsurface durationBar = new GUIScrollBar(new Rectangle((int)(modeList.Rect.X + modeList.Rect.Width + GUI.style.smallPadding.X), modeList.Rect.Y + 30, 100, 20), Color.Gold, 0.1f, Alignment.Left, infoFrame); durationBar.BarSize = 0.1f; - durationBar.Enabled = (Game1.server != null); + durationBar.Enabled = (Game1.Server != null); - if (isServer && Game1.server!=null) + if (isServer && Game1.Server!=null) { GUIButton startButton = new GUIButton(new Rectangle(0,0,200,30), "Start", Color.White, Alignment.Right | Alignment.Bottom, infoFrame); - startButton.OnClicked = Game1.server.StartGame; + startButton.OnClicked = Game1.Server.StartGame; //mapList.OnSelected = new GUIListBox.OnSelectedHandler(Game1.server.UpdateNetLobby); - modeList.OnSelected = Game1.server.UpdateNetLobby; - durationBar.OnMoved = Game1.server.UpdateNetLobby; + modeList.OnSelected = Game1.Server.UpdateNetLobby; + durationBar.OnMoved = Game1.Server.UpdateNetLobby; if (mapList.CountChildren > 0) mapList.Select(Map.SavedMaps[0]); if (GameMode.list.Count > 0) modeList.Select(GameMode.list[0]); @@ -199,7 +200,7 @@ namespace Subsurface int x = playerFrame.Rect.Width / 2; GUITextBox playerName = new GUITextBox(new Rectangle(x, 0, 0, 20), Color.White, Color.Black, Alignment.Left | Alignment.Top, Alignment.Left, playerFrame); - playerName.Text = Game1.client.CharacterInfo.name; + playerName.Text = Game1.Client.CharacterInfo.name; playerName.OnEnter += ChangeCharacterName; new GUITextBlock(new Rectangle(x,40,200, 30), "Gender: ", Color.Transparent, Color.Black, @@ -240,7 +241,7 @@ namespace Subsurface private bool SelectMap(object obj) { - if (Game1.server != null) Game1.server.UpdateNetLobby(obj); + if (Game1.Server != null) Game1.Server.UpdateNetLobby(obj); Map map = (Map)obj; @@ -275,7 +276,7 @@ namespace Subsurface { base.Update(deltaTime); - Game1.gameScreen.Cam.MoveCamera((float)deltaTime); + Game1.GameScreen.Cam.MoveCamera((float)deltaTime); Vector2 pos = new Vector2( Map.Borders.X + Map.Borders.Width / 2, @@ -288,7 +289,7 @@ namespace Subsurface pos += offset * 0.8f; - Game1.gameScreen.Cam.TargetPos = pos; + Game1.GameScreen.Cam.TargetPos = pos; menu.Update((float)deltaTime); @@ -299,7 +300,7 @@ namespace Subsurface { graphics.Clear(Color.CornflowerBlue); - Game1.gameScreen.DrawMap(graphics, spriteBatch); + Game1.GameScreen.DrawMap(graphics, spriteBatch); spriteBatch.Begin(); @@ -310,18 +311,18 @@ namespace Subsurface spriteBatch.End(); - if (Game1.client != null) + if (Game1.Client != null) { - if (Game1.client.Character != null) + if (Game1.Client.Character != null) { Vector2 position = new Vector2(playerFrame.Rect.X + playerFrame.Rect.Width * 0.25f, playerFrame.Rect.Y + 25.0f); - Vector2 pos = Game1.client.Character.Position; + Vector2 pos = Game1.Client.Character.Position; pos.Y = -pos.Y; Matrix transform = Matrix.CreateTranslation(new Vector3(-pos+position, 0.0f)); spriteBatch.Begin(SpriteSortMode.BackToFront, null,null,null,null,null,transform); - Game1.client.Character.Draw(spriteBatch); + Game1.Client.Character.Draw(spriteBatch); spriteBatch.End(); } else @@ -346,7 +347,7 @@ namespace Subsurface public bool StartGame(object obj) { - Game1.server.StartGame(null, obj); + Game1.Server.StartGame(null, obj); return true; } @@ -356,11 +357,11 @@ namespace Subsurface if (isServer) { - Game1.server.SendChatMessage("Server: " + message); + Game1.Server.SendChatMessage("Server: " + message); } else { - Game1.client.SendChatMessage(Game1.client.Name + ": " + message); + Game1.Client.SendChatMessage(Game1.Client.Name + ": " + message); } return true; @@ -368,13 +369,13 @@ namespace Subsurface private void CreatePreviewCharacter() { - if (Game1.client.Character != null) Game1.client.Character.Remove(); + if (Game1.Client.Character != null) Game1.Client.Character.Remove(); Vector2 pos = new Vector2(1000.0f, 1000.0f); - Character character = new Character(Game1.client.CharacterInfo, pos); + Character character = new Character(Game1.Client.CharacterInfo, pos); - Game1.client.Character = character; + Game1.Client.Character = character; character.animController.isStanding = true; @@ -406,8 +407,8 @@ namespace Subsurface try { Gender gender = (Gender)obj; - Game1.client.CharacterInfo.gender = gender; - Game1.client.SendCharacterData(); + Game1.Client.CharacterInfo.gender = gender; + Game1.Client.SendCharacterData(); CreatePreviewCharacter(); } catch @@ -421,9 +422,9 @@ namespace Subsurface { if (string.IsNullOrEmpty(newName)) return false; - Game1.client.CharacterInfo.name = newName; - Game1.client.Name = newName; - Game1.client.SendCharacterData(); + Game1.Client.CharacterInfo.name = newName; + Game1.Client.Name = newName; + Game1.Client.SendCharacterData(); textBox.Text = newName; @@ -472,7 +473,7 @@ namespace Subsurface } else { - msg.Write(selectedMap.Name); + msg.Write(Path.GetFileName(selectedMap.FilePath)); msg.Write(selectedMap.MapHash.MD5Hash); } @@ -502,7 +503,7 @@ namespace Subsurface else { mapList.Select(map); - map.Load(); + //map.Load(); return true; } } diff --git a/Subsurface/Sounds/AmbientSoundManager.cs b/Subsurface/Sounds/AmbientSoundManager.cs index 4ef624a7b..01053901e 100644 --- a/Subsurface/Sounds/AmbientSoundManager.cs +++ b/Subsurface/Sounds/AmbientSoundManager.cs @@ -6,6 +6,7 @@ using FarseerPhysics; using FarseerPhysics.Dynamics; using Microsoft.Xna.Framework; using Subsurface.Sounds; +using System.Collections.Generic; namespace Subsurface { @@ -33,14 +34,36 @@ namespace Subsurface } } + public class BackgroundMusic + { + public readonly string file; + public readonly string type; + + public readonly Vector2 priorityRange; + + public BackgroundMusic(string file, string type, Vector2 priorityRange) + { + this.file = file; + this.type = type; + this.priorityRange = priorityRange; + } + } + static class AmbientSoundManager { public static Sound[] flowSounds = new Sound[3]; + private const float MusicLerpSpeed = 0.01f; + private static Sound waterAmbience; private static int waterAmbienceIndex; private static DamageSound[] damageSounds; + + private static BackgroundMusic currentMusic; + private static BackgroundMusic targetMusic; + private static BackgroundMusic[] musicClips; + private static float musicVolume; public static void Init(string filePath) { @@ -57,7 +80,7 @@ namespace Subsurface var xDamageSounds = doc.Root.Elements("damagesound").ToList(); - if (!xDamageSounds.Any()) + if (xDamageSounds.Any()) { damageSounds = new DamageSound[xDamageSounds.Count()]; int i = 0; @@ -85,6 +108,24 @@ namespace Subsurface } } + var xMusic = doc.Root.Elements("music").ToList(); + + if (xMusic.Any()) + { + musicClips = new BackgroundMusic[xMusic.Count]; + int i = 0; + foreach (XElement element in xMusic) + { + string file = ToolBox.GetAttributeString(element, "file", "").ToLower(); + string type = ToolBox.GetAttributeString(element, "type", "").ToLower(); + Vector2 priority = ToolBox.GetAttributeVector2(element, "priorityrange", new Vector2(0.0f,100.0f)); + + musicClips[i] = new BackgroundMusic(file, type, priority); + + i++; + } + } + //Sound.StartStream("Content/Sounds/Music/Simplex.ogg", 0.3f); } @@ -92,6 +133,8 @@ namespace Subsurface public static void Update() { + UpdateMusic(); + float ambienceVolume = 0.5f; float lowpassHFGain = 1.0f; if (Character.Controlled != null) @@ -110,6 +153,64 @@ namespace Subsurface waterAmbienceIndex = waterAmbience.Loop(waterAmbienceIndex, ambienceVolume); } + private static void UpdateMusic() + { + + Task criticalTask = null; + if (Game1.GameSession!=null) + { + foreach (Task task in Game1.GameSession.taskManager.Tasks) + { + if (criticalTask == null || task.Priority > criticalTask.Priority) + { + criticalTask = task; + } + } + } + + List suitableMusic = null; + if (criticalTask == null) + { + suitableMusic = musicClips.Where(x => x.type == "default").ToList(); + + } + else + { + suitableMusic = musicClips.Where(x => + x.type == criticalTask.MusicType && + x.priorityRange.X < criticalTask.Priority && + x.priorityRange.Y > criticalTask.Priority).ToList(); + } + + if (suitableMusic.Count > 0 && !suitableMusic.Contains(currentMusic)) + { + int index = Game1.localRandom.Next(suitableMusic.Count()); + + if (currentMusic == null || suitableMusic[index].file != currentMusic.file) + { + targetMusic = suitableMusic[index]; + } + } + + if (targetMusic == null || currentMusic == null || targetMusic.file != currentMusic.file) + { + musicVolume = MathHelper.Lerp(musicVolume, 0.0f, MusicLerpSpeed); + if (currentMusic != null) Sound.StreamVolume(musicVolume); + + if (musicVolume < 0.01f) + { + Sound.StopStream(); + if (targetMusic != null) Sound.StartStream(targetMusic.file, musicVolume); + currentMusic = targetMusic; + } + } + else + { + musicVolume = MathHelper.Lerp(musicVolume, 0.3f, MusicLerpSpeed); + Sound.StreamVolume(musicVolume); + } + } + public static void PlayDamageSound(DamageSoundType damageType, float damage, Body body) { Vector2 bodyPosition = ConvertUnits.ToDisplayUnits(body.Position); diff --git a/Subsurface/Sounds/Sound.cs b/Subsurface/Sounds/Sound.cs index a0e0a6ca5..0901783e2 100644 --- a/Subsurface/Sounds/Sound.cs +++ b/Subsurface/Sounds/Sound.cs @@ -13,6 +13,8 @@ namespace Subsurface private static List loadedSounds = new List(); + private static OggStream stream; + private OggSound oggSound; string filePath; @@ -218,12 +220,17 @@ namespace Subsurface public static void StartStream(string file, float volume = 1.0f) { - SoundManager.StartStream(file, volume); + stream = SoundManager.StartStream(file, volume); } - public static void Stoptream() + public static void StreamVolume(float volume = 1.0f) { - SoundManager.StopStream(); + stream.Volume = volume; + } + + public static void StopStream() + { + if (stream!=null) SoundManager.StopStream(); } public static void Dispose() diff --git a/Subsurface/Subsurface.csproj b/Subsurface/Subsurface.csproj index 4219730aa..35706e91c 100644 --- a/Subsurface/Subsurface.csproj +++ b/Subsurface/Subsurface.csproj @@ -133,6 +133,7 @@ + @@ -218,16 +219,28 @@ PreserveNewest - + + PreserveNewest + + PreserveNewest PreserveNewest - + PreserveNewest - + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + PreserveNewest @@ -271,6 +284,12 @@ PreserveNewest Designer + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -357,6 +376,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -400,10 +425,10 @@ PreserveNewest - + PreserveNewest - + PreserveNewest @@ -565,6 +590,15 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -577,6 +611,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -642,6 +682,7 @@ + diff --git a/Subsurface/Subsurface.csproj.user b/Subsurface/Subsurface.csproj.user index 693505ea4..505c3a0bf 100644 --- a/Subsurface/Subsurface.csproj.user +++ b/Subsurface/Subsurface.csproj.user @@ -9,6 +9,6 @@ en-US false - ShowAllFiles + ProjectFiles \ No newline at end of file diff --git a/Subsurface/ToolBox.cs b/Subsurface/ToolBox.cs index 245368bd8..57b9bdd3d 100644 --- a/Subsurface/ToolBox.cs +++ b/Subsurface/ToolBox.cs @@ -128,50 +128,50 @@ namespace Subsurface } - public static void CompressStringToFile(string fileName, string value) - { - // A. - // Write string to temporary file. - string temp = Path.GetTempFileName(); - File.WriteAllText(temp, value); + //public static void CompressStringToFile(string fileName, string value) + //{ + // // A. + // // Write string to temporary file. + // string temp = Path.GetTempFileName(); + // File.WriteAllText(temp, value); - // B. - // Read file into byte array buffer. - byte[] b; - using (FileStream f = new FileStream(temp, FileMode.Open)) - { - b = new byte[f.Length]; - f.Read(b, 0, (int)f.Length); - } + // // B. + // // Read file into byte array buffer. + // byte[] b; + // using (FileStream f = new FileStream(temp, FileMode.Open)) + // { + // b = new byte[f.Length]; + // f.Read(b, 0, (int)f.Length); + // } - // C. - // Use GZipStream to write compressed bytes to target file. - using (FileStream f2 = new FileStream(fileName, FileMode.Create)) - using (GZipStream gz = new GZipStream(f2, CompressionMode.Compress, false)) - { - gz.Write(b, 0, b.Length); - } - } + // // C. + // // Use GZipStream to write compressed bytes to target file. + // using (FileStream f2 = new FileStream(fileName, FileMode.Create)) + // using (GZipStream gz = new GZipStream(f2, CompressionMode.Compress, false)) + // { + // gz.Write(b, 0, b.Length); + // } + //} - public static Stream DecompressFiletoStream(string fileName) - { - if (!File.Exists(fileName)) - { - DebugConsole.ThrowError("File ''"+fileName+" doesn't exist!"); - return null; - } + //public static Stream DecompressFiletoStream(string fileName) + //{ + // if (!File.Exists(fileName)) + // { + // DebugConsole.ThrowError("File ''"+fileName+" doesn't exist!"); + // return null; + // } - using (FileStream originalFileStream = new FileStream(fileName, FileMode.Open)) - { - MemoryStream decompressedFileStream = new MemoryStream(); + // using (FileStream originalFileStream = new FileStream(fileName, FileMode.Open)) + // { + // MemoryStream decompressedFileStream = new MemoryStream(); - using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress)) - { - decompressionStream.CopyTo(decompressedFileStream); - return decompressedFileStream; - } - } - } + // using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress)) + // { + // decompressionStream.CopyTo(decompressedFileStream); + // return decompressedFileStream; + // } + // } + //} public static XDocument TryLoadXml(string filePath) { diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index 53ee92e2e..b61cebe5a 100644 Binary files a/Subsurface_Solution.v12.suo and b/Subsurface_Solution.v12.suo differ