Example #1
0
        public void EndRound(string endMessage, List <TraitorMissionResult> traitorResults = null, CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None)
        {
            if (Mission != null)
            {
                Mission.End();
            }
            GameAnalyticsManager.AddProgressionEvent(
                (Mission == null || Mission.Completed) ? GameAnalyticsSDK.Net.EGAProgressionStatus.Complete : GameAnalyticsSDK.Net.EGAProgressionStatus.Fail,
                GameMode.Preset.Identifier,
                Mission == null ? "None" : Mission.GetType().ToString());

#if CLIENT
            if (!(GameMode is TestGameMode) && Screen.Selected == GameMain.GameScreen && RoundSummary != null)
            {
                GUI.ClearMessages();
                GUIMessageBox.MessageBoxes.RemoveAll(mb => mb.UserData is RoundSummary);
                GUIFrame summaryFrame = RoundSummary.CreateSummaryFrame(this, endMessage, traitorResults, transitionType);
                GUIMessageBox.MessageBoxes.Add(summaryFrame);
                RoundSummary.ContinueButton.OnClicked = (_, __) => { GUIMessageBox.MessageBoxes.Remove(summaryFrame); return(true); };
            }

            if (GameMain.NetLobbyScreen != null)
            {
                GameMain.NetLobbyScreen.OnRoundEnded();
            }
            TabMenu.OnRoundEnded();
            GUIMessageBox.MessageBoxes.RemoveAll(mb => mb.UserData as string == "ConversationAction");
#endif
            SteamAchievementManager.OnRoundEnded(this);

            GameMode?.End(transitionType);
            EventManager?.EndRound();
            StatusEffect.StopAll();
            Mission   = null;
            IsRunning = false;
        }
        public SalvageMission(MissionPrefab prefab, Location[] locations)
            : base(prefab, locations)
        {
            containerTag = prefab.ConfigElement.GetAttributeString("containertag", "");

            if (prefab.ConfigElement.Attribute("itemname") != null)
            {
                DebugConsole.ThrowError("Error in SalvageMission - use item identifier instead of the name of the item.");
                string itemName = prefab.ConfigElement.GetAttributeString("itemname", "");
                itemPrefab = MapEntityPrefab.Find(itemName) as ItemPrefab;
                if (itemPrefab == null)
                {
                    DebugConsole.ThrowError("Error in SalvageMission: couldn't find an item prefab with the name " + itemName);
                }
            }
            else
            {
                string itemIdentifier = prefab.ConfigElement.GetAttributeString("itemidentifier", "");
                itemPrefab = MapEntityPrefab.Find(null, itemIdentifier) as ItemPrefab;
                if (itemPrefab == null)
                {
                    DebugConsole.ThrowError("Error in SalvageMission - couldn't find an item prefab with the identifier " + itemIdentifier);
                }
            }

            existingItemTag         = prefab.ConfigElement.GetAttributeString("existingitemtag", "");
            showMessageWhenPickedUp = prefab.ConfigElement.GetAttributeBool("showmessagewhenpickedup", false);

            string spawnPositionTypeStr = prefab.ConfigElement.GetAttributeString("spawntype", "");

            if (string.IsNullOrWhiteSpace(spawnPositionTypeStr) ||
                !Enum.TryParse(spawnPositionTypeStr, true, out spawnPositionType))
            {
                spawnPositionType = Level.PositionType.Cave | Level.PositionType.Ruin;
            }

            foreach (XElement element in prefab.ConfigElement.Elements())
            {
                switch (element.Name.ToString().ToLowerInvariant())
                {
                case "statuseffect":
                {
                    var newEffect = StatusEffect.Load(element, parentDebugName: prefab.Name);
                    if (newEffect == null)
                    {
                        continue;
                    }
                    statusEffects.Add(new List <StatusEffect> {
                            newEffect
                        });
                    break;
                }

                case "chooserandom":
                    statusEffects.Add(new List <StatusEffect>());
                    foreach (XElement subElement in element.Elements())
                    {
                        var newEffect = StatusEffect.Load(subElement, parentDebugName: prefab.Name);
                        if (newEffect == null)
                        {
                            continue;
                        }
                        statusEffects.Last().Add(newEffect);
                    }
                    break;
                }
            }
        }
Example #3
0
        public Attack(XElement element, string parentDebugName)
        {
            SourceElement = element;
            Deserialize();

            if (element.Attribute("damage") != null ||
                element.Attribute("bluntdamage") != null ||
                element.Attribute("burndamage") != null ||
                element.Attribute("bleedingdamage") != null)
            {
                DebugConsole.ThrowError("Error in Attack (" + parentDebugName + ") - Define damage as afflictions instead of using the damage attribute (e.g. <Affliction identifier=\"internaldamage\" strength=\"10\" />).");
            }

            DamageRange = element.GetAttributeFloat("damagerange", 0f);

            InitProjSpecific(element);

            foreach (XElement subElement in element.Elements())
            {
                switch (subElement.Name.ToString().ToLowerInvariant())
                {
                case "statuseffect":
                    if (statusEffects == null)
                    {
                        statusEffects = new List <StatusEffect>();
                    }
                    statusEffects.Add(StatusEffect.Load(subElement, parentDebugName));
                    break;

                case "affliction":
                    AfflictionPrefab afflictionPrefab;
                    if (subElement.Attribute("name") != null)
                    {
                        DebugConsole.ThrowError("Error in Attack (" + parentDebugName + ") - define afflictions using identifiers instead of names.");
                        string afflictionName = subElement.GetAttributeString("name", "").ToLowerInvariant();
                        afflictionPrefab = AfflictionPrefab.List.Find(ap => ap.Name.ToLowerInvariant() == afflictionName);
                        if (afflictionPrefab == null)
                        {
                            DebugConsole.ThrowError("Error in Attack (" + parentDebugName + ") - Affliction prefab \"" + afflictionName + "\" not found.");
                            continue;
                        }
                    }
                    else
                    {
                        string afflictionIdentifier = subElement.GetAttributeString("identifier", "").ToLowerInvariant();
                        afflictionPrefab = AfflictionPrefab.List.Find(ap => ap.Identifier.ToLowerInvariant() == afflictionIdentifier);
                        if (afflictionPrefab == null)
                        {
                            DebugConsole.ThrowError("Error in Attack (" + parentDebugName + ") - Affliction prefab \"" + afflictionIdentifier + "\" not found.");
                            continue;
                        }
                    }

                    float afflictionStrength = subElement.GetAttributeFloat(1.0f, "amount", "strength");
                    var   affliction         = afflictionPrefab.Instantiate(afflictionStrength);
                    affliction.ApplyProbability = subElement.GetAttributeFloat("probability", 1.0f);
                    Afflictions.Add(affliction);

                    break;

                case "conditional":
                    foreach (XAttribute attribute in subElement.Attributes())
                    {
                        Conditionals.Add(new PropertyConditional(attribute));
                    }
                    break;
                }
            }
        }
Example #4
0
        public Attack(XElement element)
        {
            try
            {
                DamageType = (DamageType)Enum.Parse(typeof(DamageType), element.GetAttributeString("damagetype", "None"), true);
            }
            catch
            {
                DamageType = DamageType.None;
            }

            damage          = element.GetAttributeFloat("damage", 0.0f);
            structureDamage = element.GetAttributeFloat("structuredamage", 0.0f);
            bleedingDamage  = element.GetAttributeFloat("bleedingdamage", 0.0f);
            Stun            = element.GetAttributeFloat("stun", 0.0f);

            SeverLimbsProbability = element.GetAttributeFloat("severlimbsprobability", 0.0f);

            Force       = element.GetAttributeFloat("force", 0.0f);
            TargetForce = element.GetAttributeFloat("targetforce", 0.0f);
            Torque      = element.GetAttributeFloat("torque", 0.0f);

            Range       = element.GetAttributeFloat("range", 0.0f);
            DamageRange = element.GetAttributeFloat("damagerange", Range);
            Duration    = element.GetAttributeFloat("duration", 0.0f);

            priority = element.GetAttributeFloat("priority", 1.0f);

            onlyHumans = element.GetAttributeBool("onlyhumans", false);

            InitProjSpecific(element);

            string limbIndicesStr = element.GetAttributeString("applyforceonlimbs", "");

            if (!string.IsNullOrWhiteSpace(limbIndicesStr))
            {
                ApplyForceOnLimbs = new List <int>();
                foreach (string limbIndexStr in limbIndicesStr.Split(','))
                {
                    int limbIndex;
                    if (int.TryParse(limbIndexStr, out limbIndex))
                    {
                        ApplyForceOnLimbs.Add(limbIndex);
                    }
                }
            }

            foreach (XElement subElement in element.Elements())
            {
                switch (subElement.Name.ToString().ToLowerInvariant())
                {
                case "statuseffect":
                    if (statusEffects == null)
                    {
                        statusEffects = new List <StatusEffect>();
                    }
                    statusEffects.Add(StatusEffect.Load(subElement));
                    break;
                }
            }
        }
Example #5
0
        public static RelatedItem Load(XElement element, bool returnEmpty, string parentDebugName)
        {
            string[] identifiers;
            if (element.Attribute("name") != null)
            {
                //backwards compatibility + a console warning
                DebugConsole.ThrowError("Error in RelatedItem config (" + (string.IsNullOrEmpty(parentDebugName) ? element.ToString() : parentDebugName) + ") - use item tags or identifiers instead of names.");
                string[] itemNames = element.GetAttributeStringArray("name", new string[0]);
                //attempt to convert to identifiers and tags
                List <string> convertedIdentifiers = new List <string>();
                foreach (string itemName in itemNames)
                {
                    var matchingItem = ItemPrefab.Prefabs.Find(me => me.Name == itemName);
                    if (matchingItem != null)
                    {
                        convertedIdentifiers.Add(matchingItem.Identifier);
                    }
                    else
                    {
                        //no matching item found, this must be a tag
                        convertedIdentifiers.Add(itemName);
                    }
                }
                identifiers = convertedIdentifiers.ToArray();
            }
            else
            {
                identifiers = element.GetAttributeStringArray("items", null, convertToLowerInvariant: true) ?? element.GetAttributeStringArray("item", null, convertToLowerInvariant: true);
                if (identifiers == null)
                {
                    identifiers = element.GetAttributeStringArray("identifiers", null, convertToLowerInvariant: true) ?? element.GetAttributeStringArray("tags", null, convertToLowerInvariant: true);
                    if (identifiers == null)
                    {
                        identifiers = element.GetAttributeStringArray("identifier", null, convertToLowerInvariant: true) ?? element.GetAttributeStringArray("tag", new string[0], convertToLowerInvariant: true);
                    }
                }
            }

            string[] excludedIdentifiers = element.GetAttributeStringArray("excludeditems", null, convertToLowerInvariant: true) ?? element.GetAttributeStringArray("excludeditem", null, convertToLowerInvariant: true);
            if (excludedIdentifiers == null)
            {
                excludedIdentifiers = element.GetAttributeStringArray("excludedidentifiers", null, convertToLowerInvariant: true) ?? element.GetAttributeStringArray("excludedtags", null, convertToLowerInvariant: true);
                if (excludedIdentifiers == null)
                {
                    excludedIdentifiers = element.GetAttributeStringArray("excludedidentifier", null, convertToLowerInvariant: true) ?? element.GetAttributeStringArray("excludedtag", new string[0], convertToLowerInvariant: true);
                }
            }

            if (identifiers.Length == 0 && excludedIdentifiers.Length == 0 && !returnEmpty)
            {
                return(null);
            }

            RelatedItem ri      = new RelatedItem(identifiers, excludedIdentifiers);
            string      typeStr = element.GetAttributeString("type", "");

            if (string.IsNullOrEmpty(typeStr))
            {
                switch (element.Name.ToString().ToLowerInvariant())
                {
                case "containable":
                    typeStr = "Contained";
                    break;

                case "suitablefertilizer":
                case "suitableseed":
                    typeStr = "None";
                    break;
                }
            }
            if (!Enum.TryParse(typeStr, true, out ri.type))
            {
                DebugConsole.ThrowError("Error in RelatedItem config (" + parentDebugName + ") - \"" + typeStr + "\" is not a valid relation type.");
                return(null);
            }

            ri.MsgTag = element.GetAttributeString("msg", "");
            string msg = TextManager.Get(ri.MsgTag, true);

            if (msg == null)
            {
                ri.Msg = ri.MsgTag;
            }
            else
            {
#if CLIENT
                foreach (InputType inputType in Enum.GetValues(typeof(InputType)))
                {
                    msg = msg.Replace("[" + inputType.ToString().ToLowerInvariant() + "]", GameMain.Config.KeyBindText(inputType));
                }
                ri.Msg = msg;
#endif
            }

            foreach (XElement subElement in element.Elements())
            {
                if (!subElement.Name.ToString().Equals("statuseffect", StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }
                ri.statusEffects.Add(StatusEffect.Load(subElement, parentDebugName));
            }

            ri.IsOptional     = element.GetAttributeBool("optional", false);
            ri.IgnoreInEditor = element.GetAttributeBool("ignoreineditor", false);
            ri.MatchOnEmpty   = element.GetAttributeBool("matchonempty", false);
            return(ri);
        }
Example #6
0
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        public override void Update(double deltaTime)
        {
#if DEBUG
            if (GameMain.GameSession != null && GameMain.GameSession.Level != null && GameMain.GameSession.Submarine != null &&
                !DebugConsole.IsOpen)
            {
                var closestSub = Submarine.FindClosest(cam.WorldViewCenter);
                if (closestSub == null)
                {
                    closestSub = GameMain.GameSession.Submarine;
                }

                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;
                }

                if (targetMovement != Vector2.Zero)
                {
                    closestSub.ApplyForce(targetMovement * closestSub.SubBody.Body.Mass * 100.0f);
                }
            }
#endif

            foreach (MapEntity e in MapEntity.mapEntityList)
            {
                e.IsHighlighted = false;
            }

            if (GameMain.GameSession != null)
            {
                GameMain.GameSession.Update((float)deltaTime);
            }

            if (Level.Loaded != null)
            {
                Level.Loaded.Update((float)deltaTime);
            }

            if (Character.Controlled != null && Character.Controlled.SelectedConstruction != null)
            {
                if (Character.Controlled.SelectedConstruction == Character.Controlled.ClosestItem)
                {
                    Character.Controlled.SelectedConstruction.UpdateHUD(cam, Character.Controlled);
                }
            }
            Character.UpdateAll(cam, (float)deltaTime);

            BackgroundCreatureManager.Update(cam, (float)deltaTime);

            GameMain.ParticleManager.Update((float)deltaTime);

            StatusEffect.UpdateAll((float)deltaTime);

            if (Character.Controlled != null && Lights.LightManager.ViewTarget != null)
            {
                cam.TargetPos = Lights.LightManager.ViewTarget.WorldPosition;
            }

            GameMain.LightManager.Update((float)deltaTime);
            cam.MoveCamera((float)deltaTime);

            foreach (Submarine sub in Submarine.Loaded)
            {
                sub.SetPrevTransform(sub.Position);
            }

            foreach (PhysicsBody pb in PhysicsBody.list)
            {
                pb.SetPrevTransform(pb.SimPosition, pb.Rotation);
            }

            MapEntity.UpdateAll(cam, (float)deltaTime);

            Character.UpdateAnimAll((float)deltaTime);

            Ragdoll.UpdateAll(cam, (float)deltaTime);

            foreach (Submarine sub in Submarine.Loaded)
            {
                sub.Update((float)deltaTime);
            }

            GameMain.World.Step((float)deltaTime);

            if (!PlayerInput.LeftButtonHeld())
            {
                Inventory.draggingSlot = null;
                Inventory.draggingItem = null;
            }
        }
Example #7
0
            public Effect(XElement element, string parentDebugName)
            {
                MinStrength = element.GetAttributeFloat("minstrength", 0);
                MaxStrength = element.GetAttributeFloat("maxstrength", 0);

                MultiplyByMaxVitality = element.GetAttributeBool("multiplybymaxvitality", false);

                MinVitalityDecrease = element.GetAttributeFloat("minvitalitydecrease", 0.0f);
                MaxVitalityDecrease = element.GetAttributeFloat("maxvitalitydecrease", 0.0f);
                MaxVitalityDecrease = Math.Max(MinVitalityDecrease, MaxVitalityDecrease);

                MinScreenDistortStrength = element.GetAttributeFloat("minscreendistort", 0.0f);
                MaxScreenDistortStrength = element.GetAttributeFloat("maxscreendistort", 0.0f);
                MaxScreenDistortStrength = Math.Max(MinScreenDistortStrength, MaxScreenDistortStrength);

                MinRadialDistortStrength = element.GetAttributeFloat("minradialdistort", 0.0f);
                MaxRadialDistortStrength = element.GetAttributeFloat("maxradialdistort", 0.0f);
                MaxRadialDistortStrength = Math.Max(MinRadialDistortStrength, MaxRadialDistortStrength);

                MinChromaticAberrationStrength = element.GetAttributeFloat("minchromaticaberration", 0.0f);
                MaxChromaticAberrationStrength = element.GetAttributeFloat("maxchromaticaberration", 0.0f);
                MaxChromaticAberrationStrength = Math.Max(MinChromaticAberrationStrength, MaxChromaticAberrationStrength);

                MinGrainStrength = element.GetAttributeFloat(nameof(MinGrainStrength).ToLower(), 0.0f);
                MaxGrainStrength = element.GetAttributeFloat(nameof(MaxGrainStrength).ToLower(), 0.0f);
                MaxGrainStrength = Math.Max(MinGrainStrength, MaxGrainStrength);

                MinScreenBlurStrength = element.GetAttributeFloat("minscreenblur", 0.0f);
                MaxScreenBlurStrength = element.GetAttributeFloat("maxscreenblur", 0.0f);
                MaxScreenBlurStrength = Math.Max(MinScreenBlurStrength, MaxScreenBlurStrength);

                MinSkillMultiplier = element.GetAttributeFloat("minskillmultiplier", 1.0f);
                MaxSkillMultiplier = element.GetAttributeFloat("maxskillmultiplier", 1.0f);

                ResistanceFor = element.GetAttributeString("resistancefor", "");
                MinResistance = element.GetAttributeFloat("minresistance", 0.0f);
                MaxResistance = element.GetAttributeFloat("maxresistance", 0.0f);
                MaxResistance = Math.Max(MinResistance, MaxResistance);

                MinSpeedMultiplier = element.GetAttributeFloat("minspeedmultiplier", 1.0f);
                MaxSpeedMultiplier = element.GetAttributeFloat("maxspeedmultiplier", 1.0f);
                MaxSpeedMultiplier = Math.Max(MinSpeedMultiplier, MaxSpeedMultiplier);

                MinBuffMultiplier = element.GetAttributeFloat("minbuffmultiplier", 1.0f);
                MaxBuffMultiplier = element.GetAttributeFloat("maxbuffmultiplier", 1.0f);
                MaxBuffMultiplier = Math.Max(MinBuffMultiplier, MaxBuffMultiplier);

                DialogFlag = element.GetAttributeString("dialogflag", "");

                StrengthChange = element.GetAttributeFloat("strengthchange", 0.0f);

                foreach (XElement subElement in element.Elements())
                {
                    switch (subElement.Name.ToString().ToLowerInvariant())
                    {
                    case "statuseffect":
                        StatusEffects.Add(StatusEffect.Load(subElement, parentDebugName));
                        break;
                    }
                }
            }
Example #8
0
        public LevelTrigger(XElement element, Vector2 position, float rotation, float scale = 1.0f, string parentDebugName = "")
        {
            TriggererPosition = new Dictionary <Entity, Vector2>();

            worldPosition = position;
            if (element.Attributes("radius").Any() || element.Attributes("width").Any() || element.Attributes("height").Any())
            {
                physicsBody = new PhysicsBody(element, scale)
                {
                    CollisionCategories = Physics.CollisionLevel,
                    CollidesWith        = Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionProjectile | Physics.CollisionWall
                };
                physicsBody.FarseerBody.OnCollision  += PhysicsBody_OnCollision;
                physicsBody.FarseerBody.OnSeparation += PhysicsBody_OnSeparation;
                physicsBody.FarseerBody.IsSensor      = true;
                physicsBody.FarseerBody.IsStatic      = true;
                physicsBody.FarseerBody.IsKinematic   = true;

                ColliderRadius = ConvertUnits.ToDisplayUnits(Math.Max(Math.Max(PhysicsBody.radius, PhysicsBody.width / 2.0f), PhysicsBody.height / 2.0f));

                physicsBody.SetTransform(ConvertUnits.ToSimUnits(position), rotation);
            }

            cameraShake = element.GetAttributeFloat("camerashake", 0.0f);

            stayTriggeredDelay       = element.GetAttributeFloat("staytriggereddelay", 0.0f);
            randomTriggerInterval    = element.GetAttributeFloat("randomtriggerinterval", 0.0f);
            randomTriggerProbability = element.GetAttributeFloat("randomtriggerprobability", 0.0f);

            UseNetworkSyncing = element.GetAttributeBool("networksyncing", false);

            unrotatedForce =
                element.Attribute("force") != null && element.Attribute("force").Value.Contains(',') ?
                element.GetAttributeVector2("force", Vector2.Zero) :
                new Vector2(element.GetAttributeFloat("force", 0.0f), 0.0f);

            ForceFluctuationInterval = element.GetAttributeFloat("forcefluctuationinterval", 0.01f);
            ForceFluctuationStrength = Math.Max(element.GetAttributeFloat("forcefluctuationstrength", 0.0f), 0.0f);
            ForceFalloff             = element.GetAttributeBool("forcefalloff", true);

            ForceVelocityLimit = ConvertUnits.ToSimUnits(element.GetAttributeFloat("forcevelocitylimit", float.MaxValue));
            string forceModeStr = element.GetAttributeString("forcemode", "Force");

            if (!Enum.TryParse(forceModeStr, out forceMode))
            {
                DebugConsole.ThrowError("Error in LevelTrigger config: \"" + forceModeStr + "\" is not a valid force mode.");
            }
            CalculateDirectionalForce();

            string triggeredByStr = element.GetAttributeString("triggeredby", "Character");

            if (!Enum.TryParse(triggeredByStr, out triggeredBy))
            {
                DebugConsole.ThrowError("Error in LevelTrigger config: \"" + triggeredByStr + "\" is not a valid triggerer type.");
            }
            UpdateCollisionCategories();
            triggerOthersDistance = element.GetAttributeFloat("triggerothersdistance", 0.0f);

            var tagsArray = element.GetAttributeStringArray("tags", new string[0]);

            foreach (string tag in tagsArray)
            {
                tags.Add(tag.ToLower());
            }

            if (triggeredBy.HasFlag(TriggererType.OtherTrigger))
            {
                var otherTagsArray = element.GetAttributeStringArray("allowedothertriggertags", new string[0]);
                foreach (string tag in otherTagsArray)
                {
                    allowedOtherTriggerTags.Add(tag.ToLower());
                }
            }

            foreach (XElement subElement in element.Elements())
            {
                switch (subElement.Name.ToString().ToLowerInvariant())
                {
                case "statuseffect":
                    statusEffects.Add(StatusEffect.Load(subElement, string.IsNullOrEmpty(parentDebugName) ? "LevelTrigger" : "LevelTrigger in " + parentDebugName));
                    break;

                case "attack":
                case "damage":
                    var attack = new Attack(subElement, string.IsNullOrEmpty(parentDebugName) ? "LevelTrigger" : "LevelTrigger in " + parentDebugName);
                    var multipliedAfflictions = attack.GetMultipliedAfflictions((float)Timing.Step);
                    attack.Afflictions.Clear();
                    foreach (Affliction affliction in multipliedAfflictions)
                    {
                        attack.Afflictions.Add(affliction, null);
                    }
                    attacks.Add(attack);
                    break;
                }
            }

            forceFluctuationTimer = Rand.Range(0.0f, ForceFluctuationInterval);
            randomTriggerTimer    = Rand.Range(0.0f, randomTriggerInterval);
        }
Example #9
0
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        public override void Update(double deltaTime)
        {
#if DEBUG && CLIENT
            if (GameMain.GameSession != null && GameMain.GameSession.Level != null && GameMain.GameSession.Submarine != null &&
                !DebugConsole.IsOpen && GUI.KeyboardDispatcher.Subscriber == null)
            {
                var closestSub = Submarine.FindClosest(cam.WorldViewCenter);
                if (closestSub == null)
                {
                    closestSub = GameMain.GameSession.Submarine;
                }

                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;
                }

                if (targetMovement != Vector2.Zero)
                {
                    closestSub.ApplyForce(targetMovement * closestSub.SubBody.Body.Mass * 100.0f);
                }
            }
#endif
            foreach (PhysicsBody body in PhysicsBody.List)
            {
                body.Update((float)deltaTime);
            }
            foreach (MapEntity e in MapEntity.mapEntityList)
            {
                e.IsHighlighted = false;
            }

            if (GameMain.GameSession != null)
            {
                GameMain.GameSession.Update((float)deltaTime);
            }
#if CLIENT
            var sw = new System.Diagnostics.Stopwatch();
            sw.Start();

            GameMain.ParticleManager.Update((float)deltaTime);

            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("ParticleUpdate", sw.ElapsedTicks);
            sw.Restart();

            GameMain.LightManager.Update((float)deltaTime);

            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("LightUpdate", sw.ElapsedTicks);
            sw.Restart();
#endif

            if (Level.Loaded != null)
            {
                Level.Loaded.Update((float)deltaTime, cam);
            }

#if CLIENT
            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("LevelUpdate", sw.ElapsedTicks);

            if (Character.Controlled != null && Character.Controlled.SelectedConstruction != null && Character.Controlled.CanInteractWith(Character.Controlled.SelectedConstruction))
            {
                Character.Controlled.SelectedConstruction.UpdateHUD(cam, Character.Controlled, (float)deltaTime);
            }
            sw.Restart();
#endif

            Character.UpdateAll((float)deltaTime, cam);

#if CLIENT
            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("CharacterUpdate", sw.ElapsedTicks);
            sw.Restart();
#endif

            StatusEffect.UpdateAll((float)deltaTime);

#if CLIENT
            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("StatusEffectUpdate", sw.ElapsedTicks);
            sw.Restart();

            if (Character.Controlled != null &&
                Lights.LightManager.ViewTarget != null)
            {
                Vector2 targetPos = Lights.LightManager.ViewTarget.DrawPosition;
                if (Lights.LightManager.ViewTarget == Character.Controlled && CharacterHealth.OpenHealthWindow != null)
                {
                    Vector2 screenTargetPos = CharacterHealth.OpenHealthWindow.Alignment == Alignment.Left ?
                                              new Vector2(GameMain.GraphicsWidth * 0.75f, GameMain.GraphicsHeight * 0.5f) :
                                              new Vector2(GameMain.GraphicsWidth * 0.25f, GameMain.GraphicsHeight * 0.5f);
                    Vector2 screenOffset = screenTargetPos - new Vector2(GameMain.GraphicsWidth / 2, GameMain.GraphicsHeight / 2);
                    screenOffset.Y = -screenOffset.Y;
                    targetPos     -= screenOffset / cam.Zoom;
                }
                cam.TargetPos = targetPos;
            }
#endif

            cam.MoveCamera((float)deltaTime);

            foreach (Submarine sub in Submarine.Loaded)
            {
                sub.SetPrevTransform(sub.Position);
            }

            foreach (PhysicsBody pb in PhysicsBody.List)
            {
                pb.SetPrevTransform(pb.SimPosition, pb.Rotation);
            }

            MapEntity.UpdateAll((float)deltaTime, cam);
#if CLIENT
            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("MapEntityUpdate", sw.ElapsedTicks);
            sw.Restart();
#endif
            Character.UpdateAnimAll((float)deltaTime);

            Ragdoll.UpdateAll((float)deltaTime, cam);

#if CLIENT
            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("AnimUpdate", sw.ElapsedTicks);
            sw.Restart();
#endif

            foreach (Submarine sub in Submarine.Loaded)
            {
                sub.Update((float)deltaTime);
            }

#if CLIENT
            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("SubmarineUpdate", sw.ElapsedTicks);
            sw.Restart();
#endif

            GameMain.World.Step((float)deltaTime);

#if CLIENT
            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("Physics", sw.ElapsedTicks);
#endif

#if CLIENT
            if (!PlayerInput.LeftButtonHeld())
            {
                Inventory.draggingSlot = null;
                Inventory.draggingItem = null;
            }
#endif
        }
Example #10
0
        public void EndRound(string endMessage, List <TraitorMissionResult> traitorResults = null, CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None)
        {
            RoundEnding = true;

            try
            {
                IEnumerable <Character> crewCharacters = GetSessionCrewCharacters();

                foreach (Mission mission in missions)
                {
                    mission.End();
                }

                foreach (Character character in crewCharacters)
                {
                    character.CheckTalents(AbilityEffectType.OnRoundEnd);
                }

                if (missions.Any())
                {
                    if (missions.Any(m => m.Completed))
                    {
                        foreach (Character character in crewCharacters)
                        {
                            character.CheckTalents(AbilityEffectType.OnAnyMissionCompleted);
                        }
                    }

                    if (missions.All(m => m.Completed))
                    {
                        foreach (Character character in crewCharacters)
                        {
                            character.CheckTalents(AbilityEffectType.OnAllMissionsCompleted);
                        }
                    }
                }

#if CLIENT
                if (GUI.PauseMenuOpen)
                {
                    GUI.TogglePauseMenu();
                }
                GUI.PreventPauseMenuToggle = true;

                if (!(GameMode is TestGameMode) && Screen.Selected == GameMain.GameScreen && RoundSummary != null)
                {
                    GUI.ClearMessages();
                    GUIMessageBox.MessageBoxes.RemoveAll(mb => mb.UserData is RoundSummary);
                    GUIFrame summaryFrame = RoundSummary.CreateSummaryFrame(this, endMessage, traitorResults, transitionType);
                    GUIMessageBox.MessageBoxes.Add(summaryFrame);
                    RoundSummary.ContinueButton.OnClicked = (_, __) => { GUIMessageBox.MessageBoxes.Remove(summaryFrame); return(true); };
                }

                if (GameMain.NetLobbyScreen != null)
                {
                    GameMain.NetLobbyScreen.OnRoundEnded();
                }
                TabMenu.OnRoundEnded();
                GUIMessageBox.MessageBoxes.RemoveAll(mb => mb.UserData as string == "ConversationAction" || ReadyCheck.IsReadyCheck(mb));
#endif
                SteamAchievementManager.OnRoundEnded(this);

                GameMode?.End(transitionType);
                EventManager?.EndRound();
                StatusEffect.StopAll();
                missions.Clear();
                IsRunning = false;

#if CLIENT
                HintManager.OnRoundEnded();
#endif
            }
            finally
            {
                RoundEnding = false;
            }
        }
Example #11
0
        private void InitializeLevel(Level level)
        {
            //make sure no status effects have been carried on from the next round
            //(they should be stopped in EndRound, this is a safeguard against cases where the round is ended ungracefully)
            StatusEffect.StopAll();

#if CLIENT
#if !DEBUG
            GameMain.LightManager.LosEnabled = GameMain.Client == null || GameMain.Client.CharacterInfo != null;
#endif
            if (GameMain.LightManager.LosEnabled)
            {
                GameMain.LightManager.LosAlpha = 1f;
            }
            if (GameMain.Client == null)
            {
                GameMain.LightManager.LosMode = GameMain.Config.LosMode;
            }
#endif
            LevelData = level?.LevelData;
            Level     = level;

            PlaceSubAtStart(Level);

            foreach (var sub in Submarine.Loaded)
            {
                if (sub.Info.IsOutpost)
                {
                    sub.DisableObstructedWayPoints();
                }
            }

            Entity.Spawner = new EntitySpawner();

            missions.Clear();
            GameMode.AddExtraMissions(LevelData);
            missions.AddRange(GameMode.Missions);
            GameMode.Start();
            foreach (Mission mission in missions)
            {
                int prevEntityCount = Entity.GetEntities().Count();
                mission.Start(Level.Loaded);
                if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient && Entity.GetEntities().Count() != prevEntityCount)
                {
                    DebugConsole.ThrowError(
                        $"Entity count has changed after starting a mission ({mission.Prefab.Identifier}) as a client. " +
                        "The clients should not instantiate entities themselves when starting the mission," +
                        " but instead the server should inform the client of the spawned entities using Mission.ServerWriteInitial.");
                }
            }

            EventManager?.StartRound(Level.Loaded);
            SteamAchievementManager.OnStartRound();

            if (GameMode != null)
            {
                GameMode.ShowStartMessage();

                if (GameMain.NetworkMember == null)
                {
                    //only place items and corpses here in single player
                    //the server does this after loading the respawn shuttle
                    Level?.SpawnNPCs();
                    Level?.SpawnCorpses();
                    Level?.PrepareBeaconStation();
                    AutoItemPlacer.PlaceIfNeeded();
                }
                if (GameMode is MultiPlayerCampaign mpCampaign)
                {
                    mpCampaign.UpgradeManager.ApplyUpgrades();
                    mpCampaign.UpgradeManager.SanityCheckUpgrades(Submarine);
                }
                if (GameMode is CampaignMode)
                {
                    Submarine.WarmStartPower();
                }
            }

            GameMain.Config.RecentlyEncounteredCreatures.Clear();

            GameMain.GameScreen.Cam.Position = Character.Controlled?.WorldPosition ?? Submarine.MainSub.WorldPosition;
            RoundStartTime = Timing.TotalTime;
            GameMain.ResetFrameTime();
            IsRunning = true;
        }
Example #12
0
        public Attack(XElement element, string parentDebugName)
        {
            Deserialize(element);

            if (element.Attribute("damage") != null ||
                element.Attribute("bluntdamage") != null ||
                element.Attribute("burndamage") != null ||
                element.Attribute("bleedingdamage") != null)
            {
                DebugConsole.ThrowError("Error in Attack (" + parentDebugName + ") - Define damage as afflictions instead of using the damage attribute (e.g. <Affliction identifier=\"internaldamage\" strength=\"10\" />).");
            }

            //if level wall damage is not defined, default to the structure damage
            if (element.Attribute("LevelWallDamage") == null &&
                element.Attribute("levelwalldamage") == null)
            {
                LevelWallDamage = StructureDamage;
            }

            InitProjSpecific(element);

            foreach (XElement subElement in element.Elements())
            {
                switch (subElement.Name.ToString().ToLowerInvariant())
                {
                case "statuseffect":
                    statusEffects.Add(StatusEffect.Load(subElement, parentDebugName));
                    break;

                case "affliction":
                    AfflictionPrefab afflictionPrefab;
                    if (subElement.Attribute("name") != null)
                    {
                        DebugConsole.ThrowError("Error in Attack (" + parentDebugName + ") - define afflictions using identifiers instead of names.");
                        string afflictionName = subElement.GetAttributeString("name", "").ToLowerInvariant();
                        afflictionPrefab = AfflictionPrefab.List.FirstOrDefault(ap => ap.Name.Equals(afflictionName, System.StringComparison.OrdinalIgnoreCase));
                        if (afflictionPrefab == null)
                        {
                            DebugConsole.ThrowError("Error in Attack (" + parentDebugName + ") - Affliction prefab \"" + afflictionName + "\" not found.");
                            continue;
                        }
                    }
                    else
                    {
                        string afflictionIdentifier = subElement.GetAttributeString("identifier", "").ToLowerInvariant();
                        afflictionPrefab = AfflictionPrefab.List.FirstOrDefault(ap => ap.Identifier.Equals(afflictionIdentifier, System.StringComparison.OrdinalIgnoreCase));
                        if (afflictionPrefab == null)
                        {
                            DebugConsole.ThrowError("Error in Attack (" + parentDebugName + ") - Affliction prefab \"" + afflictionIdentifier + "\" not found.");
                            continue;
                        }
                    }
                    break;

                case "conditional":
                    foreach (XAttribute attribute in subElement.Attributes())
                    {
                        if (PropertyConditional.IsValid(attribute))
                        {
                            Conditionals.Add(new PropertyConditional(attribute));
                        }
                    }
                    break;
                }
            }
        }
Example #13
0
        public void StartRound(Level level, bool mirrorLevel = false)
        {
            //make sure no status effects have been carried on from the next round
            //(they should be stopped in EndRound, this is a safeguard against cases where the round is ended ungracefully)
            StatusEffect.StopAll();

#if CLIENT
            GameMain.LightManager.LosEnabled = GameMain.Client == null || GameMain.Client.CharacterInfo != null;
            if (GameMain.Client == null)
            {
                GameMain.LightManager.LosMode = GameMain.Config.LosMode;
            }
#endif
            this.Level = level;

            if (SubmarineInfo == null)
            {
                DebugConsole.ThrowError("Couldn't start game session, submarine not selected.");
                return;
            }

            if (SubmarineInfo.IsFileCorrupted)
            {
                DebugConsole.ThrowError("Couldn't start game session, submarine file corrupted.");
                return;
            }

            Submarine.Unload();
            Submarine         = Submarine.MainSub = new Submarine(SubmarineInfo);
            Submarine.MainSub = Submarine;
            if (GameMode.Mission != null && GameMode.Mission.TeamCount > 1 && Submarine.MainSubs[1] == null)
            {
                Submarine.MainSubs[1] = new Submarine(SubmarineInfo, true);
            }

            if (level != null)
            {
                level.Generate(mirrorLevel);
                if (level.StartOutpost != null)
                {
                    //start by placing the sub below the outpost
                    Rectangle outpostBorders = Level.Loaded.StartOutpost.GetDockedBorders();
                    Rectangle subBorders     = Submarine.GetDockedBorders();

                    Vector2 startOutpostSize = Vector2.Zero;
                    if (Level.Loaded.StartOutpost != null)
                    {
                        startOutpostSize = Level.Loaded.StartOutpost.Borders.Size.ToVector2();
                    }
                    Submarine.SetPosition(
                        Level.Loaded.StartOutpost.WorldPosition -
                        new Vector2(0.0f, outpostBorders.Height / 2 + subBorders.Height / 2));

                    //find the port that's the nearest to the outpost and dock if one is found
                    float       closestDistance = 0.0f;
                    DockingPort myPort = null, outPostPort = null;
                    foreach (DockingPort port in DockingPort.List)
                    {
                        if (port.IsHorizontal || port.Docked)
                        {
                            continue;
                        }
                        if (port.Item.Submarine == level.StartOutpost)
                        {
                            outPostPort = port;
                            continue;
                        }
                        if (port.Item.Submarine != Submarine)
                        {
                            continue;
                        }

                        //the submarine port has to be at the top of the sub
                        if (port.Item.WorldPosition.Y < Submarine.WorldPosition.Y)
                        {
                            continue;
                        }

                        float dist = Vector2.DistanceSquared(port.Item.WorldPosition, level.StartOutpost.WorldPosition);
                        if (myPort == null || dist < closestDistance || (port.MainDockingPort && !myPort.MainDockingPort))
                        {
                            myPort          = port;
                            closestDistance = dist;
                        }
                    }

                    if (myPort != null && outPostPort != null)
                    {
                        Vector2 portDiff = myPort.Item.WorldPosition - Submarine.WorldPosition;
                        Submarine.SetPosition((outPostPort.Item.WorldPosition - portDiff) - Vector2.UnitY * outPostPort.DockedDistance);
                        myPort.Dock(outPostPort);
                        myPort.Lock(true);
                    }
                }
                else
                {
                    Submarine.SetPosition(Submarine.FindSpawnPos(level.StartPosition));
                }
            }

            foreach (var sub in Submarine.Loaded)
            {
                if (sub.Info.IsOutpost)
                {
                    sub.DisableObstructedWayPoints();
                }
            }

            Entity.Spawner = new EntitySpawner();

            if (GameMode.Mission != null)
            {
                Mission = GameMode.Mission;
            }
            if (GameMode != null)
            {
                GameMode.Start();
            }
            if (GameMode.Mission != null)
            {
                int prevEntityCount = Entity.GetEntityList().Count;
                Mission.Start(Level.Loaded);
                if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient && Entity.GetEntityList().Count != prevEntityCount)
                {
                    DebugConsole.ThrowError(
                        "Entity count has changed after starting a mission as a client. " +
                        "The clients should not instantiate entities themselves when starting the mission," +
                        " but instead the server should inform the client of the spawned entities using Mission.ServerWriteInitial.");
                }
            }

            EventManager?.StartRound(level);
            SteamAchievementManager.OnStartRound();

            if (GameMode != null)
            {
                GameMode.ShowStartMessage();

                if (GameMain.NetworkMember == null)
                {
                    //only place items and corpses here in single player
                    //the server does this after loading the respawn shuttle
                    Level?.SpawnCorpses();
                    AutoItemPlacer.PlaceIfNeeded(GameMode);
                }
                if (GameMode is MultiPlayerCampaign mpCampaign && GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
                {
                    mpCampaign.CargoManager.CreateItems();
                }
            }

            GameAnalyticsManager.AddDesignEvent("Submarine:" + Submarine.Info.Name);
            GameAnalyticsManager.AddDesignEvent("Level", ToolBox.StringToInt(level?.Seed ?? "[NO_LEVEL]"));
            GameAnalyticsManager.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
                                                     GameMode.Preset.Identifier, (Mission == null ? "None" : Mission.GetType().ToString()));

#if CLIENT
            if (GameMode is SinglePlayerCampaign)
            {
                SteamAchievementManager.OnBiomeDiscovered(level.Biome);
            }
            if (!(GameMode is SubTestMode))
            {
                RoundSummary = new RoundSummary(this);
            }

            GameMain.GameScreen.ColorFade(Color.Black, Color.TransparentBlack, 5.0f);

            if (!(GameMode is TutorialMode) && !(GameMode is SubTestMode))
            {
                GUI.AddMessage("", Color.Transparent, 3.0f, playSound: false);
                GUI.AddMessage(level.Biome.DisplayName, Color.Lerp(Color.CadetBlue, Color.DarkRed, level.Difficulty / 100.0f), 5.0f, playSound: false);
                GUI.AddMessage(TextManager.AddPunctuation(':', TextManager.Get("Destination"), EndLocation.Name), Color.CadetBlue, playSound: false);
                GUI.AddMessage(TextManager.AddPunctuation(':', TextManager.Get("Mission"), (Mission == null ? TextManager.Get("None") : Mission.Name)), Color.CadetBlue, playSound: false);
            }
#endif

            RoundStartTime = Timing.TotalTime;
            GameMain.ResetFrameTime();
        }
Example #14
0
        protected override void StartMissionSpecific(Level level)
        {
            if (items.Any())
            {
#if DEBUG
                throw new Exception($"items.Count > 0 ({items.Count})");
#else
                DebugConsole.AddWarning("Item list was not empty at the start of a nest mission. The mission instance may not have been ended correctly on previous rounds.");
                items.Clear();
#endif
            }

            if (!IsClient)
            {
                //ruin/cave/wreck items are allowed to spawn close to the sub
                float minDistance = spawnPositionType == Level.PositionType.Ruin || spawnPositionType == Level.PositionType.Cave || spawnPositionType == Level.PositionType.Wreck ?
                                    0.0f : Level.Loaded.Size.X * 0.3f;

                nestPosition = Level.Loaded.GetRandomItemPos(spawnPositionType, 100.0f, minDistance, 30.0f);
                List <GraphEdge> spawnEdges = new List <GraphEdge>();
                if (spawnPositionType == Level.PositionType.Cave)
                {
                    Level.Cave closestCave     = null;
                    float      closestCaveDist = float.PositiveInfinity;
                    foreach (var cave in Level.Loaded.Caves)
                    {
                        float dist = Vector2.DistanceSquared(nestPosition, cave.Area.Center.ToVector2());
                        if (dist < closestCaveDist)
                        {
                            closestCave     = cave;
                            closestCaveDist = dist;
                        }
                    }
                    if (closestCave != null)
                    {
                        closestCave.DisplayOnSonar = true;
                        SpawnNestObjects(level, closestCave);
#if SERVER
                        selectedCave = closestCave;
#endif
                    }
                    var nearbyCells = Level.Loaded.GetCells(nestPosition, searchDepth: 3);
                    if (nearbyCells.Any())
                    {
                        List <GraphEdge> validEdges = new List <GraphEdge>();
                        foreach (var edge in nearbyCells.SelectMany(c => c.Edges))
                        {
                            if (!edge.NextToCave || !edge.IsSolid)
                            {
                                continue;
                            }
                            if (Level.Loaded.ExtraWalls.Any(w => w.IsPointInside(edge.Center + edge.GetNormal(edge.Cell1 ?? edge.Cell2) * 100.0f)))
                            {
                                continue;
                            }
                            validEdges.Add(edge);
                        }

                        if (validEdges.Any())
                        {
                            spawnEdges.AddRange(validEdges.Where(e => MathUtils.LineSegmentToPointDistanceSquared(e.Point1.ToPoint(), e.Point2.ToPoint(), nestPosition.ToPoint()) < itemSpawnRadius * itemSpawnRadius).Distinct());
                        }
                        //no valid edges found close enough to the nest position, find the closest one
                        if (!spawnEdges.Any())
                        {
                            GraphEdge closestEdge    = null;
                            float     closestDistSqr = float.PositiveInfinity;
                            foreach (var edge in nearbyCells.SelectMany(c => c.Edges))
                            {
                                if (!edge.NextToCave || !edge.IsSolid)
                                {
                                    continue;
                                }
                                float dist = Vector2.DistanceSquared(edge.Center, nestPosition);
                                if (dist < closestDistSqr)
                                {
                                    closestEdge    = edge;
                                    closestDistSqr = dist;
                                }
                            }
                            if (closestEdge != null)
                            {
                                spawnEdges.Add(closestEdge);
                                itemSpawnRadius = Math.Max(itemSpawnRadius, (float)Math.Sqrt(closestDistSqr) * 1.5f);
                            }
                        }
                    }
                }

                foreach (XElement subElement in itemConfig.Elements())
                {
                    string itemIdentifier = subElement.GetAttributeString("identifier", "");
                    if (!(MapEntityPrefab.Find(null, itemIdentifier) is ItemPrefab itemPrefab))
                    {
                        DebugConsole.ThrowError("Couldn't spawn item for nest mission: item prefab \"" + itemIdentifier + "\" not found");
                        continue;
                    }

                    Vector2 spawnPos = nestPosition;
                    float   rotation = 0.0f;
                    if (spawnEdges.Any())
                    {
                        var edge = spawnEdges.GetRandom(Rand.RandSync.Server);
                        spawnPos = Vector2.Lerp(edge.Point1, edge.Point2, Rand.Range(0.1f, 0.9f, Rand.RandSync.Server));
                        Vector2 normal = Vector2.UnitY;
                        if (edge.Cell1 != null && edge.Cell1.CellType == CellType.Solid)
                        {
                            normal = edge.GetNormal(edge.Cell1);
                        }
                        else if (edge.Cell2 != null && edge.Cell2.CellType == CellType.Solid)
                        {
                            normal = edge.GetNormal(edge.Cell2);
                        }
                        spawnPos += normal * 10.0f;
                        rotation  = MathUtils.VectorToAngle(normal) - MathHelper.PiOver2;
                    }

                    var item = new Item(itemPrefab, spawnPos, null);
                    item.body.FarseerBody.BodyType = BodyType.Kinematic;
                    item.body.SetTransformIgnoreContacts(item.body.SimPosition, rotation);
                    item.FindHull();
                    items.Add(item);

                    var statusEffectElement = subElement.Element("StatusEffectOnApproach") ?? subElement.Element("statuseffectonapproach");
                    if (statusEffectElement != null)
                    {
                        statusEffectOnApproach.Add(item, StatusEffect.Load(statusEffectElement, Prefab.Identifier));
                    }
                }
            }
        }
Example #15
0
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        public override void Update(double deltaTime)
        {
#if RUN_PHYSICS_IN_SEPARATE_THREAD
            physicsTime += deltaTime;
            lock (updateLock)
            {
#endif


#if DEBUG && CLIENT
            if (GameMain.GameSession != null && GameMain.GameSession.Level != null && GameMain.GameSession.Submarine != null &&
                !DebugConsole.IsOpen && GUI.KeyboardDispatcher.Subscriber == null)
            {
                var closestSub = Submarine.FindClosest(cam.WorldViewCenter);
                if (closestSub == null)
                {
                    closestSub = GameMain.GameSession.Submarine;
                }

                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;
                }

                if (targetMovement != Vector2.Zero)
                {
                    closestSub.ApplyForce(targetMovement * closestSub.SubBody.Body.Mass * 100.0f);
                }
            }
#endif

            GameTime += deltaTime;

            foreach (PhysicsBody body in PhysicsBody.List)
            {
                if (body.Enabled)
                {
                    body.Update();
                }
            }
            foreach (MapEntity e in MapEntity.mapEntityList)
            {
                e.IsHighlighted = false;
            }

            if (GameMain.GameSession != null)
            {
                GameMain.GameSession.Update((float)deltaTime);
            }
#if CLIENT
            var sw = new System.Diagnostics.Stopwatch();
            sw.Start();

            GameMain.ParticleManager.Update((float)deltaTime);

            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("ParticleUpdate", sw.ElapsedTicks);
            sw.Restart();

            if (Level.Loaded != null)
            {
                Level.Loaded.Update((float)deltaTime, cam);
            }

            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("LevelUpdate", sw.ElapsedTicks);

            if (Character.Controlled != null)
            {
                if (Character.Controlled.SelectedConstruction != null && Character.Controlled.CanInteractWith(Character.Controlled.SelectedConstruction))
                {
                    Character.Controlled.SelectedConstruction.UpdateHUD(cam, Character.Controlled, (float)deltaTime);
                }
                if (Character.Controlled.Inventory != null)
                {
                    foreach (Item item in Character.Controlled.Inventory.Items)
                    {
                        if (item == null)
                        {
                            continue;
                        }
                        if (Character.Controlled.HasEquippedItem(item))
                        {
                            item.UpdateHUD(cam, Character.Controlled, (float)deltaTime);
                        }
                    }
                }
            }


            sw.Restart();

            Character.UpdateAll((float)deltaTime, cam);
#elif SERVER
            if (Level.Loaded != null)
            {
                Level.Loaded.Update((float)deltaTime, Camera.Instance);
            }
            Character.UpdateAll((float)deltaTime, Camera.Instance);
#endif


#if CLIENT
            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("CharacterUpdate", sw.ElapsedTicks);
            sw.Restart();
#endif

            StatusEffect.UpdateAll((float)deltaTime);

#if CLIENT
            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("StatusEffectUpdate", sw.ElapsedTicks);
            sw.Restart();

            if (Character.Controlled != null &&
                Lights.LightManager.ViewTarget != null)
            {
                Vector2 targetPos = Lights.LightManager.ViewTarget.DrawPosition;
                if (Lights.LightManager.ViewTarget == Character.Controlled &&
                    (CharacterHealth.OpenHealthWindow != null || CrewManager.IsCommandInterfaceOpen))
                {
                    Vector2 screenTargetPos = new Vector2(0.0f, GameMain.GraphicsHeight * 0.5f);
                    if (CrewManager.IsCommandInterfaceOpen)
                    {
                        screenTargetPos.X = GameMain.GraphicsWidth * 0.5f;
                    }
                    else
                    {
                        screenTargetPos = CharacterHealth.OpenHealthWindow.Alignment == Alignment.Left ?
                                          new Vector2(GameMain.GraphicsWidth * 0.75f, GameMain.GraphicsHeight * 0.5f) :
                                          new Vector2(GameMain.GraphicsWidth * 0.25f, GameMain.GraphicsHeight * 0.5f);
                    }
                    Vector2 screenOffset = screenTargetPos - new Vector2(GameMain.GraphicsWidth / 2, GameMain.GraphicsHeight / 2);
                    screenOffset.Y = -screenOffset.Y;
                    targetPos     -= screenOffset / cam.Zoom;
                }
                cam.TargetPos = targetPos;
            }

            cam.MoveCamera((float)deltaTime);
#endif

            foreach (Submarine sub in Submarine.Loaded)
            {
                sub.SetPrevTransform(sub.Position);
            }

            foreach (PhysicsBody body in PhysicsBody.List)
            {
                if (body.Enabled)
                {
                    body.SetPrevTransform(body.SimPosition, body.Rotation);
                }
            }

#if CLIENT
            MapEntity.UpdateAll((float)deltaTime, cam);
#elif SERVER
            MapEntity.UpdateAll((float)deltaTime, Camera.Instance);
#endif

#if CLIENT
            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("MapEntityUpdate", sw.ElapsedTicks);
            sw.Restart();
#endif
            Character.UpdateAnimAll((float)deltaTime);

#if CLIENT
            Ragdoll.UpdateAll((float)deltaTime, cam);
#elif SERVER
            Ragdoll.UpdateAll((float)deltaTime, Camera.Instance);
#endif

#if CLIENT
            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("AnimUpdate", sw.ElapsedTicks);
            sw.Restart();
#endif

            foreach (Submarine sub in Submarine.Loaded)
            {
                sub.Update((float)deltaTime);
            }

#if CLIENT
            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("SubmarineUpdate", sw.ElapsedTicks);
            sw.Restart();
#endif

#if !RUN_PHYSICS_IN_SEPARATE_THREAD
            try
            {
                GameMain.World.Step((float)Timing.Step);
            }
            catch (WorldLockedException e)
            {
                string errorMsg = "Attempted to modify the state of the physics simulation while a time step was running.";
                DebugConsole.ThrowError(errorMsg, e);
                GameAnalyticsManager.AddErrorEventOnce("GameScreen.Update:WorldLockedException" + e.Message, GameAnalyticsSDK.Net.EGAErrorSeverity.Critical, errorMsg);
            }
#endif


#if CLIENT
            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("Physics", sw.ElapsedTicks);
#endif

#if CLIENT
            if (!PlayerInput.PrimaryMouseButtonHeld())
            {
                Inventory.draggingSlot = null;
                Inventory.draggingItem = null;
            }
#endif


#if RUN_PHYSICS_IN_SEPARATE_THREAD
        }
#endif
        }
        public static RelatedItem Load(XElement element, string parentDebugName)
        {
            string[] identifiers;
            if (element.Attribute("name") != null)
            {
                //backwards compatibility + a console warning
                DebugConsole.ThrowError("Error in RelatedItem config (" + (string.IsNullOrEmpty(parentDebugName) ? element.ToString() : parentDebugName) + ") - use item identifiers or tags instead of names.");
                string[] itemNames = element.GetAttributeStringArray("name", new string[0]);
                //attempt to convert to identifiers and tags
                List <string> convertedIdentifiers = new List <string>();
                foreach (string itemName in itemNames)
                {
                    if (MapEntityPrefab.List.Find(me => me.Name == itemName) is ItemPrefab matchingItem)
                    {
                        convertedIdentifiers.Add(matchingItem.Identifier);
                    }
                    else
                    {
                        //no matching item found, this must be a tag
                        convertedIdentifiers.Add(itemName);
                    }
                }
                identifiers = convertedIdentifiers.ToArray();
            }
            else
            {
                identifiers = element.GetAttributeStringArray("identifiers", new string[0]);
                if (identifiers.Length == 0)
                {
                    identifiers = element.GetAttributeStringArray("identifier", new string[0]);
                }
            }

            string[] excludedIdentifiers = element.GetAttributeStringArray("excludedidentifiers", new string[0]);
            if (excludedIdentifiers.Length == 0)
            {
                excludedIdentifiers = element.GetAttributeStringArray("excludedidentifier", new string[0]);
            }

            if (identifiers.Length == 0 && excludedIdentifiers.Length == 0)
            {
                return(null);
            }

            RelatedItem ri = new RelatedItem(identifiers, excludedIdentifiers);

            string typeStr = element.GetAttributeString("type", "");

            if (string.IsNullOrEmpty(typeStr))
            {
                if (element.Name.ToString().ToLowerInvariant() == "containable")
                {
                    typeStr = "Contained";
                }
            }
            if (!Enum.TryParse(typeStr, true, out ri.type))
            {
                DebugConsole.ThrowError("Error in RelatedItem config (" + parentDebugName + ") - \"" + typeStr + "\" is not a valid relation type.");
                return(null);
            }

            string msgTag = element.GetAttributeString("msg", "");
            string msg    = TextManager.Get(msgTag, true);

            if (msg == null)
            {
                ri.Msg = msgTag;
            }
            else
            {
#if CLIENT
                foreach (InputType inputType in Enum.GetValues(typeof(InputType)))
                {
                    msg = msg.Replace("[" + inputType.ToString().ToLowerInvariant() + "]", GameMain.Config.KeyBind(inputType).ToString());
                }
                ri.Msg = msg;
#endif
            }

            foreach (XElement subElement in element.Elements())
            {
                if (subElement.Name.ToString().ToLowerInvariant() != "statuseffect")
                {
                    continue;
                }
                ri.statusEffects.Add(StatusEffect.Load(subElement, parentDebugName));
            }

            ri.IsOptional = element.GetAttributeBool("optional", false);
            return(ri);
        }
Example #17
0
 public static void LoadStatusEffect(List <StatusEffect> statusEffects, XElement element, string parentDebugName)
 {
     statusEffects.Add(StatusEffect.Load(element, parentDebugName));
 }
Example #18
0
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        public override void Update(double deltaTime)
        {
#if CLIENT
            if (Character.Spied != null)
            {
                if ((PlayerInput.KeyDown(InputType.Up) || PlayerInput.KeyDown(InputType.Down) || PlayerInput.KeyDown(InputType.Left) || PlayerInput.KeyDown(InputType.Right)) && !DebugConsole.IsOpen)
                {
                    if (GameMain.NetworkMember != null && !GameMain.NetworkMember.chatMsgBox.Selected)
                    {
                        if (Character.Controlled != null)
                        {
                            cam.Position = Character.Controlled.WorldPosition;
                        }
                        else
                        {
                            cam.Position = Character.Spied.WorldPosition;
                        }
                        Character.Spied = null;
                        cam.UpdateTransform(true);
                    }
                }
            }
#endif

#if DEBUG && CLIENT
            if (GameMain.GameSession != null && GameMain.GameSession.Level != null && GameMain.GameSession.Submarine != null &&
                !DebugConsole.IsOpen && GUIComponent.KeyboardDispatcher.Subscriber == null)
            {
                /*
                 * var closestSub = Submarine.FindClosest(cam.WorldViewCenter);
                 * if (closestSub == null) closestSub = GameMain.GameSession.Submarine;
                 *
                 * 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;
                 *
                 * if (targetMovement != Vector2.Zero)
                 *  closestSub.ApplyForce(targetMovement * closestSub.SubBody.Body.Mass * 100.0f);
                 */
            }
#endif

#if CLIENT
            GameMain.NilModProfiler.SWMapEntityUpdate.Start();
#endif

            foreach (MapEntity e in MapEntity.mapEntityList)
            {
                e.IsHighlighted = false;
            }

#if CLIENT
            GameMain.NilModProfiler.SWMapEntityUpdate.Stop();

            if (GameMain.GameSession != null)
            {
                GameMain.NilModProfiler.SWGameSessionUpdate.Start();
                GameMain.GameSession.Update((float)deltaTime);
                GameMain.NilModProfiler.RecordGameSessionUpdate();
            }

            GameMain.NilModProfiler.SWParticleManager.Start();

            GameMain.ParticleManager.Update((float)deltaTime);

            GameMain.NilModProfiler.RecordParticleManager();
            GameMain.NilModProfiler.SWLightManager.Start();

            GameMain.LightManager.Update((float)deltaTime);

            GameMain.NilModProfiler.RecordLightManager();
#endif

            if (Level.Loaded != null)
            {
#if CLIENT
                GameMain.NilModProfiler.SWLevelUpdate.Start();
#endif
                Level.Loaded.Update((float)deltaTime, cam);
#if CLIENT
                GameMain.NilModProfiler.RecordLevelUpdate();
#endif
            }

#if CLIENT
            if (Character.Controlled != null && Character.Controlled.SelectedConstruction != null && Character.Controlled.CanInteractWith(Character.Controlled.SelectedConstruction))
            {
                Character.Controlled.SelectedConstruction.UpdateHUD(cam, Character.Controlled);
            }
            GameMain.NilModProfiler.SWCharacterUpdate.Start();
#endif

            Character.UpdateAll((float)deltaTime, cam);

#if CLIENT
            //NilMod spy Code
            if (Character.Spied != null)
            {
                Character.ViewSpied((float)deltaTime, Cam, true);
                Lights.LightManager.ViewTarget = Character.Spied;
                CharacterHUD.Update((float)deltaTime, Character.Spied);

                foreach (HUDProgressBar progressBar in Character.Spied.HUDProgressBars.Values)
                {
                    progressBar.Update((float)deltaTime);
                }

                foreach (var pb in Character.Spied.HUDProgressBars)
                {
                    if (pb.Value.FadeTimer <= 0.0f)
                    {
                        Character.Spied.HUDProgressBars.Remove(pb.Key);
                    }
                }
            }

            GameMain.NilModProfiler.SWCharacterUpdate.Stop();
            GameMain.NilModProfiler.RecordCharacterUpdate();
            GameMain.NilModProfiler.SWStatusEffect.Start();
#endif
            StatusEffect.UpdateAll((float)deltaTime);

#if CLIENT
            GameMain.NilModProfiler.RecordStatusEffect();
            if ((Character.Controlled != null && Lights.LightManager.ViewTarget != null) || (Character.Spied != null && Lights.LightManager.ViewTarget != null))
            {
                cam.TargetPos = Lights.LightManager.ViewTarget.WorldPosition;
            }
#endif

            cam.MoveCamera((float)deltaTime);
#if CLIENT
            GameMain.NilModProfiler.SWSetTransforms.Start();
#endif
            foreach (Submarine sub in Submarine.Loaded)
            {
                sub.SetPrevTransform(sub.Position);
            }

            foreach (PhysicsBody pb in PhysicsBody.List)
            {
                pb.SetPrevTransform(pb.SimPosition, pb.Rotation);
            }
#if CLIENT
            GameMain.NilModProfiler.RecordSetTransforms();
            GameMain.NilModProfiler.SWMapEntityUpdate.Start();
#endif
            MapEntity.UpdateAll((float)deltaTime, cam);
#if CLIENT
            GameMain.NilModProfiler.RecordMapEntityUpdate();
            GameMain.NilModProfiler.SWCharacterAnimUpdate.Start();
#endif
            Character.UpdateAnimAll((float)deltaTime);
#if CLIENT
            GameMain.NilModProfiler.RecordCharacterAnimUpdate();
            GameMain.NilModProfiler.SWRagdollUpdate.Start();
#endif
            Ragdoll.UpdateAll((float)deltaTime, cam);
#if CLIENT
            GameMain.NilModProfiler.RecordRagdollUpdate();
            GameMain.NilModProfiler.SWSubmarineUpdate.Start();
#endif
            foreach (Submarine sub in Submarine.Loaded)
            {
                sub.Update((float)deltaTime);
            }

#if CLIENT
            GameMain.NilModProfiler.RecordSubmarineUpdate();
            GameMain.NilModProfiler.SWCharacterUpdate.Start();
#endif

#if CLIENT
            GameMain.NilModProfiler.RecordCharacterUpdate();
            GameMain.NilModProfiler.SWPhysicsWorldStep.Start();
#endif
            GameMain.World.Step((float)deltaTime);
#if CLIENT
            GameMain.NilModProfiler.RecordPhysicsWorldStep();

            if (!PlayerInput.LeftButtonHeld())
            {
                Inventory.draggingSlot = null;
                Inventory.draggingItem = null;
            }
#endif
        }
Example #19
0
        private static XElement ParseWeapon(ItemPrefab prefab)
        {
            float stun             = 0;
            bool  isAoE            = false;
            float?structDamage     = null;
            int   skillRequirement = 0;

            // affliction, amount
            List <Tuple <string, float> > damages = new List <Tuple <string, float> >();

            string[] validNames = { nameof(Projectile), nameof(MeleeWeapon), nameof(RepairTool), nameof(ItemComponent), nameof(RangedWeapon) };
            foreach (XElement icElement in prefab.ConfigElement.Elements())
            {
                string icName = icElement.Name.ToString();
                if (!validNames.Any(name => icName.Equals(name, StringComparison.OrdinalIgnoreCase)))
                {
                    continue;
                }

                foreach (XElement icChildElement in icElement.Elements())
                {
                    string name = icChildElement.Name.ToString();
                    if (IsRequiredSkill(icChildElement, out Skill? skill) && skill != null)
                    {
                        skillRequirement = (int)skill.Level;
                    }
                    else if (name.Equals(nameof(Attack), StringComparison.OrdinalIgnoreCase))
                    {
                        ParseAttack(new Attack(icChildElement, debugIdentifier));
                    }
                    else if (name.Equals(nameof(Explosion), StringComparison.OrdinalIgnoreCase))
                    {
                        ParseExplosion(new[] { new Explosion(icChildElement, debugIdentifier) });
                    }
                    else if (name.Equals(nameof(StatusEffect), StringComparison.OrdinalIgnoreCase))
                    {
                        ParseStatusEffect(new[] { StatusEffect.Load(icChildElement, debugIdentifier) });
                    }

                    void ParseStatusEffect(IEnumerable <StatusEffect> statusEffects)
                    {
                        foreach (StatusEffect effect in statusEffects)
                        {
                            if (effect.HasTargetType(StatusEffect.TargetType.Character))
                            {
                                continue;
                            }

                            ParseAfflictions(effect.Afflictions);
                            ParseExplosion(effect.Explosions);
                        }
                    }

                    void ParseExplosion(IEnumerable <Explosion> explosions)
                    {
                        foreach (Explosion explosion in explosions)
                        {
                            isAoE = true;
                            ParseAttack(explosion.Attack);
                            ParseStatusEffect(explosion.Attack.StatusEffects);
                        }
                    }

                    void ParseAttack(Attack attack)
                    {
                        structDamage ??= attack.StructureDamage;
                        ParseAfflictions(attack.Afflictions.Keys);
                        ParseStatusEffect(attack.StatusEffects);
                    }

                    void ParseAfflictions(IEnumerable <Affliction> afflictions)
                    {
                        foreach (Affliction affliction in afflictions)
                        {
                            // Exclude stuns
                            if (affliction.Prefab == AfflictionPrefab.Stun)
                            {
                                stun += affliction.NonClampedStrength;
                                continue;
                            }

                            damages.Add(Tuple.Create(affliction.Prefab.Name, affliction.NonClampedStrength));
                        }
                    }
                }
            }

            return(new XElement("Weapon",
                                new XAttribute("damagenames", FormatArray(damages.Select(tpl => tpl.Item1))),
                                new XAttribute("damageamounts", FormatArray(damages.Select(tpl => FormatFloat(tpl.Item2)))),
                                new XAttribute("isaoe", isAoE),
                                new XAttribute("structuredamage", structDamage ?? 0),
                                new XAttribute("stun", FormatFloat(stun)),
                                new XAttribute("skillrequirement", skillRequirement)
                                ));
        }