protected void ChangeLocationType(LocationTypeChange change) { if (change == null) { throw new ArgumentException(); } if (GameMain.GameSession.GameMode is CampaignMode && !IsClient) { int srcIndex = -1; for (int i = 0; i < Locations.Length; i++) { if (Locations[i].Type.Identifier.Equals(change.CurrentType, StringComparison.OrdinalIgnoreCase)) { srcIndex = i; break; } } if (srcIndex == -1) { return; } var location = Locations[srcIndex]; if (change.RequiredDurationRange.X > 0) { location.PendingLocationTypeChange = (change, Rand.Range(change.RequiredDurationRange.X, change.RequiredDurationRange.Y), Prefab); } else { location.ChangeType(LocationType.List.Find(lt => lt.Identifier.Equals(change.ChangeToType, StringComparison.OrdinalIgnoreCase))); location.LocationTypeChangeCooldown = change.CooldownAfterChange; } } }
partial void ChangeLocationType(Location location, string prevName, LocationTypeChange change) { //focus on the location var mapAnim = new MapAnim() { EndZoom = zoom * 1.5f, EndLocation = location, Duration = CurrentLocation == location ? 1.0f : 2.0f, StartDelay = 1.0f }; if (change.Messages != null && change.Messages.Count > 0) { mapAnim.EndMessage = change.Messages[Rand.Range(0, change.Messages.Count)] .Replace("[previousname]", prevName) .Replace("[name]", location.Name); } mapAnimQueue.Enqueue(mapAnim); mapAnimQueue.Enqueue(new MapAnim() { EndZoom = zoom, StartLocation = location, EndLocation = CurrentLocation, Duration = 1.0f, StartDelay = 0.5f }); }
private void ChangeLocationType(Location location, LocationTypeChange change) { string prevName = location.Name; location.ChangeType(LocationType.List.Find(lt => lt.Identifier.Equals(change.ChangeToType, StringComparison.OrdinalIgnoreCase))); ChangeLocationTypeProjSpecific(location, prevName, change); location.ProximityTimer.Remove(change); location.TimeSinceLastTypeChange = 0; location.PendingLocationTypeChange = null; }
partial void ChangeLocationType(Location location, string prevName, LocationTypeChange change) { if (change.Messages.Any()) { string msg = change.Messages[Rand.Range(0, change.Messages.Count)] .Replace("[previousname]", prevName) .Replace("[name]", location.Name); location.LastTypeChangeMessage = msg; if (GameMain.Client != null) { GameMain.Client.AddChatMessage(msg, Networking.ChatMessageType.Default, TextManager.Get("RadioAnnouncerName")); } else { GameMain.GameSession?.GameMode.CrewManager.AddSinglePlayerChatMessage( TextManager.Get("RadioAnnouncerName"), msg, Networking.ChatMessageType.Default, sender: null); } } }
public Requirement(XElement element, LocationTypeChange change) { RequiredLocations = element.GetAttributeStringArray("requiredlocations", element.GetAttributeStringArray("requiredadjacentlocations", new string[0])).ToList(); RequiredProximity = Math.Max(element.GetAttributeInt("requiredproximity", 1), 1); ProximityProbabilityIncrease = element.GetAttributeFloat("proximityprobabilityincrease", 0.0f); RequiredProximityForProbabilityIncrease = element.GetAttributeInt("requiredproximityforprobabilityincrease", -1); RequireBeaconStation = element.GetAttributeBool("requirebeaconstation", false); RequireHuntingGrounds = element.GetAttributeBool("requirehuntinggrounds", false); string functionStr = element.GetAttributeString("function", "Add"); if (!Enum.TryParse(functionStr, ignoreCase: true, out Function)) { DebugConsole.ThrowError( $"Invalid location type change in location type \"{change.CurrentType}\". " + $"\"{functionStr}\" is not a valid function."); } Probability = element.GetAttributeFloat("probability", 1.0f); if (RequiredProximityForProbabilityIncrease > 0 || ProximityProbabilityIncrease > 0.0f) { if (!RequiredLocations.Any() && !RequireBeaconStation && !RequireHuntingGrounds) { DebugConsole.AddWarning( $"Invalid location type change in location type \"{change.CurrentType}\". " + "Probability is configured to increase when near some other type of location, but the RequiredLocations attribute is not set."); } if (Probability >= 1.0f) { DebugConsole.AddWarning( $"Invalid location type change in location type \"{change.CurrentType}\". " + "Probability is configured to increase when near some other type of location, but the base probability is already 100%"); } } }
partial void ChangeLocationType(Location location, string prevName, LocationTypeChange change);
partial void ChangeLocationTypeProjSpecific(Location location, string prevName, LocationTypeChange change);
public MissionPrefab(XElement element) { ConfigElement = element; Identifier = element.GetAttributeString("identifier", ""); TextIdentifier = element.GetAttributeString("textidentifier", null) ?? Identifier; tags = element.GetAttributeStringArray("tags", new string[0], convertToLowerInvariant: true); Name = TextManager.Get("MissionName." + TextIdentifier, true) ?? element.GetAttributeString("name", ""); Description = TextManager.Get("MissionDescription." + TextIdentifier, true) ?? element.GetAttributeString("description", ""); Reward = element.GetAttributeInt("reward", 1); AllowRetry = element.GetAttributeBool("allowretry", false); IsSideObjective = element.GetAttributeBool("sideobjective", false); Commonness = element.GetAttributeInt("commonness", 1); if (element.GetAttribute("difficulty") != null) { int difficulty = element.GetAttributeInt("difficulty", MinDifficulty); Difficulty = Math.Clamp(difficulty, MinDifficulty, MaxDifficulty); } SuccessMessage = TextManager.Get("MissionSuccess." + TextIdentifier, true) ?? element.GetAttributeString("successmessage", "Mission completed successfully"); FailureMessage = TextManager.Get("MissionFailure." + TextIdentifier, true) ?? ""; if (string.IsNullOrEmpty(FailureMessage) && TextManager.ContainsTag("missionfailed")) { FailureMessage = TextManager.Get("missionfailed", returnNull: true) ?? ""; } if (string.IsNullOrEmpty(FailureMessage) && GameMain.Config.Language == "English") { FailureMessage = element.GetAttributeString("failuremessage", ""); } SonarLabel = TextManager.Get("MissionSonarLabel." + TextIdentifier, true) ?? TextManager.Get("MissionSonarLabel." + element.GetAttributeString("sonarlabel", ""), true) ?? element.GetAttributeString("sonarlabel", ""); SonarIconIdentifier = element.GetAttributeString("sonaricon", ""); MultiplayerOnly = element.GetAttributeBool("multiplayeronly", false); SingleplayerOnly = element.GetAttributeBool("singleplayeronly", false); AchievementIdentifier = element.GetAttributeString("achievementidentifier", ""); UnhideEntitySubCategories = element.GetAttributeStringArray("unhideentitysubcategories", new string[0]).ToList(); Headers = new List <string>(); Messages = new List <string>(); AllowedConnectionTypes = new List <Pair <string, string> >(); for (int i = 0; i < 100; i++) { string header = TextManager.Get("MissionHeader" + i + "." + TextIdentifier, true); string message = TextManager.Get("MissionMessage" + i + "." + TextIdentifier, true); if (!string.IsNullOrEmpty(message)) { Headers.Add(header); Messages.Add(message); } } int messageIndex = 0; foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) { case "message": if (messageIndex > Headers.Count - 1) { Headers.Add(string.Empty); Messages.Add(string.Empty); } Headers[messageIndex] = TextManager.Get("MissionHeader" + messageIndex + "." + TextIdentifier, true) ?? subElement.GetAttributeString("header", ""); Messages[messageIndex] = TextManager.Get("MissionMessage" + messageIndex + "." + TextIdentifier, true) ?? subElement.GetAttributeString("text", ""); messageIndex++; break; case "locationtype": case "connectiontype": if (subElement.Attribute("identifier") != null) { AllowedLocationTypes.Add(subElement.GetAttributeString("identifier", "")); } else { AllowedConnectionTypes.Add(new Pair <string, string>( subElement.GetAttributeString("from", ""), subElement.GetAttributeString("to", ""))); } break; case "locationtypechange": LocationTypeChangeOnCompleted = new LocationTypeChange(subElement.GetAttributeString("from", ""), subElement, requireChangeMessages: false, defaultProbability: 1.0f); break; case "reputation": case "reputationreward": string factionIdentifier = subElement.GetAttributeString("identifier", ""); float amount = subElement.GetAttributeFloat("amount", 0.0f); if (ReputationRewards.ContainsKey(factionIdentifier)) { DebugConsole.ThrowError($"Error in mission prefab \"{Identifier}\". Multiple reputation changes defined for the identifier \"{factionIdentifier}\"."); continue; } ReputationRewards.Add(factionIdentifier, amount); if (!factionIdentifier.Equals("location", StringComparison.OrdinalIgnoreCase)) { if (FactionPrefab.Prefabs != null && !FactionPrefab.Prefabs.Any(p => p.Identifier.Equals(factionIdentifier, StringComparison.OrdinalIgnoreCase))) { DebugConsole.ThrowError($"Error in mission prefab \"{Identifier}\". Could not find a faction with the identifier \"{factionIdentifier}\"."); } } break; case "metadata": string identifier = subElement.GetAttributeString("identifier", string.Empty); string stringValue = subElement.GetAttributeString("value", string.Empty); if (!string.IsNullOrWhiteSpace(stringValue) && !string.IsNullOrWhiteSpace(identifier)) { object value = SetDataAction.ConvertXMLValue(stringValue); SetDataAction.OperationType operation = SetDataAction.OperationType.Set; string operatingString = subElement.GetAttributeString("operation", string.Empty); if (!string.IsNullOrWhiteSpace(operatingString)) { operation = (SetDataAction.OperationType)Enum.Parse(typeof(SetDataAction.OperationType), operatingString); } DataRewards.Add(Tuple.Create(identifier, value, operation)); } break; } } string missionTypeName = element.GetAttributeString("type", ""); if (!Enum.TryParse(missionTypeName, out Type)) { DebugConsole.ThrowError("Error in mission prefab \"" + Name + "\" - \"" + missionTypeName + "\" is not a valid mission type."); return; } if (Type == MissionType.None) { DebugConsole.ThrowError("Error in mission prefab \"" + Name + "\" - mission type cannot be none."); return; } if (CoOpMissionClasses.ContainsKey(Type)) { constructor = CoOpMissionClasses[Type].GetConstructor(new[] { typeof(MissionPrefab), typeof(Location[]) }); } else if (PvPMissionClasses.ContainsKey(Type)) { constructor = PvPMissionClasses[Type].GetConstructor(new[] { typeof(MissionPrefab), typeof(Location[]) }); } else { DebugConsole.ThrowError("Error in mission prefab \"" + Name + "\" - unsupported mission type \"" + Type.ToString() + "\""); } InitProjSpecific(element); }
private void ProgressWorld() { foreach (Location location in Locations) { if (furthestDiscoveredLocation == null || location.MapPosition.X > furthestDiscoveredLocation.MapPosition.X) { furthestDiscoveredLocation = location; } } foreach (Location location in Locations) { if (location.MapPosition.X < furthestDiscoveredLocation.MapPosition.X) { furthestDiscoveredLocation = location; } if (location == CurrentLocation || location == SelectedLocation) { continue; } //find which types of locations this one can change to var cct = location.Type.CanChangeTo; List <LocationTypeChange> allowedTypeChanges = new List <LocationTypeChange>(); List <int> readyTypeChanges = new List <int>(); for (int i = 0; i < cct.Count; i++) { LocationTypeChange typeChange = cct[i]; if (typeChange.RequireDiscovered && !location.Discovered) { continue; } //check if there are any adjacent locations that would prevent the change bool disallowedFound = false; foreach (string disallowedLocationName in typeChange.DisallowedAdjacentLocations) { if (location.Connections.Any(c => c.OtherLocation(location).Type.Identifier.Equals(disallowedLocationName, StringComparison.OrdinalIgnoreCase))) { disallowedFound = true; break; } } if (disallowedFound) { continue; } //check that there's a required adjacent location present bool requiredFound = false; foreach (string requiredLocationName in typeChange.RequiredAdjacentLocations) { if (location.Connections.Any(c => c.OtherLocation(location).Type.Identifier.Equals(requiredLocationName, StringComparison.OrdinalIgnoreCase))) { requiredFound = true; break; } } if (!requiredFound && typeChange.RequiredAdjacentLocations.Count > 0) { continue; } allowedTypeChanges.Add(typeChange); if (location.TypeChangeTimer >= typeChange.RequiredDuration) { readyTypeChanges.Add(i); } } List <float> readyTypeProbabilities = readyTypeChanges.Select(i => cct[i].DetermineProbability(location)).ToList(); //select a random type change if (Rand.Range(0.0f, 1.0f) < readyTypeChanges.Sum(i => readyTypeProbabilities[i])) { var selectedTypeChangeIndex = ToolBox.SelectWeightedRandom( readyTypeChanges, readyTypeChanges.Select(i => readyTypeProbabilities[i]).ToList(), Rand.RandSync.Unsynced); var selectedTypeChange = cct[selectedTypeChangeIndex]; if (selectedTypeChange != null) { string prevName = location.Name; location.ChangeType(LocationType.List.Find(lt => lt.Identifier.Equals(selectedTypeChange.ChangeToType, StringComparison.OrdinalIgnoreCase))); ChangeLocationType(location, prevName, selectedTypeChange); location.TypeChangeTimer = -1; } } if (allowedTypeChanges.Count > 0) { location.TypeChangeTimer++; } else { location.TypeChangeTimer = 0; } location.UpdateStore(); } }