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; } } }
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; } } }
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; } } }
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); }
/// <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; } }
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; } } }
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); }
/// <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 }
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; } }
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; }
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; } } }
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(); }
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)); } } } }
/// <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); }
public static void LoadStatusEffect(List <StatusEffect> statusEffects, XElement element, string parentDebugName) { statusEffects.Add(StatusEffect.Load(element, parentDebugName)); }
/// <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 }
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) )); }