// Construct with data from the quest, pass Game for speed public Tile(QuestData.Tile questTile, Game gameObject) : base(gameObject) { qTile = questTile; // Search for tile in content if (game.cd.tileSides.ContainsKey(qTile.tileSideName)) { cTile = game.cd.tileSides[qTile.tileSideName]; } else if (game.cd.tileSides.ContainsKey("TileSide" + qTile.tileSideName)) { cTile = game.cd.tileSides["TileSide" + qTile.tileSideName]; } else { // Fatal if not found ValkyrieDebug.Log("Error: Failed to located TileSide: " + qTile.tileSideName + " in quest component: " + qTile.sectionName); Application.Quit(); } // Attempt to load image Texture2D newTex = ContentData.FileToTexture(game.cd.tileSides[qTile.tileSideName].image); if (newTex == null) { // Fatal if missing ValkyrieDebug.Log("Error: cannot open image file for TileSide: " + game.cd.tileSides[qTile.tileSideName].image); Application.Quit(); } // Create a unity object for the tile unityObject = new GameObject("Object" + qTile.sectionName); unityObject.tag = "board"; unityObject.transform.parent = game.boardCanvas.transform; // Add image to object image = unityObject.AddComponent <UnityEngine.UI.Image>(); // Create sprite from texture Sprite tileSprite = Sprite.Create(newTex, new Rect(0, 0, newTex.width, newTex.height), Vector2.zero, 1); // Set image sprite image.sprite = tileSprite; // Move to get the top left square corner at 0,0 float vPPS = game.cd.tileSides[qTile.tileSideName].pxPerSquare; float hPPS = vPPS; // manual aspect control // We need this for the 3x2 MoM tiles because they don't have square pixels!! if (game.cd.tileSides[qTile.tileSideName].aspect != 0) { hPPS = (vPPS * newTex.width / newTex.height) / game.cd.tileSides[qTile.tileSideName].aspect; } // Perform alignment move unityObject.transform.Translate(Vector3.right * ((newTex.width / 2) - cTile.left) / hPPS, Space.World); unityObject.transform.Translate(Vector3.down * ((newTex.height / 2) - cTile.top) / vPPS, Space.World); // Move to get the middle of the top left square at 0,0 // We don't do this for MoM because it spaces differently if (game.gameType.TileOnGrid()) { unityObject.transform.Translate(new Vector3(-(float)0.5, (float)0.5, 0), Space.World); } // Set the size to the image size image.rectTransform.sizeDelta = new Vector2((float)newTex.width / hPPS, (float)newTex.height / vPPS); // Rotate around 0,0 rotation amount unityObject.transform.RotateAround(Vector3.zero, Vector3.forward, qTile.rotation); // Move tile into target location (Space.World is needed because tile has been rotated) unityObject.transform.Translate(new Vector3(qTile.location.x, qTile.location.y, 0), Space.World); image.color = new Color(1, 1, 1, 0); }
// Load a saved game, does nothing if file does not exist public static void Load() { Game game = Game.Get(); try { if (File.Exists(SaveFile())) { if (!Directory.Exists(Path.GetTempPath() + "/Valkyrie")) { Directory.CreateDirectory(Path.GetTempPath() + "/Valkyrie"); } if (!Directory.Exists(Path.GetTempPath() + "/Valkyrie/Load")) { Directory.CreateDirectory(Path.GetTempPath() + "/Valkyrie/Load"); } ZipFile zip = ZipFile.Read(SaveFile()); zip.ExtractAll(Path.GetTempPath() + "/Valkyrie/Load"); // Check that quest in save is valid QuestData.Quest q = new QuestData.Quest(Path.GetTempPath() + "/Valkyrie/Load/quest"); if (!q.valid) { ValkyrieDebug.Log("Error: save contains unsupported quest version." + System.Environment.NewLine); Destroyer.MainMenu(); } string data = File.ReadAllText(Path.GetTempPath() + "/Valkyrie/Load/save.ini"); IniData saveData = IniRead.ReadFromString(data); saveData.data["Quest"]["path"] = Path.GetTempPath() + "/Valkyrie/Load/quest/quest.ini"; saveData.Get("Quest", "valkyrie"); if (FetchContent.VersionNewer(game.version, saveData.Get("Quest", "valkyrie"))) { ValkyrieDebug.Log("Error: save is from a future version." + System.Environment.NewLine); Destroyer.MainMenu(); return; } if (!FetchContent.VersionNewerOrEqual(minValkyieVersion, saveData.Get("Quest", "valkyrie"))) { ValkyrieDebug.Log("Error: save is from an old unsupported version." + System.Environment.NewLine); Destroyer.MainMenu(); return; } Destroyer.Dialog(); // Restart contend data so we can select from save game.cd = new ContentData(game.gameType.DataDirectory()); // Check if we found anything if (game.cd.GetPacks().Count == 0) { ValkyrieDebug.Log("Error: Failed to find any content packs, please check that you have them present in: " + game.gameType.DataDirectory() + System.Environment.NewLine); Application.Quit(); } game.cd.LoadContentID(""); // Load the base content // Load content that the save game uses Dictionary <string, string> packs = saveData.Get("Packs"); foreach (KeyValuePair <string, string> kv in packs) { game.cd.LoadContentID(""); game.cd.LoadContentID(kv.Key); } // This loads the game new Quest(saveData); // Draw things on the screen game.heroCanvas.SetupUI(); game.heroCanvas.UpdateImages(); game.heroCanvas.UpdateStatus(); if (game.gameType.DisplayMorale()) { game.moraleDisplay = new MoraleDisplay(); } if (!game.gameType.DisplayHeroes()) { game.heroCanvas.Clean(); } // Create the menu button new MenuButton(); new LogButton(); game.stageUI = new NextStageButton(); } } catch (System.Exception) { ValkyrieDebug.Log("Error: Unable to open save file: " + SaveFile()); Application.Quit(); } }
// Event ended public void EndEvent(QuestData.Event eventData, int state = 0) { // Get list of next events List <string> eventList = new List <string>(); if (eventData.nextEvent.Count > state) { eventList = eventData.nextEvent[state]; } // Only take enabled events from list List <string> enabledEvents = new List <string>(); foreach (string s in eventList) { // Check if the event doesn't exists - quest fault if (!events.ContainsKey(s)) { string questToTransition = game.quest.originalPath + Path.DirectorySeparatorChar + s; if (game.quest.fromSavegame) { questToTransition = ContentData.ValkyrieLoadQuestPath + Path.DirectorySeparatorChar + s; } if (File.Exists(questToTransition)) { events.Add(s, new StartQuestEvent(s)); enabledEvents.Add(s); } else { ValkyrieDebug.Log("Warning: Missing event called: " + s); game.quest.log.Add(new Quest.LogEntry("Warning: Missing event called: " + s, true)); } } else if (!game.quest.eManager.events[s].Disabled()) { enabledEvents.Add(s); } } // Has the quest ended? if (game.quest.vars.GetValue("$end") != 0) { game.quest.questHasEnded = true; if (Path.GetFileName(game.quest.originalPath).StartsWith("EditorScenario") || !Path.GetFileName(game.quest.originalPath).EndsWith(".valkyrie")) { // do not show score screen for scenario with a non customized name, or if the scenario is not a package (most probably a test) Destroyer.MainMenu(); } else { new EndGameScreen(); } return; } currentEvent = null; // Are there any events? if (enabledEvents.Count > 0) { // Are we picking at random? if (eventData.randomEvents) { // Add a random event game.quest.eManager.QueueEvent(enabledEvents[UnityEngine.Random.Range(0, enabledEvents.Count)], false); } else { // Add the first valid event game.quest.eManager.QueueEvent(enabledEvents[0], false); } } // Add any custom triggered events AddCustomTriggers(); if (eventStack.Count == 0) { monsterImage = null; monsterHealth = false; if (game.quest.phase == Quest.MoMPhase.monsters) { game.roundControl.MonsterActivated(); return; } } // Trigger a stacked event TriggerEvent(); }
private static Texture2D PvrToTexture(string file) { if (file == null) { throw new ArgumentNullException("file"); } long pixelformat = -1; try { string imagePath = new Uri(file).AbsoluteUri; var www = new WWW(imagePath); // *** HEADER **** // int verison // int flags pixelformat = BitConverter.ToInt64(www.bytes, 8); // int color space // int channel type int height = BitConverter.ToInt32(www.bytes, 24); int width = BitConverter.ToInt32(www.bytes, 28); // int depth // int num surfaces // int num faces // int mip map count // int meta data size // *** IMAGE DATA **** const int PVR_HEADER_SIZE = 52; var image = new byte[www.bytesDownloaded - PVR_HEADER_SIZE]; Buffer.BlockCopy(www.bytes, PVR_HEADER_SIZE, image, 0, www.bytesDownloaded - PVR_HEADER_SIZE); Texture2D texture = null; switch (pixelformat) { case 22: // ETC2_RGB4 texture = new Texture2D(width, height, TextureFormat.ETC2_RGB, false, true); texture.LoadRawTextureData(image); texture.Apply(); break; case 23: // ETC2_RGB8 texture = new Texture2D(width, height, TextureFormat.ETC2_RGBA8, false, true); texture.LoadRawTextureData(image); texture.Apply(); break; default: ValkyrieDebug.Log("Warning: PVR unknown pixelformat: '" + pixelformat + "' in file: '" + file + "'"); break; } return(texture); } catch (Exception ex) { if (!File.Exists(file)) { ValkyrieDebug.Log("Warning: PVR Image missing: '" + file + "'"); } else { ValkyrieDebug.Log("Warning: PVR Image loading of file '" + file + "' failed with " + ex.GetType().Name + " message: " + ex.Message + " pixelformat: '" + pixelformat + "'"); } return(null); } }
// Save the quest public static void Save() { Game game = Game.Get(); // Add a comment at the start of the quest with the editor version StringBuilder questData = new StringBuilder() .Append("; Saved by version: ") .AppendLine(game.version); // Save quest meta content to a string questData.AppendLine(game.quest.qd.quest.ToString()); // Write to disk try { // first we serialize dictionary to know the available languages if (LocalizationRead.selectDictionary("qst") != null) { Dictionary <string, List <string> > localization_files = LocalizationRead.dicts["qst"].SerializeMultiple(); // Append to the end of the content file the languages files questData.AppendLine().AppendLine("[QuestText]"); foreach (string language in localization_files.Keys) { questData.AppendLine("Localization." + language + ".txt"); File.WriteAllText( Path.GetDirectoryName(game.quest.qd.questPath) + "/Localization." + language + ".txt", string.Join(System.Environment.NewLine, localization_files[language].ToArray())); } questData.AppendLine(); } } catch (System.Exception) { ValkyrieDebug.Log("Error: Failed to save quest in editor."); Application.Quit(); } questData.AppendLine("[QuestData]"); Dictionary <string, StringBuilder> fileData = new Dictionary <string, StringBuilder>(); foreach (QuestData.QuestComponent qc in game.quest.qd.components.Values) { string source = qc.source; if (source.Length == 0) { source = "quest.ini"; } if (!fileData.ContainsKey(source)) { StringBuilder thisFile = new StringBuilder(); if (!source.Equals("quest.ini")) { thisFile.Append("; Saved by version: ").AppendLine(game.version); questData.AppendLine(source); } fileData.Add(source, thisFile); } if (!(qc is PerilData)) { fileData[source].AppendLine().Append(qc); } } if (fileData.ContainsKey("quest.ini")) { fileData["quest.ini"] = questData.Append(fileData["quest.ini"]); } else { fileData.Add("quest.ini", questData); } foreach (KeyValuePair <string, StringBuilder> kv in fileData) { string outFile = Path.Combine(Path.GetDirectoryName(game.quest.qd.questPath), kv.Key); // Write to disk try { Directory.CreateDirectory(Path.GetDirectoryName(outFile)); File.WriteAllText(outFile, kv.Value.ToString()); } catch (System.Exception) { ValkyrieDebug.Log("Error: Failed to write to " + outFile + ", components lost"); Application.Quit(); } } Destroyer.Dialog(); }
// Create a new quest public void NewQuest() { Game game = Game.Get(); string dataLocation = Game.AppData() + Path.DirectorySeparatorChar + Game.Get().gameType.TypeName() + "/Editor"; if (!Directory.Exists(dataLocation)) { Directory.CreateDirectory(dataLocation); } // Find an available unique directory name int i = 1; while (Directory.Exists(dataLocation + "/Editor" + game.gameType.QuestName().Translate() + i)) { i++; } string targetLocation = dataLocation + "/Editor" + game.gameType.QuestName().Translate() + i; try { Directory.CreateDirectory(targetLocation); List <string> questData = new List <string>(); // Create basic quest info questData.Add("[Quest]"); questData.Add("type=" + game.gameType.TypeName()); questData.Add("format=" + QuestData.Quest.currentFormat); questData.Add("defaultlanguage=" + game.currentLang); questData.Add(""); questData.Add("[QuestText]"); questData.Add("Localization." + game.currentLang + ".txt"); // Write quest file File.WriteAllLines(targetLocation + "/quest.ini", questData.ToArray()); // Create new dictionary DictionaryI18n newScenarioDict = new DictionaryI18n(new string[1] { ".," + game.currentLang }, game.currentLang); // Add quest name to dictionary newScenarioDict.AddEntry("quest.name", game.gameType.QuestName().Translate() + " " + i); // Add quest description to dictionary newScenarioDict.AddEntry("quest.description", game.gameType.QuestName().Translate() + " " + i + "..."); // Generate localization file Dictionary <string, List <string> > localization_files = newScenarioDict.SerializeMultiple(); foreach (string oneLang in localization_files.Keys) { // Write localization file File.WriteAllText( targetLocation + "/Localization." + oneLang + ".txt", string.Join(System.Environment.NewLine, localization_files[oneLang].ToArray())); } } catch (System.Exception e) { ValkyrieDebug.Log("Error: Failed to create new quest: " + e.Message); Application.Quit(); } // Back to edit selection new QuestEditSelection(); }
// Get a unity texture from a file (dds, svr or other unity supported format) // Crop to pos and size in pixels public static Texture2D FileToTexture(string file, Vector2 pos, Vector2 size) { if (file == null) { throw new ArgumentNullException("file"); } var resolvedFile = ResolveTextureFile(file); // return if file could not be resolved if (resolvedFile == null) { ValkyrieDebug.Log("Could not resolve file: '" + file + "'"); return(null); } file = resolvedFile; Texture2D texture = null; if (textureCache == null) { textureCache = new Dictionary <string, Texture2D>(); } if (textureCache.ContainsKey(file)) { texture = textureCache[file]; } else { string ext = Path.GetExtension(file); if (ext.Equals(".dds", StringComparison.InvariantCultureIgnoreCase)) { texture = DdsToTexture(file); } else if (ext.Equals(".pvr", StringComparison.InvariantCultureIgnoreCase)) { texture = PvrToTexture(file); } else // If the image isn't one of the formats above, just use unity file load { texture = ImageToTexture(file); } if (!file.Contains(TempPath)) { textureCache.Add(file, texture); } } // Get whole image if (size.x == 0) { return(texture); } // Get part of the image // Array of pixels from image Color[] pix = texture.GetPixels(Mathf.RoundToInt(pos.x), Mathf.RoundToInt(pos.y), Mathf.RoundToInt(size.x), Mathf.RoundToInt(size.y)); // Empty texture var subTexture = new Texture2D(Mathf.RoundToInt(size.x), Mathf.RoundToInt(size.y)); // Set pixels subTexture.SetPixels(pix); subTexture.Apply(); return(subTexture); }
// Create a menu which will take up the whole screen and have options. All items are dialog for destruction. public MainMenuScreen() { // This will destroy all, because we shouldn't have anything left at the main menu Destroyer.Destroy(); Game game = Game.Get(); game.cd = new ContentData(game.gameType.DataDirectory()); // Check if we found anything if (game.cd.GetPacks().Count == 0) { ValkyrieDebug.Log("Error: Failed to find any content packs, please check that you have them present in: " + game.gameType.DataDirectory() + System.Environment.NewLine); Application.Quit(); } // Load base game.cd.LoadContentID(""); List <string> music = new List <string>(); foreach (AudioData ad in game.cd.audio.Values) { if (ad.ContainsTrait("menu")) { music.Add(ad.file); } } game.audioControl.Music(music); // Name. Should this be the banner, or better to print Valkyrie with the game font? UIElement ui = new UIElement(); ui.SetLocation(2, 1, UIScaler.GetWidthUnits() - 4, 3); ui.SetText("Valkyrie"); ui.SetFont(game.gameType.GetHeaderFont()); ui.SetFontSize(UIScaler.GetLargeFont()); // Version type : alpha / beta should be displayed if (Game.Get().version.EndsWith("a")) { ui = new UIElement(); ui.SetLocation(UIScaler.GetRight(-6), 1, 6, 3); ui.SetText("alpha version"); ui.SetTextAlignment(TextAnchor.MiddleLeft); ui.SetFontSize(UIScaler.GetMediumFont()); } if (Game.Get().version.EndsWith("b")) { ui = new UIElement(); ui.SetLocation(UIScaler.GetRight(-6), 1, 6, 3); ui.SetText("beta version"); ui.SetTextAlignment(TextAnchor.MiddleLeft); ui.SetFontSize(UIScaler.GetMediumFont()); } // Button for start quest/scenario ui = new UIElement(); ui.SetLocation((UIScaler.GetWidthUnits() - ButtonWidth) / 2, 5, ButtonWidth, 2); ui.SetText(new StringKey("val", "START_QUEST", game.gameType.QuestName())); ui.SetFont(game.gameType.GetHeaderFont()); ui.SetFontSize(UIScaler.GetMediumFont()); ui.SetButton(Start); ui.SetBGColor(new Color(0, 0.03f, 0f)); new UIElementBorder(ui); ui = new UIElement(); ui.SetLocation((UIScaler.GetWidthUnits() - ButtonWidth) / 2, 8, ButtonWidth, 2); if (SaveManager.SaveExists()) { ui.SetText(new StringKey("val", "LOAD_QUEST", game.gameType.QuestName())); ui.SetButton(delegate { new SaveSelectScreen(); }); ui.SetBGColor(new Color(0, 0.03f, 0f)); new UIElementBorder(ui); } else { ui.SetText(new StringKey("val", "LOAD_QUEST", game.gameType.QuestName()), Color.grey); new UIElementBorder(ui, Color.grey); } ui.SetFont(game.gameType.GetHeaderFont()); ui.SetFontSize(UIScaler.GetMediumFont()); // Content selection page ui = new UIElement(); ui.SetLocation((UIScaler.GetWidthUnits() - ButtonWidth) / 2, 11, ButtonWidth, 2); ui.SetText(SELECT_CONTENT); ui.SetFont(game.gameType.GetHeaderFont()); ui.SetFontSize(UIScaler.GetMediumFont()); ui.SetButton(Content); ui.SetBGColor(new Color(0, 0.03f, 0f)); new UIElementBorder(ui); // Quest/Scenario editor ui = new UIElement(); ui.SetLocation((UIScaler.GetWidthUnits() - ButtonWidth) / 2, 14, ButtonWidth, 2); ui.SetText(new StringKey("val", "QUEST_NAME_EDITOR", game.gameType.QuestName())); ui.SetFont(game.gameType.GetHeaderFont()); ui.SetFontSize(UIScaler.GetMediumFont()); ui.SetButton(Editor); ui.SetBGColor(new Color(0, 0.03f, 0f)); new UIElementBorder(ui); // About page (managed in this class) ui = new UIElement(); ui.SetLocation((UIScaler.GetWidthUnits() - ButtonWidth) / 2, 17, ButtonWidth, 2); ui.SetText(ABOUT); ui.SetFont(game.gameType.GetHeaderFont()); ui.SetFontSize(UIScaler.GetMediumFont()); ui.SetButton(About); ui.SetBGColor(new Color(0, 0.03f, 0f)); new UIElementBorder(ui); // Configuration menu ui = new UIElement(); ui.SetLocation((UIScaler.GetWidthUnits() - ButtonWidth) / 2, 20, ButtonWidth, 2); ui.SetText(OPTIONS); ui.SetFont(game.gameType.GetHeaderFont()); ui.SetFontSize(UIScaler.GetMediumFont()); ui.SetButton(Config); ui.SetBGColor(new Color(0, 0.03f, 0f)); new UIElementBorder(ui); // Exit Valkyrie ui = new UIElement(); ui.SetLocation((UIScaler.GetWidthUnits() - ButtonWidth) / 2, 23, ButtonWidth, 2); ui.SetText(CommonStringKeys.EXIT); ui.SetFont(game.gameType.GetHeaderFont()); ui.SetFontSize(UIScaler.GetMediumFont()); ui.SetButton(Exit); ui.SetBGColor(new Color(0, 0.03f, 0f)); new UIElementBorder(ui); }
// Select a quest public void Start(QuestData.Quest q) { ValkyrieDebug.Log("INFO: Start quest from details screen"); GameStateManager.Quest.Start(q); }
// Save texture to disk private void ExportTexture(AssetPreloadData asset) { if (asset == null) { throw new ArgumentNullException("asset"); } Texture2D texture2D = new Texture2D(asset, false); texture2D = new Texture2D(asset, true); Directory.CreateDirectory(contentPath); Directory.CreateDirectory(contentPath + "/img"); // Default file name string fileCandidate = contentPath + "/img/" + asset.Text; string fileName = fileCandidate + asset.extension; ValkyrieDebug.Log("ExportTexture: " + fileName); // This should apend a postfix to the name to avoid collisions, but as we import multiple times // This is broken while (File.Exists(fileName)) { return;// Fixme; } switch (texture2D.m_TextureFormat) { #region DDS case 1: //Alpha8 case 2: //A4R4G4B4 case 3: //B8G8R8 //confirmed on X360, iOS //PS3 unsure case 4: //G8R8A8B8 //confirmed on X360, iOS case 5: //B8G8R8A8 //confirmed on X360, PS3, Web, iOS case 7: //R5G6B5 //confirmed switched on X360; confirmed on iOS case 10: //DXT1 case 12: //DXT5 case 13: //R4G4B4A4, iOS (only?) using (var fs = File.Open(fileName, FileMode.Create)) { using (var writer = new BinaryWriter(fs)) { // We have to manually add a header because unity doesn't have it writer.Write(0x20534444); writer.Write(0x7C); writer.Write(texture2D.dwFlags); writer.Write(texture2D.m_Height); writer.Write(texture2D.m_Width); writer.Write(texture2D.dwPitchOrLinearSize); //should be main tex size without mips); writer.Write((int)0); //dwDepth not implemented writer.Write(texture2D.dwMipMapCount); writer.Write(new byte[44]); //dwReserved1[11] writer.Write(texture2D.dwSize); writer.Write(texture2D.dwFlags2); writer.Write(texture2D.dwFourCC); writer.Write(texture2D.dwRGBBitCount); writer.Write(texture2D.dwRBitMask); writer.Write(texture2D.dwGBitMask); writer.Write(texture2D.dwBBitMask); writer.Write(texture2D.dwABitMask); writer.Write(texture2D.dwCaps); writer.Write(texture2D.dwCaps2); writer.Write(new byte[12]); //dwCaps3&4 & dwReserved2 // Write image data writer.Write(texture2D.image_data); } } break; #endregion #region PVR case 30: //PVRTC_RGB2 case 31: //PVRTC_RGBA2 case 32: //PVRTC_RGB4 case 33: //PVRTC_RGBA4 case 34: //ETC_RGB4 using (var fs = File.Open(fileName, FileMode.Create)) { using (var writer = new BinaryWriter(fs)) { // We have to manually add a header because unity doesn't have it writer.Write(texture2D.pvrVersion); writer.Write(texture2D.pvrFlags); writer.Write(texture2D.pvrPixelFormat); writer.Write(texture2D.pvrColourSpace); writer.Write(texture2D.pvrChannelType); writer.Write(texture2D.m_Height); writer.Write(texture2D.m_Width); writer.Write(texture2D.pvrDepth); writer.Write(texture2D.pvrNumSurfaces); writer.Write(texture2D.pvrNumFaces); writer.Write(texture2D.dwMipMapCount); writer.Write(texture2D.pvrMetaDataSize); // Write image data writer.Write(texture2D.image_data); } } break; #endregion case 28: //DXT1 Crunched case 29: //DXT1 Crunched default: using (var fs = File.Open(fileName, FileMode.Create)) { using (var writer = new BinaryWriter(fs)) { writer.Write(texture2D.image_data); } } break; } }
// Create a menu which will take up the whole screen and have options. All items are dialog for destruction. public MainMenuScreen() { // This will destroy all, because we shouldn't have anything left at the main menu Destroyer.Destroy(); Game game = Game.Get(); game.cd = new ContentData(game.gameType.DataDirectory()); // Check if we found anything if (game.cd.GetPacks().Count == 0) { ValkyrieDebug.Log("Error: Failed to find any content packs, please check that you have them present in: " + game.gameType.DataDirectory() + System.Environment.NewLine); Application.Quit(); } // Load base game.cd.LoadContentID(""); List <string> music = new List <string>(); foreach (AudioData ad in game.cd.audio.Values) { if (ad.ContainsTrait("menu")) { music.Add(ad.file); } } game.audioControl.Music(music); // Name. Should this be the banner, or better to print Valkyrie with the game font? DialogBox db = new DialogBox(new Vector2(2, 1), new Vector2(UIScaler.GetWidthUnits() - 4, 3), new StringKey(null, "Valkyrie", false)); db.textObj.GetComponent <UnityEngine.UI.Text>().fontSize = UIScaler.GetLargeFont(); db.SetFont(game.gameType.GetHeaderFont()); // Button for start quest/scenario TextButton tb = new TextButton( new Vector2((UIScaler.GetWidthUnits() - 12) / 2, 5), new Vector2(12, 2f), new StringKey("val", "START_QUEST", game.gameType.QuestName()), delegate { Start(); }); tb.background.GetComponent <UnityEngine.UI.Image>().color = new Color(0, 0.03f, 0f); tb.SetFont(game.gameType.GetHeaderFont()); // Load save game (enabled if exists) if (SaveManager.SaveExists()) { tb = new TextButton( new Vector2((UIScaler.GetWidthUnits() - 12) / 2, 8), new Vector2(12, 2f), new StringKey("val", "LOAD_QUEST", game.gameType.QuestName()), delegate { SaveManager.Load(); }); tb.background.GetComponent <UnityEngine.UI.Image>().color = new Color(0, 0.03f, 0f); tb.SetFont(game.gameType.GetHeaderFont()); } else { db = new DialogBox( new Vector2((UIScaler.GetWidthUnits() - 12) / 2, 8), new Vector2(12, 2f), new StringKey("val", "LOAD_QUEST", game.gameType.QuestName()), Color.red); db.textObj.GetComponent <UnityEngine.UI.Text>().fontSize = UIScaler.GetMediumFont(); db.SetFont(game.gameType.GetHeaderFont()); db.AddBorder(); } // Content selection page tb = new TextButton( new Vector2((UIScaler.GetWidthUnits() - 12) / 2, 11), new Vector2(12, 2f), SELECT_CONTENT, delegate { Content(); }); tb.background.GetComponent <UnityEngine.UI.Image>().color = new Color(0, 0.03f, 0f); tb.SetFont(game.gameType.GetHeaderFont()); // Quest/Scenario editor tb = new TextButton( new Vector2((UIScaler.GetWidthUnits() - 12) / 2, 14), new Vector2(12, 2f), new StringKey("val", "QUEST_NAME_EDITOR", game.gameType.QuestName()), delegate { Editor(); }); tb.background.GetComponent <UnityEngine.UI.Image>().color = new Color(0, 0.03f, 0f); tb.SetFont(game.gameType.GetHeaderFont()); // About page (managed in this class) tb = new TextButton( new Vector2((UIScaler.GetWidthUnits() - 12) / 2, 17), new Vector2(12, 2f), ABOUT, delegate { About(); }); tb.background.GetComponent <UnityEngine.UI.Image>().color = new Color(0, 0.03f, 0f); tb.SetFont(game.gameType.GetHeaderFont()); // Configuration menu tb = new TextButton( new Vector2((UIScaler.GetWidthUnits() - 12) / 2, 20), new Vector2(12, 2f), OPTIONS, delegate { Config(); }); tb.background.GetComponent <UnityEngine.UI.Image>().color = new Color(0, 0.03f, 0f); tb.SetFont(game.gameType.GetHeaderFont()); // Exit Valkyrie tb = new TextButton(new Vector2((UIScaler.GetWidthUnits() - 12) / 2, 23), new Vector2(12, 2f), CommonStringKeys.EXIT, delegate { Exit(); }); tb.background.GetComponent <UnityEngine.UI.Image>().color = new Color(0, 0.03f, 0f); tb.SetFont(game.gameType.GetHeaderFont()); }
// Save the quest public static void Save() { Game game = Game.Get(); // Add a comment at the start of the quest with the editor version StringBuilder content = new StringBuilder() .Append("; Saved by version: ") .AppendLine(game.version); // Save quest meta content to a string content.AppendLine(game.quest.qd.quest.ToString()); content.AppendLine("[QuestData]"); content.AppendLine("tiles.ini"); content.AppendLine("events.ini"); content.AppendLine("tokens.ini"); content.AppendLine("spawns.ini"); content.AppendLine("monsters.ini"); content.AppendLine("other.ini"); StringBuilder tiles = new StringBuilder() .Append("; Saved by version: ") .AppendLine(game.version); StringBuilder events = new StringBuilder() .Append("; Saved by version: ") .AppendLine(game.version); StringBuilder tokens = new StringBuilder() .Append("; Saved by version: ") .AppendLine(game.version); StringBuilder spawns = new StringBuilder() .Append("; Saved by version: ") .AppendLine(game.version); StringBuilder monsters = new StringBuilder() .Append("; Saved by version: ") .AppendLine(game.version); StringBuilder other = new StringBuilder() .Append("; Saved by version: ") .AppendLine(game.version); // Add all quest components foreach (KeyValuePair <string, QuestData.QuestComponent> kv in game.quest.qd.components) { if (kv.Value is QuestData.Tile) { tiles.AppendLine().Append(kv.Value); } else if (kv.Value is QuestData.Event && !kv.Value.GetType().IsSubclassOf(typeof(QuestData.Event))) { events.AppendLine().Append(kv.Value); } else if (kv.Value is QuestData.Token) { tokens.AppendLine().Append(kv.Value); } else if (kv.Value is QuestData.Spawn) { spawns.AppendLine().Append(kv.Value); } else if (kv.Value is QuestData.CustomMonster || kv.Value is QuestData.Activation) { monsters.AppendLine().Append(kv.Value); } // Skip peril, not a quest component else if (!(kv.Value is PerilData)) { other.AppendLine().Append(kv.Value); } } // Write to disk try { File.WriteAllText(game.quest.qd.questPath, content.ToString()); File.WriteAllText(Path.GetDirectoryName(game.quest.qd.questPath) + "/tiles.ini", tiles.ToString()); File.WriteAllText(Path.GetDirectoryName(game.quest.qd.questPath) + "/events.ini", events.ToString()); File.WriteAllText(Path.GetDirectoryName(game.quest.qd.questPath) + "/tokens.ini", tokens.ToString()); File.WriteAllText(Path.GetDirectoryName(game.quest.qd.questPath) + "/spawns.ini", spawns.ToString()); File.WriteAllText(Path.GetDirectoryName(game.quest.qd.questPath) + "/monsters.ini", monsters.ToString()); File.WriteAllText(Path.GetDirectoryName(game.quest.qd.questPath) + "/other.ini", other.ToString()); string ini_content = content.ToString(); ini_content += tiles.ToString(); ini_content += events.ToString(); ini_content += tokens.ToString(); ini_content += spawns.ToString(); ini_content += monsters.ToString(); ini_content += other.ToString(); if (LocalizationRead.scenarioDict != null) { List <string> localization_file = LocalizationRead.scenarioDict.Serialize(); File.WriteAllText( Path.GetDirectoryName(game.quest.qd.questPath) + "/Localization.txt", string.Join(System.Environment.NewLine, localization_file.ToArray())); } } catch (System.Exception) { ValkyrieDebug.Log("Error: Failed to save quest in editor."); Application.Quit(); } // Reload quest Reload(); }
/// <summary> /// Parse ini data into data structure /// </summary> /// <param name="lines">array of text lines</param> /// <param name="path">path from where lines came</param> /// <returns></returns> public static IniData ReadFromStringArray(string[] lines, string path) { // Create a dictionary for the first section Dictionary <string, string> entryData = new Dictionary <string, string>(); // Name for the current section string entryName = ""; // Create object to hold output IniData output = new IniData(); // Section headers have these chars removed char[] charsToTrim = { '[', ']' }; // Parse all lines foreach (string l in lines) { // Start of new section if (l.Length > 0 && l.Trim()[0] == '[') { // If not first section, add the last section of data if (entryName != "") { if (!output.Add(entryName, entryData)) { ValkyrieDebug.Log("Warning: duplicate section \"" + entryName + "\" in " + path + " will be ignored."); } } // create new data for new section entryData = new Dictionary <string, string>(); // Get name of new section entryName = l.Trim().Trim(charsToTrim); // Blank section names not allowed, but not fatal if (entryName.Equals("")) { ValkyrieDebug.Log("Warning: empty section in " + path + " will be ignored."); } } // If the line is not a comment (starts with ;) else if (l.Length > 0 && l.Trim()[0] != ';') { int equalsLocation = l.IndexOf('='); // Add data as entry with no value if (equalsLocation == -1) { if (entryData.ContainsKey(l.Trim())) { ValkyrieDebug.Log("Warning: duplicate \"" + l.Trim() + "\" data in section \"" + entryName + "\" in " + path + " will be ignored."); } else { entryData.Add(l.Trim(), ""); } } // If there is an = add data as key and value else { string key = l.Substring(0, equalsLocation).Trim(); if (entryData.ContainsKey(key)) { ValkyrieDebug.Log("Warning: duplicate \"" + key + "\" data in section \"" + entryName + "\" in " + path + " will be ignored."); } else { string value = l.Substring(equalsLocation + 1).Trim().Trim('\"'); //string translatedValue = LocalizationRead.FFGLookup(value); entryData.Add(key, value); } } // This won't go anywhere if we don't have a section if (entryName.Equals("")) { ValkyrieDebug.Log("Warning: data without section in " + path + " will be ignored."); } } } // Add the last section if (entryName != "") { if (!output.Add(entryName, entryData)) { ValkyrieDebug.Log("Warning: duplicate section \"" + entryName + "\" in " + path + " will be ignored."); } } return(output); }
// Read a content pack for list of files and meta data public void PopulatePackList(string path) { // All packs must have a content_pack.ini, otherwise ignore if (File.Exists(path + "/content_pack.ini")) { ContentPack pack = new ContentPack(); // Get all data from the file IniData d = IniRead.ReadFromIni(path + "/content_pack.ini"); // Todo: better error handling if (d == null) { ValkyrieDebug.Log("Failed to get any data out of " + path + "/content_pack.ini!"); Application.Quit(); } pack.name = d.Get("ContentPack", "name"); if (pack.name.Equals("")) { ValkyrieDebug.Log("Failed to get name data out of " + path + "/content_pack.ini!"); Application.Quit(); } // id can be empty/missing pack.id = d.Get("ContentPack", "id"); // If this is invalid we will just handle it later, not fatal pack.image = path + "/" + d.Get("ContentPack", "image"); // Black description isn't fatal pack.description = d.Get("ContentPack", "description"); // Some packs have a type pack.type = d.Get("ContentPack", "type"); // Get cloned packs string cloneString = d.Get("ContentPack", "clone"); pack.clone = new List <string>(); foreach (string s in cloneString.Split(" ".ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries)) { pack.clone.Add(s); } // Get all the other ini files in the pack List <string> files = new List <string>(); // content_pack file is included files.Add(path + "/content_pack.ini"); // No extra files is valid if (d.Get("ContentPackData") != null) { foreach (string file in d.Get("ContentPackData").Keys) { files.Add(path + "/" + file); } } // Save list of files pack.iniFiles = files; // Add content pack allPacks.Add(pack); // We finish without actually loading the content, this is done later (content optional) } }
private static void SaveWithScreen(int num, bool quit = false) { Game game = Game.Get(); try { if (!Directory.Exists(Game.AppData())) { Directory.CreateDirectory(Game.AppData()); } if (!Directory.Exists(ContentData.GameTypePath)) { Directory.CreateDirectory(ContentData.GameTypePath); } if (!Directory.Exists(Path.Combine(ContentData.GameTypePath, "Save"))) { Directory.CreateDirectory(Path.Combine(ContentData.GameTypePath, "Save")); } string tempValkyriePath = ContentData.TempValyriePath; if (!Directory.Exists(tempValkyriePath)) { Directory.CreateDirectory(tempValkyriePath); } File.WriteAllText(Path.Combine(tempValkyriePath, "save.ini"), game.quest.ToString()); Vector2 screenSize = new Vector2(Screen.width, Screen.height); Color[] screenColor = game.cc.screenShot.GetPixels(0); float scale = 4f / 30f; Texture2D outTex = new Texture2D(Mathf.RoundToInt(screenSize.x * scale), Mathf.RoundToInt(screenSize.y * scale), TextureFormat.RGB24, false); Color[] outColor = new Color[outTex.width * outTex.height]; for (int i = 0; i < outColor.Length; i++) { float xX = (float)i % (float)outTex.width; float xY = Mathf.Floor((float)i / (float)outTex.width); Vector2 vCenter = new Vector2(xX, xY) / scale; int xXFrom = (int)Mathf.Max(Mathf.Floor(vCenter.x - (0.5f / scale)), 0); int xXTo = (int)Mathf.Min(Mathf.Ceil(vCenter.x + (0.5f / scale)), screenSize.x); int xYFrom = (int)Mathf.Max(Mathf.Floor(vCenter.y - (0.5f / scale)), 0); int xYTo = (int)Mathf.Min(Mathf.Ceil(vCenter.y + (0.5f / scale)), screenSize.y); Color oColorTemp = new Color(); float xGridCount = 0; for (int iy = xYFrom; iy < xYTo; iy++) { for (int ix = xXFrom; ix < xXTo; ix++) { int index = (int)(((float)iy * screenSize.x) + ix); if (index >= screenColor.Length || index < 0) { continue; } oColorTemp += screenColor[index]; xGridCount++; } } outColor[i] = oColorTemp / (float)xGridCount; } outTex.SetPixels(outColor); outTex.Apply(); File.WriteAllBytes(Path.Combine(tempValkyriePath, "image.png"), outTex.EncodeToPNG()); // Check if we should update the zip file or write a new one with quest content // first autosave is a new zip file, following autosave just update the zip bool zip_update = false; if (num == 0 && game.quest.firstAutoSaveDone) { zip_update = true; } else if (num == 0) { game.quest.firstAutoSaveDone = true; } // Quest content can be in original path, or savegame path string quest_content_path; if (game.quest.fromSavegame) { quest_content_path = ContentData.ValkyrieLoadQuestPath; } else { quest_content_path = game.quest.originalPath; } // zip in a separate thread ZipManager.WriteZipAsync(tempValkyriePath, quest_content_path, SaveFile(num), zip_update); } catch (System.IO.IOException e) { ValkyrieDebug.Log("Warning: Unable to write to save file. " + e.Message); } if (quit) { ZipManager.Wait4PreviousSave(); Destroyer.MainMenu(); } }
// Activate a monster virtual public bool ActivateMonster(Quest.Monster m) { List <ActivationData> adList = new List <ActivationData>(); Game game = Game.Get(); bool customActivations = false; MonsterData md = m.monsterData; // Find out of this monster is quest specific QuestMonster qm = md as QuestMonster; if (qm != null) { // Get the base monster type if (game.cd.monsters.ContainsKey(qm.derivedType)) { md = game.cd.monsters[qm.derivedType]; } // Determine if the monster has quest specific activations customActivations = !qm.useMonsterTypeActivations; } // A monster with quest specific activations if (customActivations) { if (!qm.useMonsterTypeActivations) { adList = new List <ActivationData>(); // Get all custom activations foreach (string s in qm.activations) { // Find the activation in quest data if (game.quest.qd.components.ContainsKey("Activation" + s)) { adList.Add(new QuestActivation(game.quest.qd.components["Activation" + s] as QuestData.Activation)); } // Otherwise look for the activation in content data else if (game.cd.activations.ContainsKey("MonsterActivation" + s)) { adList.Add(game.cd.activations["MonsterActivation" + s]); } else // Invalid activation { game.quest.log.Add(new Quest.LogEntry("Warning: Unable to find activation: " + s + " for monster type: " + m.monsterData.sectionName, true)); } } } } else // Content Data activations only { // Find all possible activations foreach (KeyValuePair <string, ActivationData> kv in game.cd.activations) { // Is this activation for this monster type? (replace "Monster" with "MonsterActivation", ignore specific variety) if (kv.Key.IndexOf("MonsterActivation" + md.sectionName.Substring("Monster".Length)) == 0) { adList.Add(kv.Value); } } // Search for additional common activations foreach (string s in md.activations) { if (game.cd.activations.ContainsKey("MonsterActivation" + s)) { adList.Add(game.cd.activations["MonsterActivation" + s]); } else { ValkyrieDebug.Log("Warning: Unable to find activation: " + s + " for monster type: " + md.sectionName); } } } // Check for no activations if (adList.Count == 0) { ValkyrieDebug.Log("Error: Unable to find any activation data for monster type: " + md.name); Application.Quit(); } // No current activation if (m.currentActivation == null) { // Pick a random activation ActivationData activation = adList[Random.Range(0, adList.Count)]; m.NewActivation(activation); } // MoM has a special activation if (game.gameType is MoMGameType) { m.masterStarted = true; new ActivateDialogMoM(m); return(false); } // If no minion activation just do master if (m.currentActivation.ad.minionActions.fullKey.Length == 0) { m.minionStarted = true; m.masterStarted = true; new ActivateDialog(m, true, true); return(false); } // If no master activation just do minion if (m.currentActivation.ad.masterActions.fullKey.Length == 0) { m.minionStarted = true; m.masterStarted = true; new ActivateDialog(m, false, true); return(false); } // Random pick Minion or master (both available) m.minionStarted = Random.Range(0, 2) == 0; // If order specificed then use that instead if (m.currentActivation.ad.masterFirst) { m.minionStarted = false; } if (m.currentActivation.ad.minionFirst) { m.minionStarted = true; } // Master is opposite of minion as this is the first activation m.masterStarted = !m.minionStarted; // Create activation window new ActivateDialog(m, m.masterStarted); // More groups unactivated return(false); }
// Import one assets file public void Import(string assetFile) { List <string> unityFiles = new List <string>(); //files to load // read file AssetsFile assetsFile = new AssetsFile(assetFile, new EndianStream(File.OpenRead(assetFile), EndianType.BigEndian)); // Legacy assets not supported, shouldn't be old if (assetsFile.fileGen < 15) { ValkyrieDebug.Log("Invalid asset file: " + assetFile); return; } // Loop through all assets listed in file // Fixme: I don't think we need to do this as we are importing from all files anyway foreach (var sharedFile in assetsFile.sharedAssetsList) { // Some listed assets are in other assets files string sharedFilePath = finder.location + "/" + sharedFile.fileName; string sharedFileName = Path.GetFileName(sharedFile.fileName); // find assets file var quedSharedFile = unityFiles.Find(uFile => string.Equals(Path.GetFileName(uFile), sharedFileName, System.StringComparison.OrdinalIgnoreCase)); if (quedSharedFile == null) { if (!File.Exists(sharedFilePath)) { var findFiles = Directory.GetFiles(Path.GetDirectoryName(assetFile), sharedFileName, SearchOption.AllDirectories); if (findFiles.Length > 0) { sharedFilePath = findFiles[0]; } } if (File.Exists(sharedFilePath)) { //this would get screwed if the file somehow fails to load sharedFile.Index = unityFiles.Count; unityFiles.Add(sharedFilePath); } } else { sharedFile.Index = unityFiles.IndexOf(quedSharedFile); } } // Make assets from string list assetFiles = new List <AssetsFile>(); foreach (string s in unityFiles) { AssetsFile file = new AssetsFile(s, new EndianStream(File.OpenRead(s), EndianType.BigEndian)); assetFiles.Add(file); } // Get all asset content BuildAssetStrucutres(); // Write log WriteImportLog(logFile); }
// Add a placement image public void AddPlacedMonsterImg(string place, Texture2D newTex, int sizeX, int sizeY, float posX = 0, float posY = 0) { Game game = Game.Get(); Sprite iconSprite; // Check that placement name exists if (!game.quest.qd.components.ContainsKey(place) && place.Length > 0) { ValkyrieDebug.Log("Error: Invalid moster place: " + place); Application.Quit(); } // Create object GameObject circleObject = new GameObject("MonsterSpawnBorder" + place); GameObject gameObject = new GameObject("MonsterSpawn" + place); GameObject borderObject = new GameObject("MonsterSpawnBorder" + place); gameObject.tag = Game.DIALOG; borderObject.tag = Game.DIALOG; circleObject.tag = Game.DIALOG; circleObject.transform.SetParent(game.tokenCanvas.transform); gameObject.transform.SetParent(game.tokenCanvas.transform); borderObject.transform.SetParent(game.tokenCanvas.transform); // Create the image UnityEngine.UI.Image image = gameObject.AddComponent <UnityEngine.UI.Image>(); iconSprite = Sprite.Create(newTex, new Rect(0, 0, newTex.width, newTex.height), Vector2.zero, 1); image.sprite = iconSprite; image.rectTransform.sizeDelta = new Vector2(sizeX, sizeY); UnityEngine.UI.Image iconFrame = null; if (game.gameType is D2EGameType) { // Move to get the top left square corner at 0,0 gameObject.transform.Translate(Vector3.right * (float)(sizeX - 1) / 2f, Space.World); gameObject.transform.Translate(Vector3.down * (float)(sizeY - 1) / 2f, Space.World); borderObject.transform.Translate(Vector3.right * (float)(sizeX - 1) / 2f, Space.World); borderObject.transform.Translate(Vector3.down * (float)(sizeY - 1) / 2f, Space.World); image.rectTransform.sizeDelta = new Vector2(sizeX * 0.83f, sizeY * 0.83f); borderObject.AddComponent <CanvasRenderer>(); borderObject.AddComponent <RectTransform>(); iconFrame = borderObject.AddComponent <UnityEngine.UI.Image>(); Texture2D frameTex = Resources.Load("sprites/borders/Frame_Monster_1x1") as Texture2D; if (sizeX == 3) { frameTex = Resources.Load("sprites/borders/Frame_Monster_2x3") as Texture2D; } if (sizeX == 2 && sizeY == 1) { frameTex = Resources.Load("sprites/borders/Frame_Monster_1x2") as Texture2D; } iconFrame.sprite = Sprite.Create(frameTex, new Rect(0, 0, frameTex.width, frameTex.height), Vector2.zero, 1); iconFrame.rectTransform.sizeDelta = new Vector2(sizeX, sizeY); } if (place.Length > 0) { QuestData.MPlace mp = game.quest.qd.components[place] as QuestData.MPlace; posX = mp.location.x; posY = mp.location.y; circleObject.transform.Translate(Vector3.right * (float)(sizeX - 1) / 2f, Space.World); circleObject.transform.Translate(Vector3.down * (float)(sizeY - 1) / 2f, Space.World); circleObject.AddComponent <CanvasRenderer>(); circleObject.AddComponent <RectTransform>(); UnityEngine.UI.Image iconCicle = circleObject.AddComponent <UnityEngine.UI.Image>(); Texture2D circleTex = Resources.Load("sprites/target") as Texture2D; if (sizeX == 2 && sizeY == 1) { circleTex = Resources.Load("sprites/borders/Empty_Monster_1x2") as Texture2D; } iconCicle.sprite = Sprite.Create(circleTex, new Rect(0, 0, circleTex.width, circleTex.height), Vector2.zero, 1); iconCicle.rectTransform.sizeDelta = new Vector2(sizeX * 1.08f, sizeY * 1.08f); if (mp.master) { iconCicle.color = Color.red; } if (mp.rotate) { gameObject.transform.RotateAround(Vector3.zero, Vector3.forward, -90); iconFrame.transform.RotateAround(Vector3.zero, Vector3.forward, -90); iconCicle.transform.RotateAround(Vector3.zero, Vector3.forward, -90); } } // Move to square gameObject.transform.Translate(new Vector3(posX, posY, 0), Space.World); borderObject.transform.Translate(new Vector3(posX, posY, 0), Space.World); circleObject.transform.Translate(new Vector3(posX, posY, 0), Space.World); }
// Read a content pack for list of files and meta data public void PopulatePackList(string path) { // All packs must have a content_pack.ini, otherwise ignore if (File.Exists(path + Path.DirectorySeparatorChar + "content_pack.ini")) { ContentPack pack = new ContentPack(); // Get all data from the file IniData d = IniRead.ReadFromIni(path + Path.DirectorySeparatorChar + "content_pack.ini"); // Todo: better error handling if (d == null) { ValkyrieDebug.Log("Failed to get any data out of " + path + Path.DirectorySeparatorChar + "content_pack.ini!"); Application.Quit(); } pack.name = d.Get("ContentPack", "name"); if (pack.name.Equals("")) { ValkyrieDebug.Log("Failed to get name data out of " + path + Path.DirectorySeparatorChar + "content_pack.ini!"); Application.Quit(); } // id can be empty/missing pack.id = d.Get("ContentPack", "id"); // If this is invalid we will just handle it later, not fatal if (d.Get("ContentPack", "image").IndexOf("{import}") == 0) { pack.image = ImportPath() + d.Get("ContentPack", "image").Substring(8); } else { pack.image = path + Path.DirectorySeparatorChar + d.Get("ContentPack", "image"); } // Black description isn't fatal pack.description = d.Get("ContentPack", "description"); // Some packs have a type pack.type = d.Get("ContentPack", "type"); // Get cloned packs string cloneString = d.Get("ContentPack", "clone"); pack.clone = new List <string>(); foreach (string s in cloneString.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)) { pack.clone.Add(s); } // Get all the other ini files in the pack List <string> files = new List <string>(); // content_pack file is included files.Add(path + Path.DirectorySeparatorChar + "content_pack.ini"); // No extra files is valid if (d.Get("ContentPackData") != null) { foreach (string file in d.Get("ContentPackData").Keys) { files.Add(path + Path.DirectorySeparatorChar + file); } } // Save list of files pack.iniFiles = files; // Get all the other ini files in the pack Dictionary <string, List <string> > dictFiles = new Dictionary <string, List <string> >(); // No extra files is valid if (d.Get("LanguageData") != null) { foreach (string s in d.Get("LanguageData").Keys) { int firstSpace = s.IndexOf(' '); string id = s.Substring(0, firstSpace); string file = s.Substring(firstSpace + 1); if (!dictFiles.ContainsKey(id)) { dictFiles.Add(id, new List <string>()); } dictFiles[id].Add(path + Path.DirectorySeparatorChar + file); } } // Save list of files pack.localizationFiles = dictFiles; // Add content pack allPacks.Add(pack); // Add symbol packSymbol.Add(pack.id, new StringKey("val", pack.id + "_SYMBOL")); // We finish without actually loading the content, this is done later (content optional) } }
// Load a saved game, does nothing if file does not exist public static void Load(int num = 0) { Game game = Game.Get(); try { if (File.Exists(SaveFile(num))) { if (!Directory.Exists(ContentData.TempValyriePath)) { Directory.CreateDirectory(ContentData.TempValyriePath); } string valkyrieLoadPath = Path.Combine(ContentData.TempValyriePath, "Load"); if (!Directory.Exists(valkyrieLoadPath)) { Directory.CreateDirectory(valkyrieLoadPath); } Directory.Delete(valkyrieLoadPath, true); ZipFile zip = ZipFile.Read(SaveFile(num)); zip.ExtractAll(valkyrieLoadPath); zip.Dispose(); // Check that quest in save is valid QuestData.Quest q = new QuestData.Quest(Path.Combine(valkyrieLoadPath, "quest")); if (!q.valid) { ValkyrieDebug.Log("Error: save contains unsupported quest version." + System.Environment.NewLine); Destroyer.MainMenu(); return; } string data = File.ReadAllText(Path.Combine(valkyrieLoadPath, "save.ini")); IniData saveData = IniRead.ReadFromString(data); saveData.data["Quest"]["path"] = Path.Combine(valkyrieLoadPath, "quest" + Path.DirectorySeparatorChar + "quest.ini"); saveData.Get("Quest", "valkyrie"); if (VersionNewer(game.version, saveData.Get("Quest", "valkyrie"))) { ValkyrieDebug.Log("Error: save is from a future version." + System.Environment.NewLine); Destroyer.MainMenu(); return; } if (!VersionNewerOrEqual(minValkyieVersion, saveData.Get("Quest", "valkyrie"))) { ValkyrieDebug.Log("Error: save is from an old unsupported version." + System.Environment.NewLine); Destroyer.MainMenu(); return; } Destroyer.Dialog(); // Restart contend data so we can select from save game.cd = new ContentData(game.gameType.DataDirectory()); // Check if we found anything if (game.cd.GetPacks().Count == 0) { ValkyrieDebug.Log("Error: Failed to find any content packs, please check that you have them present in: " + game.gameType.DataDirectory() + System.Environment.NewLine); Application.Quit(); } game.cd.LoadContentID(""); // Load the base content // Load content that the save game uses Dictionary <string, string> packs = saveData.Get("Packs"); foreach (KeyValuePair <string, string> kv in packs) { game.cd.LoadContentID(""); // Support for save games from 1.2 and older if (kv.Key.Equals("FA")) { game.cd.LoadContentID("FAI"); game.cd.LoadContentID("FAM"); game.cd.LoadContentID("FAT"); } if (kv.Key.Equals("CotW")) { game.cd.LoadContentID("CotWI"); game.cd.LoadContentID("CotWM"); game.cd.LoadContentID("CotWT"); } if (kv.Key.Equals("MoM1E")) { game.cd.LoadContentID("MoM1EI"); game.cd.LoadContentID("MoM1EM"); game.cd.LoadContentID("MoM1ET"); } else { game.cd.LoadContentID(kv.Key); } } // This loads the game new Quest(saveData); // Draw things on the screen game.heroCanvas.SetupUI(); game.heroCanvas.UpdateImages(); game.heroCanvas.UpdateStatus(); if (game.gameType.DisplayMorale()) { game.moraleDisplay = new MoraleDisplay(); } if (!game.gameType.DisplayHeroes()) { game.heroCanvas.Clean(); } // Create the menu button new MenuButton(); new LogButton(); new SkillButton(); new InventoryButton(); game.stageUI = new NextStageButton(); } } catch (IOException e) { ValkyrieDebug.Log("Error: Unable to open save file: " + SaveFile(num) + " " + e.Message); Application.Quit(); } }
private static Texture2D DdsToTexture(string file) { if (file == null) { throw new ArgumentNullException("file"); } // Unity doesn't support dds directly, have to do hackery // Read the data byte[] ddsBytes = null; try { ddsBytes = File.ReadAllBytes(file); } catch (Exception ex) { if (!File.Exists(file)) { ValkyrieDebug.Log("Warning: DDS Image missing: '" + file + "'"); } else { ValkyrieDebug.Log("Warning: DDS Image loading of file '" + file + "' failed with " + ex.GetType().Name + " message: " + ex.Message); } return(null); } // Check for valid header byte ddsSizeCheck = ddsBytes[4]; if (ddsSizeCheck != 124) { ValkyrieDebug.Log("Warning: Image invalid: '" + file + "'"); return(null); } // Extract dimensions int height = ddsBytes[13] * 256 + ddsBytes[12]; int width = ddsBytes[17] * 256 + ddsBytes[16]; /*20-23 pit * 24-27 dep * 28-31 mm * 32-35 al * 36-39 res * 40-43 sur * 44-51 over * 52-59 des * 60-67 sov * 68-75 sblt * 76-79 size * 80-83 flags * 84-87 fourCC * 88-91 bpp * 92-95 red */ char[] type = new char[4]; type[0] = (char)ddsBytes[84]; type[1] = (char)ddsBytes[85]; type[2] = (char)ddsBytes[86]; type[3] = (char)ddsBytes[87]; // Copy image data (skip header) const int DDS_HEADER_SIZE = 128; byte[] dxtBytes = new byte[ddsBytes.Length - DDS_HEADER_SIZE]; Buffer.BlockCopy(ddsBytes, DDS_HEADER_SIZE, dxtBytes, 0, ddsBytes.Length - DDS_HEADER_SIZE); Texture2D texture = null; if (ddsBytes[87] == '5') { texture = new Texture2D(width, height, TextureFormat.DXT5, false); } else if (ddsBytes[87] == '1') { texture = new Texture2D(width, height, TextureFormat.DXT1, false); } else if (ddsBytes[88] == 32) { if (ddsBytes[92] == 0) { texture = new Texture2D(width, height, TextureFormat.BGRA32, false); } else { texture = new Texture2D(width, height, TextureFormat.RGBA32, false); } } else if (ddsBytes[88] == 24) { texture = new Texture2D(width, height, TextureFormat.RGB24, false); } else { ValkyrieDebug.Log("Warning: Image invalid: '" + file + "'"); } texture.LoadRawTextureData(dxtBytes); texture.Apply(); return(texture); }
public static void SaveWithScreen(int num, bool quit = false) { Game game = Game.Get(); try { if (!Directory.Exists(Game.AppData())) { Directory.CreateDirectory(Game.AppData()); } if (!Directory.Exists(Game.AppData() + "/" + game.gameType.TypeName())) { Directory.CreateDirectory(Game.AppData() + "/" + game.gameType.TypeName()); } if (!Directory.Exists(Game.AppData() + "/" + game.gameType.TypeName() + "/Save")) { Directory.CreateDirectory(Game.AppData() + "/" + game.gameType.TypeName() + "/Save"); } string tempValkyriePath = ContentData.TempValyriePath; if (!Directory.Exists(tempValkyriePath)) { Directory.CreateDirectory(tempValkyriePath); } File.WriteAllText(Path.Combine(tempValkyriePath, "save.ini"), game.quest.ToString()); Vector2 screenSize = new Vector2(Screen.width, Screen.height); Color[] screenColor = game.cc.screenShot.GetPixels(0); float scale = 4f / 30f; Texture2D outTex = new Texture2D(Mathf.RoundToInt(screenSize.x * scale), Mathf.RoundToInt(screenSize.y * scale), TextureFormat.RGB24, false); Color[] outColor = new Color[outTex.width * outTex.height]; for (int i = 0; i < outColor.Length; i++) { float xX = (float)i % (float)outTex.width; float xY = Mathf.Floor((float)i / (float)outTex.width); Vector2 vCenter = new Vector2(xX, xY) / scale; int xXFrom = (int)Mathf.Max(Mathf.Floor(vCenter.x - (0.5f / scale)), 0); int xXTo = (int)Mathf.Min(Mathf.Ceil(vCenter.x + (0.5f / scale)), screenSize.x); int xYFrom = (int)Mathf.Max(Mathf.Floor(vCenter.y - (0.5f / scale)), 0); int xYTo = (int)Mathf.Min(Mathf.Ceil(vCenter.y + (0.5f / scale)), screenSize.y); Color oColorTemp = new Color(); float xGridCount = 0; for (int iy = xYFrom; iy < xYTo; iy++) { for (int ix = xXFrom; ix < xXTo; ix++) { int index = (int)(((float)iy * screenSize.x) + ix); if (index >= screenColor.Length || index < 0) { continue; } oColorTemp += screenColor[index]; xGridCount++; } } outColor[i] = oColorTemp / (float)xGridCount; } outTex.SetPixels(outColor); outTex.Apply(); File.WriteAllBytes(Path.Combine(tempValkyriePath, "image.png"), outTex.EncodeToPNG()); ZipFile zip = new ZipFile(); zip.AddFile(Path.Combine(tempValkyriePath, "save.ini"), ""); zip.AddFile(Path.Combine(tempValkyriePath, "image.png"), ""); zip.AddDirectory(Path.GetDirectoryName(game.quest.qd.questPath), "quest"); zip.Save(SaveFile(num)); } catch (System.IO.IOException e) { ValkyrieDebug.Log("Warning: Unable to write to save file. " + e.Message); } if (quit) { Destroyer.MainMenu(); } }
// Save texture to disk private void ExportTexture(AssetPreloadData asset) { if (asset == null) { throw new ArgumentNullException("asset"); } Texture2D texture2D = new Texture2D(asset, false); texture2D = new Texture2D(asset, true); string imgPath = Path.Combine(contentPath, "img"); Directory.CreateDirectory(imgPath); // Default file name string fileCandidate = Path.Combine(imgPath, asset.Text); // This should apends a postfix to the name to avoid collisions string fileName = GetAvailableFileName(fileCandidate, asset.extension); ValkyrieDebug.Log("ExportTexture: '" + fileName + "' format: '" + texture2D.m_TextureFormat + "'"); switch (texture2D.m_TextureFormat) { #region DDS case 1: //Alpha8 case 2: //A4R4G4B4 case 3: //B8G8R8 //confirmed on X360, iOS //PS3 unsure case 4: //G8R8A8B8 //confirmed on X360, iOS case 5: //B8G8R8A8 //confirmed on X360, PS3, Web, iOS case 7: //R5G6B5 //confirmed switched on X360; confirmed on iOS case 10: //DXT1 case 12: //DXT5 case 13: //R4G4B4A4, iOS (only?) using (var fs = File.Open(fileName, FileMode.Create)) { using (var writer = new BinaryWriter(fs)) { // We have to manually add a header because unity doesn't have it writer.Write(0x20534444); writer.Write(0x7C); writer.Write(texture2D.dwFlags); writer.Write(texture2D.m_Height); writer.Write(texture2D.m_Width); writer.Write(texture2D.dwPitchOrLinearSize); //should be main tex size without mips); writer.Write((int)0); //dwDepth not implemented writer.Write(texture2D.dwMipMapCount); writer.Write(new byte[44]); //dwReserved1[11] writer.Write(texture2D.dwSize); writer.Write(texture2D.dwFlags2); writer.Write(texture2D.dwFourCC); writer.Write(texture2D.dwRGBBitCount); writer.Write(texture2D.dwRBitMask); writer.Write(texture2D.dwGBitMask); writer.Write(texture2D.dwBBitMask); writer.Write(texture2D.dwABitMask); writer.Write(texture2D.dwCaps); writer.Write(texture2D.dwCaps2); writer.Write(new byte[12]); //dwCaps3&4 & dwReserved2 // Write image data writer.Write(texture2D.image_data); } } break; #endregion #region PVR case 30: //PVRTC_RGB2 case 31: //PVRTC_RGBA2 case 32: //PVRTC_RGB4 case 33: //PVRTC_RGBA4 case 34: //ETC_RGB4 case 47: //ETC2_RGBA8 // We put the image data in a PVR container. See the specification for details // http://cdn.imgtec.com/sdk-documentation/PVR+File+Format.Specification.pdf using (var fs = File.Open(fileName, FileMode.Create)) { using (var writer = new BinaryWriter(fs)) { // We have to manually add a header because unity doesn't have it writer.Write(texture2D.pvrVersion); writer.Write(texture2D.pvrFlags); writer.Write(texture2D.pvrPixelFormat); writer.Write(texture2D.pvrColourSpace); writer.Write(texture2D.pvrChannelType); writer.Write(texture2D.m_Height); writer.Write(texture2D.m_Width); writer.Write(texture2D.pvrDepth); writer.Write(texture2D.pvrNumSurfaces); writer.Write(texture2D.pvrNumFaces); writer.Write(texture2D.dwMipMapCount); writer.Write(texture2D.pvrMetaDataSize); // Write image data writer.Write(texture2D.image_data); } } break; #endregion case 28: //DXT1 Crunched case 29: //DXT1 Crunched default: File.WriteAllBytes(fileName, texture2D.image_data); break; } }
public SaveData(int num = 0) { Game game = Game.Get(); if (!File.Exists(SaveFile(num))) { return; } try { if (!Directory.Exists(ContentData.TempValyriePath)) { Directory.CreateDirectory(ContentData.TempValyriePath); } string valkyrieLoadPath = Path.Combine(ContentData.TempValyriePath, "Load"); if (!Directory.Exists(valkyrieLoadPath)) { Directory.CreateDirectory(valkyrieLoadPath); } Directory.Delete(valkyrieLoadPath, true); ZipFile zip = ZipFile.Read(SaveFile(num)); zip.ExtractAll(valkyrieLoadPath); zip.Dispose(); image = ContentData.FileToTexture(Path.Combine(valkyrieLoadPath, "image.png")); // Check that quest in save is valid QuestData.Quest q = new QuestData.Quest(Path.Combine(valkyrieLoadPath, "quest")); if (!q.valid) { ValkyrieDebug.Log("Warning: Save " + num + " contains unsupported quest version." + System.Environment.NewLine); return; } DictionaryI18n tmpDict = LocalizationRead.selectDictionary("qst"); LocalizationRead.AddDictionary("qst", q.localizationDict); quest = q.name.Translate(); LocalizationRead.AddDictionary("qst", tmpDict); string data = File.ReadAllText(Path.Combine(valkyrieLoadPath, "save.ini")); IniData saveData = IniRead.ReadFromString(data); saveData.Get("Quest", "valkyrie"); if (VersionNewer(game.version, saveData.Get("Quest", "valkyrie"))) { ValkyrieDebug.Log("Warning: Save " + num + " is from a future version." + System.Environment.NewLine); return; } if (!VersionNewerOrEqual(minValkyieVersion, saveData.Get("Quest", "valkyrie"))) { ValkyrieDebug.Log("Warning: Save " + num + " is from an old unsupported version." + System.Environment.NewLine); return; } saveTime = System.DateTime.Parse(saveData.Get("Quest", "time")); valid = true; } catch (System.Exception e) { ValkyrieDebug.Log("Warning: Unable to open save file: " + SaveFile(num) + " " + e.Message); } }
// Get a unity texture from a file (dds or other unity supported format) // Crop to pos and size in pixels public static Texture2D FileToTexture(string file, Vector2 pos, Vector2 size) { string imagePath = @"file://" + file; WWW www = null; Texture2D texture = null; // Unity doesn't support dds directly, have to do hackery if (Path.GetExtension(file).Equals(".dds")) { // Read the data byte[] ddsBytes = null; try { ddsBytes = File.ReadAllBytes(file); } catch (System.Exception) { ValkyrieDebug.Log("Warning: DDS Image missing: " + file); return(null); } // Check for valid header byte ddsSizeCheck = ddsBytes[4]; if (ddsSizeCheck != 124) { ValkyrieDebug.Log("Warning: Image invalid: " + file); return(null); } // Extract dimensions int height = ddsBytes[13] * 256 + ddsBytes[12]; int width = ddsBytes[17] * 256 + ddsBytes[16]; // Copy image data (skip header) int DDS_HEADER_SIZE = 128; byte[] dxtBytes = new byte[ddsBytes.Length - DDS_HEADER_SIZE]; System.Buffer.BlockCopy(ddsBytes, DDS_HEADER_SIZE, dxtBytes, 0, ddsBytes.Length - DDS_HEADER_SIZE); // Create empty texture texture = new Texture2D(width, height, TextureFormat.DXT5, false); // Load data into texture try { texture.LoadRawTextureData(dxtBytes); } catch (System.Exception) { texture = new Texture2D(width, height, TextureFormat.DXT1, false); texture.LoadRawTextureData(dxtBytes); } texture.Apply(); } else // If the image isn't DDS just use unity file load { try { www = new WWW(@"file://" + imagePath); texture = new Texture2D(256, 256, TextureFormat.DXT5, false); www.LoadImageIntoTexture(texture); } catch (System.Exception) { ValkyrieDebug.Log("Warning: Image missing: " + file); return(null); } } // Get whole image if (size.x == 0) { return(texture); } // Get part of the image // Array of pixels from image Color[] pix = texture.GetPixels(Mathf.RoundToInt(pos.x), Mathf.RoundToInt(pos.y), Mathf.RoundToInt(size.x), Mathf.RoundToInt(size.y)); // Empty texture Texture2D subTexture = new Texture2D(Mathf.RoundToInt(size.x), Mathf.RoundToInt(size.y)); // Set pixels subTexture.SetPixels(pix); subTexture.Apply(); return(subTexture); }
// Load a saved game, does nothing if file does not exist public static void Load(int num = 0) { Game game = Game.Get(); try { if (File.Exists(SaveFile(num))) { if (!Directory.Exists(ContentData.TempValyriePath)) { Directory.CreateDirectory(ContentData.TempValyriePath); } string valkyrieLoadPath = Path.Combine(ContentData.TempValyriePath, "Load"); if (!Directory.Exists(valkyrieLoadPath)) { Directory.CreateDirectory(valkyrieLoadPath); } Directory.Delete(valkyrieLoadPath, true); ZipManager.Extract(valkyrieLoadPath, SaveFile(num), ZipManager.Extract_mode.ZIPMANAGER_EXTRACT_FULL); string savefile_content = File.ReadAllText(Path.Combine(valkyrieLoadPath, "save.ini")); IniData saveData = IniRead.ReadFromString(savefile_content); // when loading a quest, path should always be $TMP/load/quest/$subquest/quest.ini // Make sure it is when loading a quest saved for the first time, as in that case it is the original load path string questLoadPath = Path.GetDirectoryName(saveData.Get("Quest", "path")); string questOriginalPath = saveData.Get("Quest", "originalpath"); // loading a quest saved for the first time if (questLoadPath.Contains(questOriginalPath)) { questLoadPath = questLoadPath.Replace(questOriginalPath, ContentData.ValkyrieLoadQuestPath); } // Check that quest in save is valid QuestData.Quest q = new QuestData.Quest(questLoadPath); if (!q.valid) { ValkyrieDebug.Log("Error: save contains unsupported quest version." + System.Environment.NewLine); Destroyer.MainMenu(); return; } saveData.data["Quest"]["path"] = Path.Combine(questLoadPath, "quest.ini"); if (VersionManager.VersionNewer(game.version, saveData.Get("Quest", "valkyrie"))) { ValkyrieDebug.Log("Error: save is from a future version." + System.Environment.NewLine); Destroyer.MainMenu(); return; } if (!VersionManager.VersionNewerOrEqual(minValkyieVersion, saveData.Get("Quest", "valkyrie"))) { ValkyrieDebug.Log("Error: save is from an old unsupported version." + System.Environment.NewLine); Destroyer.MainMenu(); return; } Destroyer.Dialog(); // Load content that the save game uses Dictionary <string, string> packs = saveData.Get("Packs"); foreach (KeyValuePair <string, string> kv in packs) { // Support for save games from 1.2 and older if (kv.Key.Equals("FA")) { game.cd.LoadContentID("FAI"); game.cd.LoadContentID("FAM"); game.cd.LoadContentID("FAT"); } if (kv.Key.Equals("CotW")) { game.cd.LoadContentID("CotWI"); game.cd.LoadContentID("CotWM"); game.cd.LoadContentID("CotWT"); } if (kv.Key.Equals("MoM1E")) { game.cd.LoadContentID("MoM1EI"); game.cd.LoadContentID("MoM1EM"); game.cd.LoadContentID("MoM1ET"); } else { game.cd.LoadContentID(kv.Key); } } // This loads the game new Quest(saveData); // Draw things on the screen game.heroCanvas.SetupUI(); game.heroCanvas.UpdateImages(); game.heroCanvas.UpdateStatus(); if (game.gameType.DisplayMorale()) { game.moraleDisplay = new MoraleDisplay(); } if (!game.gameType.DisplayHeroes()) { game.heroCanvas.Clean(); } // Create the menu button new MenuButton(); new LogButton(); new SkillButton(); new InventoryButton(); game.stageUI = new NextStageButton(); } } catch (IOException e) { ValkyrieDebug.Log("Error: Unable to open save file: " + SaveFile(num) + " " + e.Message); Application.Quit(); } }
// Check for FFG text lookups and insert required text /// <summary> /// Replaces a FFG key with his current text /// </summary> /// <param name="input">{ffg:XXXX} like input</param> /// <returns>Translation to current language</returns> public static string DictLookup(StringKey input) { string output = input.fullKey; // While there are more lookups // Count the number of replaces. One lookup should not replace more than RECURSIVE_LIMIT elements. int recursiveCount = 0; string lookupRegexKey = LookupRegexKey(); Match match_result = Regex.Match(output, lookupRegexKey); //while (output.IndexOf("{ffg:") != -1) while (match_result.Success && recursiveCount < RECURSIVE_LIMIT) { int pos = match_result.Index; // Can be nested int bracketLevel = 1; // Start of lookup // ffg val and qst has the same length int lookupStart = pos + "{ffg:".Length; // Loop to find end of lookup int lookupEnd = lookupStart; while (bracketLevel > 0) { lookupEnd++; if (output[lookupEnd].Equals('{')) { bracketLevel++; } if (output[lookupEnd].Equals('}')) { bracketLevel--; } } // Extract lookup key string lookup = output.Substring(lookupStart, lookupEnd - lookupStart); // dict string dict = output.Substring(pos + 1, 3); // Get key result string result = DictQuery(dict, lookup); // We (unity) don't support underlines // Unity uses <> not [] result = result.Replace("[u]", "<b>").Replace("[/u]", "</b>"); result = result.Replace("[i]", "<i>").Replace("[/i]", "</i>"); result = result.Replace("[b]", "<b>").Replace("[/b]", "</b>"); // Some FFG text doesn't close b/i like it should while (Regex.Matches(result, "<b>").Count > Regex.Matches(result, "</b>").Count) { result += "</b>"; } while (Regex.Matches(result, "<i>").Count > Regex.Matches(result, "</i>").Count) { result += "</i>"; } // Replace the lookup output = output.Replace("{" + dict + ":" + lookup + "}", result); // Increase the recursive count recursiveCount++; match_result = Regex.Match(output, lookupRegexKey); } if (recursiveCount == RECURSIVE_LIMIT) { ValkyrieDebug.Log("ERROR Recursive loop limit reached translating " + input.fullKey + ". Dictionary entry must be fixed."); } return(output); }
public SaveData(int num = 0) { Game game = Game.Get(); if (!File.Exists(SaveFile(num))) { return; } try { if (!Directory.Exists(ContentData.TempValyriePath)) { Directory.CreateDirectory(ContentData.TempValyriePath); } string valkyrieLoadPath = Path.Combine(ContentData.TempValyriePath, "Preload"); if (!Directory.Exists(valkyrieLoadPath)) { Directory.CreateDirectory(valkyrieLoadPath); } ZipManager.Extract(valkyrieLoadPath, SaveFile(num), ZipManager.Extract_mode.ZIPMANAGER_EXTRACT_SAVE_INI_PIC); image = ContentData.FileToTexture(Path.Combine(valkyrieLoadPath, "image.png")); string data = File.ReadAllText(Path.Combine(valkyrieLoadPath, "save.ini")); IniData saveData = IniRead.ReadFromString(data); // when loading a quest, path should always be $TMP/load/quest/$subquest/quest.ini // Make sure it is when loading a quest saved for the first time, as in that case it is the original load path string questLoadPath = Path.GetDirectoryName(saveData.Get("Quest", "path")); string questOriginalPath = saveData.Get("Quest", "originalpath"); // loading a quest saved for the first time if (questLoadPath.Contains(questOriginalPath)) { questLoadPath = questLoadPath.Replace(questOriginalPath, ContentData.ValkyrieLoadQuestPath); } // use preload path rather than load questLoadPath = questLoadPath.Replace(ContentData.ValkyrieLoadPath, ContentData.ValkyriePreloadPath); QuestData.Quest q = new QuestData.Quest(questLoadPath); if (!q.valid) { ValkyrieDebug.Log("Warning: Save " + num + " contains unsupported quest version." + System.Environment.NewLine); return; } quest_name = saveData.Get("Quest", "questname"); if (VersionManager.VersionNewer(game.version, saveData.Get("Quest", "valkyrie"))) { ValkyrieDebug.Log("Warning: Save " + num + " is from a future version." + System.Environment.NewLine); return; } if (!VersionManager.VersionNewerOrEqual(minValkyieVersion, saveData.Get("Quest", "valkyrie"))) { ValkyrieDebug.Log("Warning: Save " + num + " is from an old unsupported version." + System.Environment.NewLine); return; } saveTime = System.DateTime.Parse(saveData.Get("Quest", "time")); valid = true; } catch (System.Exception e) { ValkyrieDebug.Log("Warning: Unable to open save file: " + SaveFile(num) + "\nException: " + e.ToString()); } }
// Trigger next event in stack public void TriggerEvent() { Game game = Game.Get(); // First check if things need to be added to the queue at end round if (game.roundControl.CheckNewRound()) { return; } // No events to trigger if (eventStack.Count == 0) { return; } // Get the next event Event e = eventStack.Pop(); currentEvent = e; // Move to another quest if (e is StartQuestEvent) { // This loads the game game.quest.ChangeQuest((e as StartQuestEvent).name); return; } // Event may have been disabled since added if (e.Disabled()) { currentEvent = null; TriggerEvent(); return; } // Play audio if (game.cd.audio.ContainsKey(e.qEvent.audio)) { game.audioControl.Play(game.cd.audio[e.qEvent.audio].file); } else if (e.qEvent.audio.Length > 0) { game.audioControl.Play(Quest.FindLocalisedMultimediaFile(e.qEvent.audio, Path.GetDirectoryName(game.quest.qd.questPath))); } // Set Music if (e.qEvent.music.Count > 0) { List <string> music = new List <string>(); foreach (string s in e.qEvent.music) { if (game.cd.audio.ContainsKey(s)) { music.Add(game.cd.audio[s].file); } else { music.Add(Quest.FindLocalisedMultimediaFile(s, Path.GetDirectoryName(game.quest.qd.questPath))); } } game.audioControl.PlayMusic(music); if (music.Count > 1) { game.quest.music = new List <string>(e.qEvent.music); } } // Perform var operations game.quest.vars.Perform(e.qEvent.operations); // Update morale change if (game.gameType is D2EGameType) { game.quest.AdjustMorale(0); } if (game.quest.vars.GetValue("$restock") == 1) { game.quest.GenerateItemSelection(); } // If a dialog window is open we force it closed (this shouldn't happen) foreach (GameObject go in GameObject.FindGameObjectsWithTag(Game.DIALOG)) { UnityEngine.Object.Destroy(go); } // If this is a monster event then add the monster group if (e is MonsterEvent) { MonsterEvent qe = (MonsterEvent)e; qe.MonsterEventSelection(); // Is this type new? Quest.Monster oldMonster = null; foreach (Quest.Monster m in game.quest.monsters) { if (m.monsterData.sectionName.Equals(qe.cMonster.sectionName)) { // Matched existing monster oldMonster = m; } } // Add the new type if (!game.gameType.MonstersGrouped() || oldMonster == null) { game.quest.monsters.Add(new Quest.Monster(qe)); game.monsterCanvas.UpdateList(); // Update monster var game.quest.vars.SetValue("#monsters", game.quest.monsters.Count); } // There is an existing group, but now it is unique else if (qe.qMonster.unique) { oldMonster.unique = true; oldMonster.uniqueText = qe.qMonster.uniqueText; oldMonster.uniqueTitle = qe.GetUniqueTitle(); oldMonster.healthMod = Mathf.RoundToInt(qe.qMonster.uniqueHealthBase + (Game.Get().quest.GetHeroCount() * qe.qMonster.uniqueHealthHero)); } // Display the location(s) if (qe.qEvent.locationSpecified && e.qEvent.display) { game.tokenBoard.AddMonster(qe); } } // Highlight a space on the board if (e.qEvent.highlight) { game.tokenBoard.AddHighlight(e.qEvent); } // Is this a shop? List <string> itemList = new List <string>(); foreach (string s in e.qEvent.addComponents) { if (s.IndexOf("QItem") == 0) { // Fix #998 if (game.gameType.TypeName() == "MoM" && itemList.Count == 1) { ValkyrieDebug.Log("WARNING: only one QItem can be used in event " + e.qEvent.sectionName + ", ignoring other items"); break; } itemList.Add(s); } } // Add board components game.quest.Add(e.qEvent.addComponents, itemList.Count > 1); // Remove board components game.quest.Remove(e.qEvent.removeComponents); // Move camera if (e.qEvent.locationSpecified && !(e.qEvent is QuestData.UI)) { CameraController.SetCamera(e.qEvent.location); } if (e.qEvent is QuestData.Puzzle) { QuestData.Puzzle p = e.qEvent as QuestData.Puzzle; if (p.puzzleClass.Equals("slide")) { new PuzzleSlideWindow(e); } if (p.puzzleClass.Equals("code")) { new PuzzleCodeWindow(e); } if (p.puzzleClass.Equals("image")) { new PuzzleImageWindow(e); } if (p.puzzleClass.Equals("tower")) { new PuzzleTowerWindow(e); } return; } // Set camera limits if (e.qEvent.minCam) { CameraController.SetCameraMin(e.qEvent.location); } if (e.qEvent.maxCam) { CameraController.SetCameraMax(e.qEvent.location); } // Is this a shop? if (itemList.Count > 1 && !game.quest.boardItems.ContainsKey("#shop")) { game.quest.boardItems.Add("#shop", new ShopInterface(itemList, Game.Get(), e.qEvent.sectionName)); game.quest.ordered_boardItems.Add("#shop"); } else if (!e.qEvent.display) { // Only raise dialog if there is text, otherwise auto confirm EndEvent(); } else { if (monsterImage != null) { MonsterDialogMoM.DrawMonster(monsterImage, true); if (monsterHealth) { } } new DialogWindow(e); } }
public bool AttemptMonsterMatch(QuestData.Spawn spawn, bool force = true) { if (monsterSelect.ContainsKey(spawn.sectionName)) { return(false); } if ((spawn.mTraitsPool.Length + spawn.mTraitsRequired.Length) == 0) { foreach (string t in spawn.mTypes) { if (monsterSelect.ContainsKey(t)) { monsterSelect.Add(spawn.sectionName, monsterSelect[t]); return(true); } if (t.IndexOf("Spawn") == 0) { return(false); } string monster = t; if (monster.IndexOf("Monster") != 0 && monster.IndexOf("CustomMonster") != 0) { monster = "Monster" + monster; } // Monster type might be a unique for this quest if (game.quest.qd.components.ContainsKey(monster)) { monsterSelect.Add(spawn.sectionName, monster); return(true); } // Monster type might exist in content packs, 'Monster' is optional else if (game.cd.monsters.ContainsKey(monster)) { monsterSelect.Add(spawn.sectionName, monster); return(true); } } } else { // List of exclusions List <string> exclude = new List <string>(); foreach (string t in spawn.mTypes) { if (monsterSelect.ContainsKey(t)) { exclude.Add(monsterSelect[t]); } else if (t.IndexOf("Spawn") == 0 && !force) { return(false); } else { exclude.Add(t); } } // Start a list of matches List <string> list = new List <string>(); foreach (KeyValuePair <string, MonsterData> kv in game.cd.monsters) { bool allFound = true; foreach (string t in spawn.mTraitsRequired) { // Does the monster have this trait? if (!kv.Value.ContainsTrait(t)) { // Trait missing, exclude monster allFound = false; } } // Must have one of these traits bool oneFound = (spawn.mTraitsPool.Length == 0); foreach (string t in spawn.mTraitsPool) { // Does the monster have this trait? if (kv.Value.ContainsTrait(t)) { oneFound = true; } } bool excludeBool = false; foreach (string t in exclude) { if (t.Equals(kv.Key)) { excludeBool = true; } } // Monster has all traits if (allFound && oneFound && !excludeBool) { list.Add(kv.Key); } } if (list.Count == 0) { ValkyrieDebug.Log("Error: Unable to find monster of traits specified in event: " + spawn.sectionName); Destroyer.MainMenu(); return(false); } // Pick monster at random from candidates monsterSelect.Add(spawn.sectionName, list[Random.Range(0, list.Count)]); return(true); } return(false); }