/// <summary> /// Undiscover the specified building in current location. /// used to undiscover residences when they are a quest resource (named residence) when "add dialog" is done for this quest resource or on quest startup /// otherwise previously discovered residences will automatically show up on the automap when used in a quest /// </summary> /// <param name="buildingKey">Building key of building to be undiscovered</param> /// <param name="onlyIfResidence">gets undiscovered only if buildingType is residence</param> public void UndiscoverBuilding(int buildingKey, bool onlyIfResidence = false) { // Must have a location loaded if (!CurrentLocation.Loaded) { return; } // Get building information DiscoveredBuilding db; if (!GetBuildingDiscoveryData(buildingKey, out db)) { return; } // Get location discovery int mapPixelID = MapsFile.GetMapPixelIDFromLongitudeLatitude((int)CurrentLocation.MapTableData.Longitude, CurrentLocation.MapTableData.Latitude); DiscoveredLocation dl = new DiscoveredLocation(); if (discoveredLocations.ContainsKey(mapPixelID)) { dl = discoveredLocations[mapPixelID]; } if (onlyIfResidence && !RMBLayout.IsResidence(db.buildingType)) { return; } if (dl.discoveredBuildings != null && dl.discoveredBuildings.ContainsKey(db.buildingKey)) { dl.discoveredBuildings.Remove(db.buildingKey); } }
/// <summary> /// Gets building information from current location. /// Does not change discovery state for building. /// </summary> /// <param name="buildingKey">Key of building to query.</param> bool GetBuildingDiscoveryData(int buildingKey, out DiscoveredBuilding buildingDiscoveryData) { buildingDiscoveryData = new DiscoveredBuilding(); // Get building directory for location BuildingDirectory buildingDirectory = GameManager.Instance.StreamingWorld.GetCurrentBuildingDirectory(); if (!buildingDirectory) { return(false); } // Get detailed building data from directory BuildingSummary buildingSummary; if (!buildingDirectory.GetBuildingSummary(buildingKey, out buildingSummary)) { int layoutX, layoutY, recordIndex; BuildingDirectory.ReverseBuildingKey(buildingKey, out layoutX, out layoutY, out recordIndex); Debug.LogFormat("Unable to find expected building key {0} in {1}.{2}", buildingKey, buildingDirectory.LocationData.RegionName, buildingDirectory.LocationData.Name); Debug.LogFormat("LayoutX={0}, LayoutY={1}, RecordIndex={2}", layoutX, layoutY, recordIndex); return(false); } // Resolve name by building type string buildingName; if (RMBLayout.IsResidence(buildingSummary.BuildingType)) { // Residence // TODO: Link to quest system active sites buildingName = HardStrings.residence; } else { // Fixed building name buildingName = BuildingNames.GetName( buildingSummary.NameSeed, buildingSummary.BuildingType, buildingSummary.FactionId, buildingDirectory.LocationData.Name, buildingDirectory.LocationData.RegionName); } // Add to data buildingDiscoveryData.buildingKey = buildingKey; buildingDiscoveryData.displayName = buildingName; buildingDiscoveryData.factionID = buildingSummary.FactionId; buildingDiscoveryData.quality = buildingSummary.Quality; buildingDiscoveryData.buildingType = buildingSummary.BuildingType; return(true); }
// Output building info to HUD private void PresentBuildingInfo(StaticBuilding building) { // Get building directory for location BuildingDirectory buildingDirectory = GameManager.Instance.StreamingWorld.GetCurrentBuildingDirectory(); if (!buildingDirectory) { return; } // Get detailed building data from directory BuildingSummary buildingSummary; if (!buildingDirectory.GetBuildingSummary(building.buildingKey, out buildingSummary)) { int layoutX, layoutY, recordIndex; BuildingDirectory.ReverseBuildingKey(building.buildingKey, out layoutX, out layoutY, out recordIndex); Debug.LogFormat("Unable to find expected building key {0} in {1}.{2}", building.buildingKey, buildingDirectory.LocationData.RegionName, buildingDirectory.LocationData.Name); Debug.LogFormat("LayoutX={0}, LayoutY={1}, RecordIndex={2}", layoutX, layoutY, recordIndex); throw new Exception("Error finding building key in directory."); } // Resolve name by building type string buildingName; if (RMBLayout.IsResidence(buildingSummary.BuildingType)) { // Residence // TODO: Link to quest system active sites buildingName = HardStrings.residence; } else { // Fixed building name buildingName = BuildingNames.GetName( buildingSummary.NameSeed, buildingSummary.BuildingType, buildingSummary.FactionId, buildingDirectory.LocationData.Name, buildingDirectory.LocationData.RegionName); } // Output building name to HUD DaggerfallUI.AddHUDText(buildingName); }
/// <summary> /// Gets building information from current location. /// Does not change discovery state for building. /// </summary> /// <param name="buildingKey">Key of building to query.</param> bool GetBuildingDiscoveryData(int buildingKey, out DiscoveredBuilding buildingDiscoveryData) { buildingDiscoveryData = new DiscoveredBuilding(); // Get building directory for location BuildingDirectory buildingDirectory = GameManager.Instance.StreamingWorld.GetCurrentBuildingDirectory(); if (!buildingDirectory) { return(false); } // Get detailed building data from directory BuildingSummary buildingSummary; if (!buildingDirectory.GetBuildingSummary(buildingKey, out buildingSummary)) { int layoutX, layoutY, recordIndex; BuildingDirectory.ReverseBuildingKey(buildingKey, out layoutX, out layoutY, out recordIndex); Debug.LogFormat("Unable to find expected building key {0} in {1}.{2}", buildingKey, buildingDirectory.LocationData.RegionName, buildingDirectory.LocationData.Name); Debug.LogFormat("LayoutX={0}, LayoutY={1}, RecordIndex={2}", layoutX, layoutY, recordIndex); return(false); } // Resolve name by building type string buildingName; if (RMBLayout.IsResidence(buildingSummary.BuildingType)) { // Residence buildingName = HardStrings.residence; // Link to quest system active sites // note Nystul: do this via TalkManager, this might seem odd at first glance but there is a reason to do so: // get info from TalkManager if pc learned about existence of the building (i.e. its name) // either through dialog ("add dialog" or by dialog-link) or quest (quest did not hide location via "dialog link" command) bool pcLearnedAboutExistence = false; bool receivedDirectionalHints = false; bool locationWasMarkedOnMapByNPC = false; string overrideBuildingName = string.Empty; if (GameManager.Instance.TalkManager.IsBuildingQuestResource(buildingSummary.buildingKey, ref overrideBuildingName, ref pcLearnedAboutExistence, ref receivedDirectionalHints, ref locationWasMarkedOnMapByNPC)) { if (pcLearnedAboutExistence) { buildingName = overrideBuildingName; } } } else { // Fixed building name buildingName = BuildingNames.GetName( buildingSummary.NameSeed, buildingSummary.BuildingType, buildingSummary.FactionId, buildingDirectory.LocationData.Name, buildingDirectory.LocationData.RegionName); } // Add to data buildingDiscoveryData.buildingKey = buildingKey; buildingDiscoveryData.displayName = buildingName; buildingDiscoveryData.factionID = buildingSummary.FactionId; buildingDiscoveryData.quality = buildingSummary.Quality; buildingDiscoveryData.buildingType = buildingSummary.BuildingType; return(true); }
private static void OnTransitionToInterior_VariantResidenceNPCsprites(PlayerEnterExit.TransitionEventArgs args) { if (villagerVarietyMod != null && villagerVarietyNumVariants == 0) { ModManager.Instance.SendModMessage(VILLAGERVARIETY_MODNAME, "getNumVariants", null, (string message, object data) => { villagerVarietyNumVariants = (int)data; }); } PlayerEnterExit playerEnterExit = GameManager.Instance.PlayerEnterExit; DFLocation.BuildingData buildingData = playerEnterExit.Interior.BuildingData; if (RMBLayout.IsResidence(buildingData.BuildingType)) { Races race = GetClimateRace(); int gender = -1; Billboard[] dfBillboards = playerEnterExit.Interior.GetComponentsInChildren <Billboard>(); foreach (Billboard billboard in dfBillboards) { if (billboard.Summary.Archive == 182) { gender = GetGender182(billboard.Summary.Record); } else if (billboard.Summary.Archive == 184) { gender = GetGender184(billboard.Summary.Record); } if (gender != -1) { StaticNPC npc = billboard.GetComponent <StaticNPC>(); if (npc && npc.Data.factionID == 0) { int faceVariant = npc.Data.nameSeed % 29; Debug.LogFormat("Replace house NPC {0}.{1} with faceVariant {2} - {3}", billboard.Summary.Archive, billboard.Summary.Record, faceVariant, faceVariant < 24); if (faceVariant < 24) { int outfitVariant = npc.Data.nameSeed % 4; int archive = gender == (int)Genders.Male ? raceArchivesMale[race][outfitVariant] : raceArchivesFemale[race][outfitVariant]; int record = 5; int faceRecord = gender == (int)Genders.Male ? raceFaceRecordMale[race][outfitVariant] : raceFaceRecordFemale[race][outfitVariant]; faceRecord += faceVariant; bool materialSet = false; if (villagerVarietyMod != null) { int variant = npc.Data.nameSeed % villagerVarietyNumVariants; string season = ""; //ModManager.Instance.SendModMessage(VILLAGERVARIETY_MODNAME, "getSeasonStr", null, (string message, object data) => { season = (string)data; }); Debug.LogFormat("Replace house NPC {0}.{1} with {2}.{3}, outfit: {4} faceRecord: {5} ({6}) variant: {7} season: {8}", billboard.Summary.Archive, billboard.Summary.Record, archive, record, outfitVariant, faceRecord, faceVariant, variant, season); string imageName = null; ModManager.Instance.SendModMessage(VILLAGERVARIETY_MODNAME, "getImageName", new object[] { archive, record, 0, faceRecord, variant, season }, (string message, object data) => { imageName = (string)data; }); if (!string.IsNullOrEmpty(imageName) && villagerVarietyMod.HasAsset(imageName)) { // Get texture and create material Texture2D texture = villagerVarietyMod.GetAsset <Texture2D>(imageName); Material material = MaterialReader.CreateStandardMaterial(MaterialReader.CustomBlendMode.Cutout); material.mainTexture = texture; // Apply material to mesh renderer MeshRenderer meshRenderer = billboard.GetComponent <MeshRenderer>(); meshRenderer.sharedMaterial = material; // Create mesh and setup UV map for mesh filter Vector2 size; Mesh mesh = DaggerfallUnity.Instance.MeshReader.GetBillboardMesh(new Rect(0, 0, 1, 1), archive, record, out size); mesh.uv = new Vector2[] { new Vector2(0, 1), new Vector2(1, 1), new Vector2(0, 0), new Vector2(1, 0) }; MeshFilter meshFilter = billboard.GetComponent <MeshFilter>(); Destroy(meshFilter.sharedMesh); meshFilter.sharedMesh = mesh; materialSet = true; } } if (!materialSet) { billboard.SetMaterial(archive, record); billboard.FramesPerSecond = 1; } GameObjectHelper.AlignBillboardToGround(billboard.gameObject, billboard.Summary.Size); Dictionary <int, FlatsFile.FlatData> flatsDict = DaggerfallUnity.Instance.ContentReader.FlatsFileReader.FlatsDict; int flatId = FlatsFile.GetFlatID(npc.Data.billboardArchiveIndex, npc.Data.billboardRecordIndex); #if UNITY_EDITOR Debug.LogFormat("Replacing face dict for {0} with {1} (for {2}.{3} / {4}.{5})", flatsDict[flatId].faceIndex, faceRecord, npc.Data.billboardArchiveIndex, npc.Data.billboardRecordIndex, billboard.Summary.Archive, billboard.Summary.Record); #endif flatsDict[flatId] = new FlatsFile.FlatData() { archive = billboard.Summary.Archive, record = billboard.Summary.Record, faceIndex = faceRecord, }; } } } } } }
/// <summary> /// Generate a list of potential sites based on building type. /// This uses actual map layout and block data rather than the (often inaccurate) list of building in map data. /// Specify BuildingTypes.AllValid to find all valid building types /// </summary> SiteDetails[] CollectQuestSitesOfBuildingType(DFLocation location, DFLocation.BuildingTypes buildingType) { // Valid building types for valid search int[] validBuildingTypes = { 0, 2, 3, 5, 6, 8, 9, 11, 12, 13, 14, 15, 17, 18, 19, 20 }; List <SiteDetails> foundSites = new List <SiteDetails>(); // Iterate through all blocks DFBlock[] blocks; RMBLayout.GetLocationBuildingData(location, out blocks); int width = location.Exterior.ExteriorData.Width; int height = location.Exterior.ExteriorData.Height; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // Iterate through all buildings in this block int index = y * width + x; BuildingSummary[] buildingSummary = RMBLayout.GetBuildingData(blocks[index], x, y); for (int i = 0; i < buildingSummary.Length; i++) { // When enumAllValid is specified accept all valid building types bool forceAccept = false; if (buildingType == DFLocation.BuildingTypes.AllValid) { for (int j = 0; j < validBuildingTypes.Length; j++) { if (validBuildingTypes[j] == (int)buildingSummary[i].BuildingType) { forceAccept = true; break; } } } // Match building against required type if (buildingSummary[i].BuildingType == buildingType || forceAccept) { // Building must be a valid quest site QuestMarker[] questSpawnMarkers, questItemMarkers; EnumerateBuildingQuestMarkers(blocks[index], i, out questSpawnMarkers, out questItemMarkers); if (!ValidateQuestMarkers(questSpawnMarkers, questItemMarkers)) { continue; } // Get building name based on type string buildingName; if (RMBLayout.IsResidence(buildingType)) { // Generate a random surname for this residence DFRandom.srand(Time.renderedFrameCount); string surname = DaggerfallUnity.Instance.NameHelper.Surname(Utility.NameHelper.BankTypes.Breton); buildingName = HardStrings.theNamedResidence.Replace("%s", surname); } else { // Use fixed name buildingName = BuildingNames.GetName( buildingSummary[i].NameSeed, buildingSummary[i].BuildingType, buildingSummary[i].FactionId, location.Name, location.RegionName); } // Configure new site details SiteDetails site = new SiteDetails(); site.questUID = ParentQuest.UID; site.siteType = SiteTypes.Building; site.mapId = location.MapTableData.MapId; site.locationId = location.Exterior.ExteriorData.LocationId; site.regionName = location.RegionName; site.locationName = location.Name; site.buildingKey = buildingSummary[i].buildingKey; site.buildingName = buildingName; site.questSpawnMarkers = questSpawnMarkers; site.questItemMarkers = questItemMarkers; // Asssign markers only if available if (questSpawnMarkers != null) { siteDetails.selectedQuestSpawnMarker = UnityEngine.Random.Range(0, questSpawnMarkers.Length); } if (questItemMarkers != null) { siteDetails.selectedQuestItemMarker = UnityEngine.Random.Range(0, questItemMarkers.Length); } foundSites.Add(site); } } } } return(foundSites.ToArray()); }