void DisplaySaveCharacterGUI() { // Get character record List <SaveTreeBaseRecord> records = currentSaveTree.FindRecords(RecordTypes.Character); if (records.Count != 1) { return; } CharacterRecord characterRecord = (CharacterRecord)records[0]; //CharacterSheet characterSheet = characterRecord.ToCharacterSheet(); EditorGUILayout.Space(); GUILayoutHelper.Horizontal(() => { EditorGUILayout.LabelField(new GUIContent("Name"), GUILayout.Width(EditorGUIUtility.labelWidth - 4)); EditorGUILayout.SelectableLabel(characterRecord.ParsedData.characterName, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); }); GUILayoutHelper.Horizontal(() => { EditorGUILayout.LabelField(new GUIContent("Gender"), GUILayout.Width(EditorGUIUtility.labelWidth - 4)); EditorGUILayout.SelectableLabel(((int)characterRecord.ParsedData.gender).ToString(), EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); }); }
/// <summary> /// Assigns character items from classic save tree. /// </summary> public void AssignItems(SaveTree saveTree) { // Find character record, should always be a singleton CharacterRecord characterRecord = (CharacterRecord)saveTree.FindRecord(RecordTypes.Character); if (characterRecord == null) { return; } // Find all character-owned items List <SaveTreeBaseRecord> itemRecords = saveTree.FindRecords(RecordTypes.Item, characterRecord); // Filter for container-based inventory items List <SaveTreeBaseRecord> filteredRecords = saveTree.FilterRecordsByParentType(itemRecords, RecordTypes.Container); // Add interim Daggerfall Unity items foreach (var record in filteredRecords) { // Get container parent ContainerRecord containerRecord = (ContainerRecord)record.Parent; // Create item, grabbing trapped soul if needed DaggerfallUnityItem newItem = new DaggerfallUnityItem((ItemRecord)record); if (newItem.ItemGroup == ItemGroups.MiscItems && newItem.GroupIndex == 1) { if (record.Children.Count > 0) { TrappedSoulRecord soulRecord = (TrappedSoulRecord)record.Children[0]; newItem.TrappedSoulType = (MobileTypes)soulRecord.RecordRoot.SpriteIndex; } else { newItem.TrappedSoulType = MobileTypes.None; } } // Add to local inventory or wagon if (containerRecord.IsWagon) { wagonItems.AddItem(newItem); } else { items.AddItem(newItem); } // Equip to player if equipped in save for (int i = 0; i < characterRecord.ParsedData.equippedItems.Length; i++) { if (characterRecord.ParsedData.equippedItems[i] == record.RecordRoot.RecordID) { equipTable.EquipItem(newItem, true, false); } } } }
/// <summary> /// Assigns character items from classic save tree. /// </summary> public void AssignItems(SaveTree saveTree) { // Find character record, should always be a singleton CharacterRecord characterRecord = (CharacterRecord)saveTree.FindRecord(RecordTypes.Character); if (characterRecord == null) { return; } // Find all character-owned items List <SaveTreeBaseRecord> itemRecords = saveTree.FindRecords(RecordTypes.Item, characterRecord); // Filter for container-based inventory items List <SaveTreeBaseRecord> filteredRecords = saveTree.FilterRecordsByParentType(itemRecords, RecordTypes.Container); // Add interim Daggerfall Unity items foreach (var record in filteredRecords) { // Get container parent ContainerRecord containerRecord = (ContainerRecord)record.Parent; // Add to local inventory or wagon DaggerfallUnityItem newItem = new DaggerfallUnityItem((ItemRecord)record); if (containerRecord.IsWagon) { wagonItems.AddItem(newItem); } else { items.AddItem(newItem); } // Equip to player if equipped in save for (int i = 0; i < characterRecord.ParsedData.equippedItems.Length; i++) { if (characterRecord.ParsedData.equippedItems[i] == (record.RecordRoot.RecordID >> 8)) { equipTable.EquipItem(newItem); } } } }
void StartFromClassicSave() { DaggerfallUnity.ResetUID(); QuestMachine.Instance.ClearState(); RaiseOnNewGameEvent(); ResetWeaponManager(); // Save index must be in range if (classicSaveIndex < 0 || classicSaveIndex >= 6) { throw new IndexOutOfRangeException("classicSaveIndex out of range."); } // Open saves in parent path of Arena2 folder string path = SaveLoadManager.Instance.DaggerfallSavePath; SaveGames saveGames = new SaveGames(path); if (!saveGames.IsPathOpen) { throw new Exception(string.Format("Could not open Daggerfall saves path {0}", path)); } // Open save index if (!saveGames.TryOpenSave(classicSaveIndex)) { string error = string.Format("Could not open classic save index {0}.", classicSaveIndex); DaggerfallUI.MessageBox(error); DaggerfallUnity.LogMessage(string.Format(error), true); return; } // Get required save data SaveTree saveTree = saveGames.SaveTree; SaveVars saveVars = saveGames.SaveVars; SaveTreeBaseRecord positionRecord = saveTree.FindRecord(RecordTypes.CharacterPositionRecord); if (NoWorld) { playerEnterExit.DisableAllParents(); } else { // Set player to world position playerEnterExit.EnableExteriorParent(); StreamingWorld streamingWorld = FindStreamingWorld(); int worldX = positionRecord.RecordRoot.Position.WorldX; int worldZ = positionRecord.RecordRoot.Position.WorldZ; streamingWorld.TeleportToWorldCoordinates(worldX, worldZ); streamingWorld.suppressWorld = false; } GameObject cameraObject = GameObject.FindGameObjectWithTag("MainCamera"); PlayerMouseLook mouseLook = cameraObject.GetComponent <PlayerMouseLook>(); if (mouseLook) { // Classic save value ranges from -256 (looking up) to 256 (looking down). // The maximum up and down range of view in classic is similar to 45 degrees up and down in DF Unity. float pitch = positionRecord.RecordRoot.Pitch; if (pitch != 0) { pitch = (pitch * 45 / 256); } mouseLook.Pitch = pitch; float yaw = positionRecord.RecordRoot.Yaw; // In classic saves 2048 units of yaw is 360 degrees. if (yaw != 0) { yaw = (yaw * 360 / 2048); } mouseLook.Yaw = yaw; } // Set whether the player's weapon is drawn WeaponManager weaponManager = GameManager.Instance.WeaponManager; weaponManager.Sheathed = (!saveVars.WeaponDrawn); // Set game time DaggerfallUnity.Instance.WorldTime.Now.FromClassicDaggerfallTime(saveVars.GameTime); // Get character record List <SaveTreeBaseRecord> records = saveTree.FindRecords(RecordTypes.Character); if (records.Count != 1) { throw new Exception("SaveTree CharacterRecord not found."); } // Get prototypical character document data CharacterRecord characterRecord = (CharacterRecord)records[0]; characterDocument = characterRecord.ToCharacterDocument(); // Assign data to player entity PlayerEntity playerEntity = FindPlayerEntity(); playerEntity.AssignCharacter(characterDocument, characterRecord.ParsedData.level, characterRecord.ParsedData.maxHealth, false); // Assign biography modifiers playerEntity.BiographyResistDiseaseMod = saveVars.BiographyResistDiseaseMod; playerEntity.BiographyResistMagicMod = saveVars.BiographyResistMagicMod; playerEntity.BiographyAvoidHitMod = saveVars.BiographyAvoidHitMod; playerEntity.BiographyResistPoisonMod = saveVars.BiographyResistPoisonMod; playerEntity.BiographyFatigueMod = saveVars.BiographyFatigueMod; // Assign faction data playerEntity.FactionData.ImportClassicReputation(saveVars); // Assign global variables playerEntity.GlobalVars.ImportClassicGlobalVars(saveVars); // Set time of last check for raising skills playerEntity.TimeOfLastSkillIncreaseCheck = saveVars.LastSkillCheckTime; // Assign items to player entity playerEntity.AssignItems(saveTree); // Assign guild memberships playerEntity.AssignGuildMemberships(saveTree); // Assign diseases and poisons to player entity playerEntity.AssignDiseasesAndPoisons(saveTree); // Assign gold pieces playerEntity.GoldPieces = (int)characterRecord.ParsedData.physicalGold; // Assign weapon hand being used weaponManager.UsingRightHand = !saveVars.UsingLeftHandWeapon; // GodMode setting playerEntity.GodMode = saveVars.GodMode; // Setup bank accounts var bankRecords = saveTree.FindRecord(RecordTypes.BankAccount); Banking.DaggerfallBankManager.ReadNativeBankData(bankRecords); // Get regional data. playerEntity.RegionData = saveVars.RegionData; // Set time tracked by playerEntity for game minute-based updates playerEntity.LastGameMinutes = saveVars.GameTime; // Get breath remaining if player was submerged (0 if they were not in the water) playerEntity.CurrentBreath = saveVars.BreathRemaining; // TODO: Import classic spellbook playerEntity.DeserializeSpellbook(null); // Get last type of crime committed playerEntity.CrimeCommitted = (PlayerEntity.Crimes)saveVars.CrimeCommitted; // Get weather byte[] climateWeathers = saveVars.ClimateWeathers; // Enums for thunder and snow are reversed in classic and Unity, so they are converted here. for (int i = 0; i < climateWeathers.Length; i++) { // TODO: 0x80 flag can be set for snow or rain, to add fog to these weathers. This isn't in DF Unity yet, so // temporarily removing the flag. climateWeathers[i] &= 0x7f; if (climateWeathers[i] == 5) { climateWeathers[i] = 6; } else if (climateWeathers[i] == 6) { climateWeathers[i] = 5; } } GameManager.Instance.WeatherManager.PlayerWeather.ClimateWeathers = climateWeathers; // Load character biography text playerEntity.BackStory = saveGames.BioFile.Lines; // Validate spellbook item DaggerfallUnity.Instance.ItemHelper.ValidateSpellbookItem(playerEntity); // Start game DaggerfallUI.Instance.PopToHUD(); GameManager.Instance.PauseGame(false); DaggerfallUI.Instance.FadeBehaviour.FadeHUDFromBlack(); DaggerfallUI.PostMessage(PostStartMessage); lastStartMethod = StartMethods.LoadClassicSave; SaveIndex = -1; if (OnStartGame != null) { OnStartGame(this, null); } }
void OnGUI() { if (!IsReady()) { EditorGUILayout.HelpBox("DaggerfallUnity instance not ready. Have you set your Arena2 path?", MessageType.Info); return; } if (selectedSave != lastSelectedSave || currentSaveTree == null) { currentSaveTree = saveTrees[selectedSave]; currentSaveVars = saveVars[selectedSave]; if (currentSaveTree == null || currentSaveVars == null) { return; } currentItems = currentSaveTree.FindRecords(RecordTypes.Item).ToArray(); // Merge savetree faction data factionDict = factionFile.Merge(currentSaveVars); lastSelectedSave = selectedSave; } if (saveTrees != null && saveTrees.Length > 0) { DisplaySaveSelectGUI(); DisplaySaveImageGUI(); DisplaySaveStatsGUI(); DisplaySaveCharacterGUI(); scrollPos = GUILayoutHelper.ScrollView(scrollPos, () => { EditorGUILayout.Space(); showFactionsFoldout = GUILayoutHelper.Foldout(showFactionsFoldout, new GUIContent("Factions"), () => { GUILayoutHelper.Indent(() => { DisplayFactionsFoldout(); }); }); EditorGUILayout.Space(); showItemsFoldout = GUILayoutHelper.Foldout(showItemsFoldout, new GUIContent("Items"), () => { GUILayoutHelper.Indent(() => { DisplayItemsFoldout(); }); }); EditorGUILayout.Space(); showSaveTreeFoldout = GUILayoutHelper.Foldout(showSaveTreeFoldout, new GUIContent("SaveTree"), () => { EditorGUILayout.HelpBox("Temporarily Filtering out records of type Door and UnknownItemRecord to keep list manageable.", MessageType.Info); DisplaySaveTree(currentSaveTree.RootRecord); }); }); } }
void StartFromClassicSave() { DaggerfallUnity.ResetUID(); RaiseOnNewGameEvent(); ResetWeaponManager(); // Save index must be in range if (classicSaveIndex < 0 || classicSaveIndex >= 6) { throw new IndexOutOfRangeException("classicSaveIndex out of range."); } // Open saves in parent path of Arena2 folder string path = SaveLoadManager.Instance.DaggerfallSavePath; SaveGames saveGames = new SaveGames(path); if (!saveGames.IsPathOpen) { throw new Exception(string.Format("Could not open Daggerfall saves path {0}", path)); } // Open save index if (!saveGames.TryOpenSave(classicSaveIndex)) { string error = string.Format("Could not open classic save index {0}.", classicSaveIndex); DaggerfallUI.MessageBox(error); DaggerfallUnity.LogMessage(string.Format(error), true); return; } // Get required save data SaveTree saveTree = saveGames.SaveTree; SaveVars saveVars = saveGames.SaveVars; if (NoWorld) { playerEnterExit.DisableAllParents(); } else { // Set player to world position playerEnterExit.EnableExteriorParent(); StreamingWorld streamingWorld = FindStreamingWorld(); int worldX = saveTree.Header.CharacterPosition.Position.WorldX; int worldZ = saveTree.Header.CharacterPosition.Position.WorldZ; streamingWorld.TeleportToWorldCoordinates(worldX, worldZ); streamingWorld.suppressWorld = false; } // Set game time DaggerfallUnity.Instance.WorldTime.Now.FromClassicDaggerfallTime(saveVars.GameTime); // Get character record List <SaveTreeBaseRecord> records = saveTree.FindRecords(RecordTypes.Character); if (records.Count != 1) { throw new Exception("SaveTree CharacterRecord not found."); } // Get prototypical character document data CharacterRecord characterRecord = (CharacterRecord)records[0]; characterDocument = characterRecord.ToCharacterDocument(); // Assign data to player entity PlayerEntity playerEntity = FindPlayerEntity(); playerEntity.AssignCharacter(characterDocument, characterRecord.ParsedData.level, characterRecord.ParsedData.startingHealth); // Assign items to player entity playerEntity.AssignItems(saveTree); // Assign gold pieces playerEntity.GoldPieces = (int)characterRecord.ParsedData.physicalGold; // Start game DaggerfallUI.Instance.PopToHUD(); GameManager.Instance.PauseGame(false); DaggerfallUI.Instance.FadeHUDFromBlack(); DaggerfallUI.PostMessage(PostStartMessage); if (OnStartGame != null) { OnStartGame(this, null); } }
/// <summary> /// Assigns character items from classic save tree. /// </summary> public void AssignItems(SaveTree saveTree) { // Find character record, should always be a singleton CharacterRecord characterRecord = (CharacterRecord)saveTree.FindRecord(RecordTypes.Character); if (characterRecord == null) { return; } // Find all character-owned items List <SaveTreeBaseRecord> itemRecords = saveTree.FindRecords(RecordTypes.Item, characterRecord); // Filter for container-based inventory items List <SaveTreeBaseRecord> filteredRecords = saveTree.FilterRecordsByParentType(itemRecords, RecordTypes.Container); // Add interim Daggerfall Unity items foreach (var record in filteredRecords) { // Get container parent ContainerRecord containerRecord = (ContainerRecord)record.Parent; // Some (most likely hacked) classic items have 0 or 65535 in image data bitfield // Discard these items as they will likely have other bad attributes such as an impossible weight // The goal here is just to prevent game from crashing due to bad item data if ((record as ItemRecord).ParsedData.image1 == 0 || (record as ItemRecord).ParsedData.image1 == 0xffff) { continue; } // Create item, grabbing trapped soul if needed DaggerfallUnityItem newItem = new DaggerfallUnityItem((ItemRecord)record); if (newItem.ItemGroup == ItemGroups.MiscItems && newItem.GroupIndex == 1) { if (record.Children.Count > 0) { TrappedSoulRecord soulRecord = (TrappedSoulRecord)record.Children[0]; newItem.TrappedSoulType = (MobileTypes)soulRecord.RecordRoot.SpriteIndex; } else { newItem.TrappedSoulType = MobileTypes.None; } } // Add to local inventory or wagon if (containerRecord.IsWagon) { wagonItems.AddItem(newItem); } else { items.AddItem(newItem); } // Equip to player if equipped in save for (int i = 0; i < characterRecord.ParsedData.equippedItems.Length; i++) { if (characterRecord.ParsedData.equippedItems[i] == record.RecordRoot.RecordID) { equipTable.EquipItem(newItem, true, false); } } } }
void StartFromClassicSave() { DaggerfallUnity.ResetUID(); QuestMachine.Instance.ClearState(); RaiseOnNewGameEvent(); ResetWeaponManager(); // Save index must be in range if (classicSaveIndex < 0 || classicSaveIndex >= 6) { throw new IndexOutOfRangeException("classicSaveIndex out of range."); } // Open saves in parent path of Arena2 folder string path = SaveLoadManager.Instance.DaggerfallSavePath; SaveGames saveGames = new SaveGames(path); if (!saveGames.IsPathOpen) { throw new Exception(string.Format("Could not open Daggerfall saves path {0}", path)); } // Open save index if (!saveGames.TryOpenSave(classicSaveIndex)) { string error = string.Format("Could not open classic save index {0}.", classicSaveIndex); DaggerfallUI.MessageBox(error); DaggerfallUnity.LogMessage(string.Format(error), true); return; } // Get required save data SaveTree saveTree = saveGames.SaveTree; SaveVars saveVars = saveGames.SaveVars; SaveTreeBaseRecord positionRecord = saveTree.FindRecord(RecordTypes.CharacterPositionRecord); if (NoWorld) { playerEnterExit.DisableAllParents(); } else { // Set player to world position playerEnterExit.EnableExteriorParent(); StreamingWorld streamingWorld = FindStreamingWorld(); int worldX = positionRecord.RecordRoot.Position.WorldX; int worldZ = positionRecord.RecordRoot.Position.WorldZ; streamingWorld.TeleportToWorldCoordinates(worldX, worldZ); streamingWorld.suppressWorld = false; } GameObject cameraObject = GameObject.FindGameObjectWithTag("MainCamera"); PlayerMouseLook mouseLook = cameraObject.GetComponent <PlayerMouseLook>(); if (mouseLook) { // Classic save value ranges from -256 (looking up) to 256 (looking down). // The maximum up and down range of view in classic is similar to 45 degrees up and down in DF Unity. float pitch = positionRecord.RecordRoot.Pitch; if (pitch != 0) { pitch = (pitch * 45 / 256); } mouseLook.Pitch = pitch; float yaw = positionRecord.RecordRoot.Yaw; // In classic saves 2048 units of yaw is 360 degrees. if (yaw != 0) { yaw = (yaw * 360 / 2048); } mouseLook.Yaw = yaw; } // Set whether the player's weapon is drawn GameManager.Instance.WeaponManager.Sheathed = (!saveVars.WeaponDrawn); // Set game time DaggerfallUnity.Instance.WorldTime.Now.FromClassicDaggerfallTime(saveVars.GameTime); // Get character record List <SaveTreeBaseRecord> records = saveTree.FindRecords(RecordTypes.Character); if (records.Count != 1) { throw new Exception("SaveTree CharacterRecord not found."); } // Get prototypical character document data CharacterRecord characterRecord = (CharacterRecord)records[0]; characterDocument = characterRecord.ToCharacterDocument(); // Assign data to player entity PlayerEntity playerEntity = FindPlayerEntity(); playerEntity.AssignCharacter(characterDocument, characterRecord.ParsedData.level, characterRecord.ParsedData.maxHealth, false); // Assign biography modifiers playerEntity.BiographyResistDiseaseMod = saveVars.BiographyResistDiseaseMod; playerEntity.BiographyResistMagicMod = saveVars.BiographyResistMagicMod; playerEntity.BiographyAvoidHitMod = saveVars.BiographyAvoidHitMod; playerEntity.BiographyResistPoisonMod = saveVars.BiographyResistPoisonMod; playerEntity.BiographyFatigueMod = saveVars.BiographyFatigueMod; // Assign faction data playerEntity.FactionData.ImportClassicReputation(saveVars); // Assign global variables playerEntity.GlobalVars.ImportClassicGlobalVars(saveVars); // Set time of last check for raising skills playerEntity.TimeOfLastSkillIncreaseCheck = saveVars.LastSkillCheckTime; // Assign items to player entity playerEntity.AssignItems(saveTree); // Assign gold pieces playerEntity.GoldPieces = (int)characterRecord.ParsedData.physicalGold; // GodMode setting playerEntity.GodMode = saveVars.GodMode; // Setup bank accounts var bankRecords = saveTree.FindRecord(RecordTypes.BankAccount); Banking.DaggerfallBankManager.ReadNativeBankData(bankRecords); // Get regional data. playerEntity.RegionData = saveVars.RegionData; // Set time tracked by playerEntity for game minute-based updates playerEntity.LastGameMinutes = saveVars.GameTime; // Start game DaggerfallUI.Instance.PopToHUD(); GameManager.Instance.PauseGame(false); DaggerfallUI.Instance.FadeHUDFromBlack(); DaggerfallUI.PostMessage(PostStartMessage); lastStartMethod = StartMethods.LoadClassicSave; SaveIndex = -1; if (OnStartGame != null) { OnStartGame(this, null); } }