/// <summary> /// saves discovery state to object automapGeometryDungeonState /// this class is mapping the hierarchy inside the GameObject gameObjectGeometry in such way /// that the MeshRenderer enabled state for objects in the 4th hierarchy level (which are the actual models) /// is matching value of field "discovered" in AutomapGeometryDungeonState.AutomapGeometryBlockState.AutomapGeometryBlockElementState.AutomapGeometryModelState /// dictionary of dungeon states of visited dungeons is then updated (which is used for save game mechanism) /// </summary> private void saveStateAutomapDungeon(bool forceSaveOfDungeonDiscoveryState) { if ((numberOfDungeonMemorized == 0)&&(!GameManager.Instance.IsPlayerInside)) // if discovery state of no dungeon has to be remembered, clear dictionary and skip the rest of this function { dictAutomapDungeonsDiscoveryState.Clear(); return; } if ((!GameManager.Instance.IsPlayerInside)&&(!forceSaveOfDungeonDiscoveryState)) // if player is outside just skip this function { return; } int updatedNumberOfDungeonMemorized = numberOfDungeonMemorized; if ((numberOfDungeonMemorized == 0) && (GameManager.Instance.IsPlayerInside)) { updatedNumberOfDungeonMemorized = 1; } Transform gameObjectGeometryDungeon = gameobjectGeometry.transform.GetChild(0); automapGeometryDungeonState = new AutomapGeometryDungeonState(); automapGeometryDungeonState.locationName = gameObjectGeometryDungeon.name; automapGeometryDungeonState.entranceDiscovered = ((gameobjectBeaconEntrancePosition) && (gameobjectBeaconEntrancePosition.activeSelf)); // get entrance marker discovery state automapGeometryDungeonState.timeInSecondsLastVisited = DaggerfallUnity.Instance.WorldTime.DaggerfallDateTime.ToSeconds(); automapGeometryDungeonState.blocks = new List<AutomapGeometryBlockState>(); foreach (Transform currentBlock in gameObjectGeometryDungeon.transform) { AutomapGeometryBlockState automapGeometryBlockState = new AutomapGeometryBlockState(); automapGeometryBlockState.blockName = currentBlock.name; List<AutomapGeometryBlockElementState> blockElements = new List<AutomapGeometryBlockElementState>(); foreach (Transform currentTransformModel in currentBlock.transform) { AutomapGeometryBlockElementState blockElement = new AutomapGeometryBlockElementState(); List<AutomapGeometryModelState> models = new List<AutomapGeometryModelState>(); foreach (Transform currentTransformMesh in currentTransformModel.transform) { AutomapGeometryModelState model = new AutomapGeometryModelState(); MeshRenderer meshRenderer = currentTransformMesh.GetComponent<MeshRenderer>(); if ((meshRenderer) && (meshRenderer.enabled)) { model.discovered = true; model.visitedInThisRun = !meshRenderer.materials[0].IsKeywordEnabled("RENDER_IN_GRAYSCALE"); // all materials of model have the same setting - so just material[0] is tested } else { model.discovered = false; model.visitedInThisRun = false; } models.Add(model); } blockElement.models = models; blockElements.Add(blockElement); } automapGeometryBlockState.blockElements = blockElements; automapGeometryDungeonState.blocks.Add(automapGeometryBlockState); } // replace or add discovery state for current dungeon DFLocation dfLocation = GameManager.Instance.PlayerGPS.CurrentLocation; string locationStringIdentifier = string.Format("{0}/{1}", dfLocation.RegionName, dfLocation.Name); if (dictAutomapDungeonsDiscoveryState.ContainsKey(locationStringIdentifier)) { dictAutomapDungeonsDiscoveryState[locationStringIdentifier] = automapGeometryDungeonState; } else { dictAutomapDungeonsDiscoveryState.Add(locationStringIdentifier, automapGeometryDungeonState); } // make list out of dictionary and sort by last time visited - then get rid of dungeons in dictionary that weren't visited lately List<KeyValuePair<string, AutomapGeometryDungeonState>> sortedList = new List<KeyValuePair<string, AutomapGeometryDungeonState>>(dictAutomapDungeonsDiscoveryState); sortedList.Sort( delegate (KeyValuePair<string, AutomapGeometryDungeonState> firstPair, KeyValuePair<string, AutomapGeometryDungeonState> nextPair) { return nextPair.Value.timeInSecondsLastVisited.CompareTo(firstPair.Value.timeInSecondsLastVisited); } ); //if there are more dungeons remembered than allowed - get rid of dungeons in dictionary that weren't visited lately if (sortedList.Count > updatedNumberOfDungeonMemorized) { ulong timeInSecondsLimit = sortedList[updatedNumberOfDungeonMemorized - 1].Value.timeInSecondsLastVisited; foreach (KeyValuePair<string, AutomapGeometryDungeonState> entry in sortedList) // use sorted list and iterate over it - remove elements of dictionary { if (entry.Value.timeInSecondsLastVisited < timeInSecondsLimit) { dictAutomapDungeonsDiscoveryState.Remove(entry.Key); // remove this dungeon's entry from dictionary } } } }
void updateMeshRendererDungeonState(ref MeshRenderer meshRenderer, AutomapGeometryDungeonState automapGeometryDungeonState, int indexBlock, int indexElement, int indexModel, bool forceNotVisitedInThisRun) { if (automapGeometryDungeonState.blocks[indexBlock].blockElements[indexElement].models[indexModel].discovered == true) { meshRenderer.enabled = true; if ((!forceNotVisitedInThisRun)&&(automapGeometryDungeonState.blocks[indexBlock].blockElements[indexElement].models[indexModel].visitedInThisRun)) { Material[] materials = meshRenderer.materials; foreach (Material mat in meshRenderer.materials) { mat.DisableKeyword("RENDER_IN_GRAYSCALE"); } meshRenderer.materials = materials; } else { Material[] materials = meshRenderer.materials; foreach (Material mat in meshRenderer.materials) { mat.EnableKeyword("RENDER_IN_GRAYSCALE"); } meshRenderer.materials = materials; } } else { meshRenderer.enabled = false; } }
/// <summary> /// restores discovery state from automapGeometryDungeonState onto gameobjectGeometry /// automapGeometryDungeonState is loaded from dictionary of dungeon states of visited dungeons /// this class is mapping the value of field "discovered" (AutomapGeometryDungeonState.AutomapGeometryBlockState.AutomapGeometryBlockElementState.AutomapGeometryModelState) /// inside object automapGeometryDungeonState to the objects inside the 4th hierarchy level of GameObject gameObjectGeometry (which are the actual models) /// in such way that the MeshRenderer enabled state for these objects match the value of field "discovered" /// </summary> /// <param name="forceNotVisitedInThisRun"> if set to true geometry is restored and its state is forced to not being visited in this run </param> private void restoreStateAutomapDungeon(bool forceNotVisitedInThisRun = false) { Transform location = gameobjectGeometry.transform.GetChild(0); HideAll(); // clear discovery state of geometry as initial starting point DFLocation dfLocation = GameManager.Instance.PlayerGPS.CurrentLocation; string locationStringIdentifier = string.Format("{0}/{1}", dfLocation.RegionName, dfLocation.Name); if (dictAutomapDungeonsDiscoveryState.ContainsKey(locationStringIdentifier)) { automapGeometryDungeonState = dictAutomapDungeonsDiscoveryState[locationStringIdentifier]; } else { automapGeometryDungeonState = null; } if (automapGeometryDungeonState == null) return; gameobjectBeaconEntrancePosition.SetActive(automapGeometryDungeonState.entranceDiscovered); // set entrance marker discovery state if (location.name != automapGeometryDungeonState.locationName) return; for (int indexBlock = 0; indexBlock < location.childCount; indexBlock++) { Transform currentBlock = location.GetChild(indexBlock); if (currentBlock.name != automapGeometryDungeonState.blocks[indexBlock].blockName) return; for (int indexElement = 0; indexElement < currentBlock.childCount; indexElement++) { Transform currentTransformElement = currentBlock.GetChild(indexElement); for (int indexModel = 0; indexModel < currentTransformElement.childCount; indexModel++) { Transform currentTransformModel = currentTransformElement.GetChild(indexModel); MeshRenderer meshRenderer = currentTransformModel.GetComponent<MeshRenderer>(); if (meshRenderer) { updateMeshRendererDungeonState(ref meshRenderer, automapGeometryDungeonState, indexBlock, indexElement, indexModel, forceNotVisitedInThisRun); } } } } }