Ejemplo n.º 1
0
    // This loads content from a pack by object
    // Duplicate content will be replaced by the higher priority value
    void LoadContent(ContentPack cp)
    {
        // Don't reload content
        if (loadedPacks.Contains(cp.id))
        {
            return;
        }

        foreach (string ini in cp.iniFiles)
        {
            IniData d = IniRead.ReadFromIni(ini);
            // Bad ini file not a fatal error, just ignore (will be in log)
            if (d == null)
            {
                return;
            }

            // Add each section
            foreach (KeyValuePair <string, Dictionary <string, string> > section in d.data)
            {
                AddContent(section.Key, section.Value, Path.GetDirectoryName(ini), cp.id);
            }
        }
        loadedPacks.Add(cp.id);

        foreach (string s in cp.clone)
        {
            LoadContentID(s);
        }
    }
Ejemplo n.º 2
0
        // Check if an import is required
        public bool NeedImport()
        {
            // Read the import log
            logFile = Path.Combine(contentPath, "import.ini");
            IniData log = IniRead.ReadFromIni(logFile);

            // If no import log, import is required
            if (log == null)
            {
                return(true);
            }

            bool appVersionOK  = false;
            bool valkVersionOK = false;

            // Check that the FFG app version in import is new enough
            string lastImport = log.Get("Import", "FFG");

            appVersionOK = VersionNewerOrEqual(finder.RequiredFFGVersion(), lastImport);

            // Check that the Valkyrie version in import is new enough
            int lastValkVersion = 0;

            int.TryParse(log.Get("Import", "Valkyrie"), out lastValkVersion);
            valkVersionOK = (FFGImport.version == lastValkVersion);
            return(!appVersionOK || !valkVersionOK);
        }
Ejemplo n.º 3
0
    // Check if an import is required
    public bool NeedImport()
    {
        // Read the import log
        logFile = ContentData.ContentPath() + gameType + "/ffg/import.ini";
        IniData log = IniRead.ReadFromIni(logFile);

        // If no import log, import is required
        if (log == null)
        {
            return(true);
        }

        bool appVersionOK  = false;
        bool valkVersionOK = false;

        // Check that the FFG app version in import is new enough
        string lastImport = log.Get("Import", "FFG");

        appVersionOK = VersionNewerOrEqual(finder.RequiredFFGVersion(), lastImport);

        // Check that the Valkyrie version in import is new enough
        lastImport    = log.Get("Import", "Valkyrie");
        valkVersionOK = VersionNewerOrEqual(requiredValkyrieVersion, lastImport);
        return(!appVersionOK || !valkVersionOK);
    }
Ejemplo n.º 4
0
    public void DrawList()
    {
        localManifest = IniRead.ReadFromString("");
        if (File.Exists(saveLocation() + "/manifest.ini"))
        {
            localManifest = IniRead.ReadFromIni(saveLocation() + "/manifest.ini");
        }

        // Heading
        DialogBox db = new DialogBox(new Vector2(2, 1), new Vector2(UIScaler.GetWidthUnits() - 4, 3), "Download " + game.gameType.QuestName());

        db.textObj.GetComponent <UnityEngine.UI.Text>().fontSize = UIScaler.GetLargeFont();
        db.SetFont(game.gameType.GetHeaderFont());

        TextButton tb;
        // Start here
        int offset = 5;

        // Loop through all available quests
        // FIXME: this isn't paged Dictionary<string, Dictionary<string, string>> data;
        foreach (KeyValuePair <string, Dictionary <string, string> > kv in remoteManifest.data)
        {
            string file = kv.Key + ".valkyrie";
            // Size is 1.2 to be clear of characters with tails
            if (File.Exists(saveLocation() + "/" + file))
            {
                int localVersion  = 0;
                int remoteVersion = 0;
                int.TryParse(localManifest.Get(kv.Key, "version"), out localVersion);
                int.TryParse(remoteManifest.Get(kv.Key, "version"), out remoteVersion);
                if (localVersion < remoteVersion)
                {
                    tb = new TextButton(new Vector2(2, offset), new Vector2(UIScaler.GetWidthUnits() - 4, 1.2f), "  [Update] " + kv.Value["name"], delegate { Selection(file); }, Color.blue, offset);
                    tb.button.GetComponent <UnityEngine.UI.Text>().fontSize   = UIScaler.GetSmallFont();
                    tb.button.GetComponent <UnityEngine.UI.Text>().alignment  = TextAnchor.MiddleLeft;
                    tb.background.GetComponent <UnityEngine.UI.Image>().color = new Color(0, 0, 0.1f);
                }
                else
                {
                    db = new DialogBox(new Vector2(2, offset), new Vector2(UIScaler.GetWidthUnits() - 4, 1.2f), "  " + kv.Value["name"], Color.grey);
                    db.AddBorder();
                    db.background.GetComponent <UnityEngine.UI.Image>().color = new Color(0.05f, 0.05f, 0.05f);
                    db.textObj.GetComponent <UnityEngine.UI.Text>().alignment = TextAnchor.MiddleLeft;
                }
            }
            else
            {
                tb = new TextButton(new Vector2(2, offset), new Vector2(UIScaler.GetWidthUnits() - 4, 1.2f), "  " + kv.Value["name"], delegate { Selection(file); }, Color.white, offset);
                tb.button.GetComponent <UnityEngine.UI.Text>().fontSize   = UIScaler.GetSmallFont();
                tb.button.GetComponent <UnityEngine.UI.Text>().alignment  = TextAnchor.MiddleLeft;
                tb.background.GetComponent <UnityEngine.UI.Image>().color = new Color(0, 0, 0.1f);
            }
            offset += 2;
        }

        tb = new TextButton(new Vector2(1, UIScaler.GetBottom(-3)), new Vector2(8, 2), "Back", delegate { Cancel(); }, Color.red);
        tb.SetFont(game.gameType.GetHeaderFont());
    }
Ejemplo n.º 5
0
    // Initialise data from the file on disk
    public ConfigFile()
    {
        data = new IniData();
        string optionsFile = Game.AppData() + "/config.ini";

        if (File.Exists(optionsFile))
        {
            data = IniRead.ReadFromIni(optionsFile);
        }
    }
Ejemplo n.º 6
0
    // Initialise data from the file on disk
    public ConfigFile()
    {
        data = new IniData();
        string optionsFile = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData) + "/Valkyrie/config.ini";

        if (File.Exists(optionsFile))
        {
            data = IniRead.ReadFromIni(optionsFile);
        }
    }
Ejemplo n.º 7
0
    static public void Extract(string target_path, string archive_name, Extract_mode mode)
    {
        // make sure save is done, to not manipulate file being currently written
        if (_job_started)
        {
            _jobHandle.Join();
            _job_started = false;
        }

        try
        {
            if (!Directory.Exists(target_path))
            {
                Directory.CreateDirectory(target_path);
            }

            ZipFile zip = ZipFile.Read(archive_name);

            if (mode == Extract_mode.ZIPMANAGER_EXTRACT_FULL)
            {
                zip.ExtractAll(target_path, ExtractExistingFileAction.OverwriteSilently);
            }

            if (mode == Extract_mode.ZIPMANAGER_EXTRACT_INI_TXT || mode == Extract_mode.ZIPMANAGER_EXTRACT_INI_TXT_PIC)
            {
                zip.ExtractSelectedEntries("name = quest.ini", null, target_path, ExtractExistingFileAction.OverwriteSilently);
                zip.ExtractSelectedEntries("name = Localization.*.txt", null, target_path, ExtractExistingFileAction.OverwriteSilently);

                if (mode == Extract_mode.ZIPMANAGER_EXTRACT_INI_TXT_PIC)
                {
                    Dictionary <string, string> iniData = IniRead.ReadFromIni(target_path + "/quest.ini", "Quest");
                    if (iniData.ContainsKey("image"))
                    {
                        zip.ExtractSelectedEntries("name = " + iniData["image"], null, target_path, ExtractExistingFileAction.OverwriteSilently);
                    }
                }
            }

            if (mode == Extract_mode.ZIPMANAGER_EXTRACT_SAVE_INI_PIC)
            {
                zip.ExtractSelectedEntries("name = save.ini", null, target_path, ExtractExistingFileAction.OverwriteSilently);
                zip.ExtractSelectedEntries("name = image.png", null, target_path, ExtractExistingFileAction.OverwriteSilently);

                // search in subfolder (* before filename is required for Android)
                zip.ExtractSelectedEntries("name = *quest.ini", null, target_path, ExtractExistingFileAction.OverwriteSilently);
                zip.ExtractSelectedEntries("name = *Localization.*.txt", null, target_path, ExtractExistingFileAction.OverwriteSilently);
            }

            zip.Dispose();
        }
        catch (System.Exception e)
        {
            ValkyrieDebug.Log("Warning: Unable to read file: " + archive_name + "\nException" + e.ToString());
        }
    }
Ejemplo n.º 8
0
    // 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)
            {
                Debug.Log("Failed to get any data out of " + path + "/content_pack.ini!");
                Application.Quit();
            }

            pack.name = d.Get("ContentPack", "name");
            if (pack.name.Equals(""))
            {
                Debug.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");

            // 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)
        }
    }
Ejemplo n.º 9
0
    public void LoadQuestData()
    {
        Debug.Log("Loading quest from: \"" + questPath + "\"");
        game = Game.Get();

        components    = new Dictionary <string, QuestComponent>();
        flags         = new List <string>();
        heroSelection = new Dictionary <string, List <Game.Hero> >();

        // Read the main quest file
        IniData d = IniRead.ReadFromIni(questPath);

        // Failure to read quest is fatal
        if (d == null)
        {
            Debug.Log("Failed to load quest from: \"" + questPath + "\"");
            Application.Quit();
        }

        // List of data files
        files = new List <string>();
        // The main data file is included
        files.Add(questPath);

        // Find others (no addition files is not fatal)
        if (d.Get("QuestData") != null)
        {
            foreach (string file in d.Get("QuestData").Keys)
            {
                // path is relative to the main file (absolute not supported)
                files.Add(Path.GetDirectoryName(questPath) + "/" + file);
            }
        }

        foreach (string f in files)
        {
            // Read each file
            d = IniRead.ReadFromIni(f);
            // Failure to read a file is fatal
            if (d == null)
            {
                Debug.Log("Unable to read quest file: \"" + f + "\"");
                Application.Quit();
            }
            foreach (KeyValuePair <string, Dictionary <string, string> > section in d.data)
            {
                // Add the section to our quest data
                AddData(section.Key, section.Value, Path.GetDirectoryName(f));
            }
        }
    }
Ejemplo n.º 10
0
    // Populate data
    public void LoadQuestData()
    {
        ValkyrieDebug.Log("Loading quest from: \"" + questPath + "\"" + System.Environment.NewLine);
        game = Game.Get();

        components       = new Dictionary <string, QuestComponent>();
        questActivations = new Dictionary <string, ActivationData>();

        // Read the main quest file
        IniData questIniData = IniRead.ReadFromIni(questPath);

        // Failure to read quest is fatal
        if (questIniData == null)
        {
            ValkyrieDebug.Log("Failed to load quest from: \"" + questPath + "\"");
            Application.Quit();
        }

        // List of data files
        files = new List <string>();
        // The main data file is included
        files.Add(questPath);

        // Find others (no addition files is not fatal)
        if (questIniData.Get("QuestData") != null)
        {
            foreach (string file in questIniData.Get("QuestData").Keys)
            {
                // path is relative to the main file (absolute not supported)
                files.Add(Path.GetDirectoryName(questPath) + "/" + file);
            }
        }

        foreach (string f in files)
        {
            // Read each file
            questIniData = IniRead.ReadFromIni(f);
            // Failure to read a file is fatal
            if (questIniData == null)
            {
                ValkyrieDebug.Log("Unable to read quest file: \"" + f + "\"");
                Application.Quit();
            }
            // Loop through all ini sections
            foreach (KeyValuePair <string, Dictionary <string, string> > section in questIniData.data)
            {
                // Add the section to our quest data
                AddData(section.Key, section.Value, Path.GetDirectoryName(f));
            }
        }
    }
Ejemplo n.º 11
0
    // This loads content from a pack by object
    // Duplicate content will be replaced by the higher priority value
    void LoadContent(ContentPack cp)
    {
        foreach (string ini in cp.iniFiles)
        {
            IniData d = IniRead.ReadFromIni(ini);
            // Bad ini file not a fatal error, just ignore (will be in log)
            if (d == null)
            {
                return;
            }

            // Add each section
            foreach (KeyValuePair <string, Dictionary <string, string> > section in d.data)
            {
                AddContent(section.Key, section.Value, Path.GetDirectoryName(ini), cp.id);
            }
        }
    }
Ejemplo n.º 12
0
    // This loads content from a pack by object
    // Duplicate content will be replaced by the higher priority value
    void LoadContent(ContentPack cp)
    {
        // Don't reload content
        if (loadedPacks.Contains(cp.id))
        {
            return;
        }

        foreach (string ini in cp.iniFiles)
        {
            IniData d = IniRead.ReadFromIni(ini);
            // Bad ini file not a fatal error, just ignore (will be in log)
            if (d == null)
            {
                return;
            }

            // Add each section
            foreach (KeyValuePair <string, Dictionary <string, string> > section in d.data)
            {
                AddContent(section.Key, section.Value, Path.GetDirectoryName(ini), cp.id);
            }
        }

        foreach (KeyValuePair <string, List <string> > kv in cp.localizationFiles)
        {
            DictionaryI18n packageDict = DictionaryI18n.ReadFromFileList("", kv.Value, DictionaryI18n.DEFAULT_LANG, Game.Get().currentLang);
            if (packageDict == null)
            {
                // Unable to load dictionary
                return;
            }
            packageDict.setCurrentLanguage(Game.Get().currentLang);

            LocalizationRead.AddDictionary(kv.Key, packageDict);
        }

        loadedPacks.Add(cp.id);

        foreach (string s in cp.clone)
        {
            LoadContentID(s);
        }
    }
Ejemplo n.º 13
0
    // This loads content from a pack by object
    // Duplicate content will be replaced by the higher priority value
    void LoadContent(ContentData.ContentPack cp)
    {
        // Don't reload content
        if (cd.loadedPacks.Contains(cp.id))
        {
            return;
        }

        foreach (KeyValuePair <string, List <string> > kv in cp.localizationFiles)
        {
            DictionaryI18n packageDict = new DictionaryI18n();
            foreach (string file in kv.Value)
            {
                packageDict.AddDataFromFile(file);
            }

            LocalizationRead.AddDictionary(kv.Key, packageDict);
        }

        foreach (string ini in cp.iniFiles)
        {
            IniData d = IniRead.ReadFromIni(ini);
            // Bad ini file not a fatal error, just ignore (will be in log)
            if (d == null)
            {
                return;
            }

            // Add each section
            foreach (KeyValuePair <string, Dictionary <string, string> > section in d.data)
            {
                LoadContent(section.Key, section.Value, Path.GetDirectoryName(ini), cp.id);
            }
        }


        cd.loadedPacks.Add(cp.id);

        foreach (string s in cp.clone)
        {
            LoadContentID(s);
        }
    }
Ejemplo n.º 14
0
    private void CheckLocalAvailability()
    {
        // load information on local quests
        IniData localManifest = IniRead.ReadFromIni(ContentData.DownloadPath() + "/manifest.ini");

        if (localManifest == null)
        {
            return;
        }

        // Update download status for each questData and check if update is available
        foreach (KeyValuePair <string, QuestData.Quest> quest_data in remote_quests_data)
        {
            if (localManifest.data.ContainsKey(quest_data.Key))
            {
                quest_data.Value.downloaded       = true;
                quest_data.Value.update_available = (localManifest.data[quest_data.Key]["version"] != quest_data.Value.version);
            }
        }
    }
Ejemplo n.º 15
0
        public Quest(string p)
        {
            path = p;
            IniData d = IniRead.ReadFromIni(p + "/quest.ini");

            if (d == null)
            {
                Debug.Log("Warning: Invalid quest:" + p + "/quest.ini!");
                return;
            }

            name = d.Get("Quest", "name");
            if (name.Equals(""))
            {
                Debug.Log("Warning: Failed to get name data out of " + p + "/content_pack.ini!");
                return;
            }

            // Missing description is OK
            description = d.Get("Quest", "description");
        }
Ejemplo n.º 16
0
    public bool NeedImport()
    {
        logFile = ContentData.ContentPath() + gameType + "/ffg/import.ini";
        IniData log = IniRead.ReadFromIni(logFile);

        if (log == null)
        {
            return(true);
        }

        bool appVersionOK  = false;
        bool valkVersionOK = false;

        string lastImport = log.Get("Import", "FFG");

        appVersionOK = VersionNewerOrEqual(finder.RequiredFFGVersion(), lastImport);

        lastImport    = log.Get("Import", "Valkyrie");
        valkVersionOK = VersionNewerOrEqual(requiredValkyrieVersion, lastImport);
        return(!appVersionOK || !valkVersionOK);
    }
Ejemplo n.º 17
0
        public Quest(string p)
        {
            path = p;
            Dictionary <string, string> d = IniRead.ReadFromIni(p + "/quest.ini", "Quest");

            if (d.ContainsKey("type"))
            {
                type = d["type"];
            }
            else
            {
                // Default to D2E to support historical quests
                type = "D2E";
            }

            if (d.ContainsKey("name"))
            {
                name = d["name"];
            }
            else
            {
                ValkyrieDebug.Log("Warning: Failed to get name data out of " + p + "/content_pack.ini!");
                return;
            }

            if (d.ContainsKey("packs") && d["packs"].Length > 0)
            {
                packs = d["packs"].Split(' ');
            }
            else
            {
                packs = new string[0];
            }

            // Missing description is OK
            if (d.ContainsKey("description"))
            {
                description = d["description"];
            }
        }
Ejemplo n.º 18
0
    public void SetQuestAvailability(string key, bool isAvailable)
    {
        // update list of local quest
        IniData localManifest = IniRead.ReadFromString("");
        string  saveLocation  = ContentData.DownloadPath();

        if (File.Exists(saveLocation + "/manifest.ini"))
        {
            localManifest = IniRead.ReadFromIni(saveLocation + "/manifest.ini");
        }

        if (isAvailable)
        {
            IniData downloaded_quest = IniRead.ReadFromString(remote_quests_data[key].ToString());
            localManifest.Remove(key);
            localManifest.Add(key, downloaded_quest.data["Quest"]);
        }
        else
        {
            if (localManifest.Get(key) != null)
            {
                localManifest.Remove(key);
            }
            // we need to delete /temp and reload list
            UnloadLocalQuests();
        }

        if (File.Exists(saveLocation + "/manifest.ini"))
        {
            File.Delete(saveLocation + "/manifest.ini");
        }
        File.WriteAllText(saveLocation + "/manifest.ini", localManifest.ToString());

        // update status quest
        remote_quests_data[key].downloaded       = isAvailable;
        remote_quests_data[key].update_available = false;
    }
Ejemplo n.º 19
0
        public Quest(string p)
        {
            path = p;
            IniData d = IniRead.ReadFromIni(p + "/quest.ini");

            if (d == null)
            {
                Debug.Log("Warning: Invalid quest:" + p + "/quest.ini!");
                return;
            }

            type = d.Get("Quest", "type");
            if (type.Length == 0)
            {
                // Default to D2E to support historical quests
                type = "D2E";
            }

            name = d.Get("Quest", "name");
            if (name.Equals(""))
            {
                Debug.Log("Warning: Failed to get name data out of " + p + "/content_pack.ini!");
                return;
            }

            if (d.Get("Quest", "packs").Length > 0)
            {
                packs = d.Get("Quest", "packs").Split(' ');
            }
            else
            {
                packs = new string[0];
            }

            // Missing description is OK
            description = d.Get("Quest", "description");
        }
Ejemplo n.º 20
0
    // Constructor takes a path in which to look for content
    public ContentData(string path)
    {
        // This is all of the available sides of tiles (not currently tracking physical tiles)
        tileSides = new Dictionary <string, TileSideData>();

        // Available heros
        heros = new Dictionary <string, HeroData>();

        // Available monsters
        monsters = new Dictionary <string, MonsterData>();

        //This has the game game and all expansions, general info
        allPacks = new List <ContentPack>();

        // This has all monster activations
        activations = new Dictionary <string, ActivationData>();

        // This has all available tokens
        tokens = new Dictionary <string, TokenData>();

        // This has all avilable perils
        perils = new Dictionary <string, PerilData>();

        // Search each directory in the path (one should be base game, others expansion.  Names don't matter
        string[] contentDirectories = Directory.GetDirectories(path);
        foreach (string p in contentDirectories)
        {
            // All packs must have a content_pack.ini, otherwise ignore
            if (File.Exists(p + "/content_pack.ini"))
            {
                ContentPack pack = new ContentPack();

                // Get all data from the file
                IniData d = IniRead.ReadFromIni(p + "/content_pack.ini");
                // Todo: better error handling
                if (d == null)
                {
                    Debug.Log("Failed to get any data out of " + p + "/content_pack.ini!");
                    Application.Quit();
                }

                pack.name = d.Get("ContentPack", "name");
                if (pack.name.Equals(""))
                {
                    Debug.Log("Failed to get name data out of " + p + "/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 = p + "/" + d.Get("ContentPack", "image");

                // Black description isn't fatal
                pack.description = d.Get("ContentPack", "description");

                // Get all the other ini files in the pack
                List <string> files = new List <string>();
                // content_pack file is included
                files.Add(p + "/content_pack.ini");

                // No extra files is valid
                if (d.Get("ContentPackData") != null)
                {
                    foreach (string file in d.Get("ContentPackData").Keys)
                    {
                        files.Add(p + "/" + 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)
            }
        }
    }
Ejemplo n.º 21
0
    // 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
            if (d.Get("ContentPack", "image").IndexOf("{import}") == 0)
            {
                pack.image = ContentData.ImportPath() + d.Get("ContentPack", "image").Substring(8);
            }
            else
            {
                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;

            // 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 + "/" + file);
                }
            }
            // Save list of files
            pack.localizationFiles = dictFiles;

            // Add content pack
            allPacks.Add(pack);

            // We finish without actually loading the content, this is done later (content optional)
        }
    }
Ejemplo n.º 22
0
    public void DrawList()
    {
        localManifest = IniRead.ReadFromString("");
        if (File.Exists(saveLocation() + "/manifest.ini"))
        {
            localManifest = IniRead.ReadFromIni(saveLocation() + "/manifest.ini");
        }

        // Heading
        DialogBox db = new DialogBox(
            new Vector2(2, 1),
            new Vector2(UIScaler.GetWidthUnits() - 4, 3),
            new StringKey("val", "QUEST_NAME_DOWNLOAD", game.gameType.QuestName())
            );

        db.textObj.GetComponent <UnityEngine.UI.Text>().fontSize = UIScaler.GetLargeFont();
        db.SetFont(game.gameType.GetHeaderFont());

        db = new DialogBox(new Vector2(1, 5f), new Vector2(UIScaler.GetWidthUnits() - 2f, 21f), StringKey.NULL);
        db.AddBorder();
        db.background.AddComponent <UnityEngine.UI.Mask>();
        UnityEngine.UI.ScrollRect scrollRect = db.background.AddComponent <UnityEngine.UI.ScrollRect>();

        GameObject    scrollArea      = new GameObject("scroll");
        RectTransform scrollInnerRect = scrollArea.AddComponent <RectTransform>();

        scrollArea.transform.parent = db.background.transform;
        scrollInnerRect.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Left, 0, (UIScaler.GetWidthUnits() - 3f) * UIScaler.GetPixelsPerUnit());
        scrollInnerRect.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, 0, 1);

        GameObject scrollBarObj = new GameObject("scrollbar");

        scrollBarObj.transform.parent = db.background.transform;
        RectTransform scrollBarRect = scrollBarObj.AddComponent <RectTransform>();

        scrollBarRect.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, 0, 21 * UIScaler.GetPixelsPerUnit());
        scrollBarRect.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Left, (UIScaler.GetWidthUnits() - 3f) * UIScaler.GetPixelsPerUnit(), 1 * UIScaler.GetPixelsPerUnit());
        UnityEngine.UI.Scrollbar scrollBar = scrollBarObj.AddComponent <UnityEngine.UI.Scrollbar>();
        scrollBar.direction          = UnityEngine.UI.Scrollbar.Direction.BottomToTop;
        scrollRect.verticalScrollbar = scrollBar;

        GameObject scrollBarHandle = new GameObject("scrollbarhandle");

        scrollBarHandle.transform.parent = scrollBarObj.transform;
        //RectTransform scrollBarHandleRect = scrollBarHandle.AddComponent<RectTransform>();
        scrollBarHandle.AddComponent <UnityEngine.UI.Image>();
        scrollBarHandle.GetComponent <UnityEngine.UI.Image>().color = new Color(0.7f, 0.7f, 0.7f);
        scrollBar.handleRect           = scrollBarHandle.GetComponent <RectTransform>();
        scrollBar.handleRect.offsetMin = Vector2.zero;
        scrollBar.handleRect.offsetMax = Vector2.zero;

        scrollRect.content    = scrollInnerRect;
        scrollRect.horizontal = false;

        TextButton tb;
        // Start here
        int offset = 5;

        // Loop through all available quests
        foreach (KeyValuePair <string, Dictionary <string, string> > kv in remoteManifest.data)
        {
            string file = kv.Key + ".valkyrie";
            LocalizationRead.scenarioDict = localizationDict;
            string questName = new StringKey("qst", kv.Key + ".name").Translate();

            int remoteFormat = 0;
            int.TryParse(remoteManifest.Get(kv.Key, "format"), out remoteFormat);
            bool formatOK = (remoteFormat >= QuestData.Quest.minumumFormat) && (remoteFormat <= QuestData.Quest.currentFormat);

            if (!formatOK)
            {
                continue;
            }

            // Size is 1.2 to be clear of characters with tails
            if (File.Exists(saveLocation() + "/" + file))
            {
                string localHash  = localManifest.Get(kv.Key, "version");
                string remoteHash = remoteManifest.Get(kv.Key, "version");

                if (!localHash.Equals(remoteHash))
                {
                    tb = new TextButton(
                        new Vector2(2, offset),
                        new Vector2(UIScaler.GetWidthUnits() - 8, 1.2f),
                        //TODO: the name should be another key in near future. now is a nonLookup key
                        new StringKey("val", "QUEST_NAME_UPDATE", questName),
                        delegate { Selection(file); },
                        Color.black, offset);

                    tb.button.GetComponent <UnityEngine.UI.Text>().fontSize   = UIScaler.GetSmallFont();
                    tb.button.GetComponent <UnityEngine.UI.Text>().material   = (Material)Resources.Load("Fonts/FontMaterial");
                    tb.button.GetComponent <UnityEngine.UI.Text>().alignment  = TextAnchor.MiddleLeft;
                    tb.background.GetComponent <UnityEngine.UI.Image>().color = new Color(0.7f, 0.7f, 1f);
                    tb.background.transform.parent = scrollArea.transform;
                    tb = new TextButton(
                        new Vector2(UIScaler.GetWidthUnits() - 6, offset),
                        new Vector2(3, 1.2f),
                        new StringKey("val", "DELETE"),
                        delegate { Delete(file); },
                        Color.black, offset);

                    tb.button.GetComponent <UnityEngine.UI.Text>().fontSize   = UIScaler.GetSmallFont();
                    tb.button.GetComponent <UnityEngine.UI.Text>().material   = (Material)Resources.Load("Fonts/FontMaterial");
                    tb.background.GetComponent <UnityEngine.UI.Image>().color = Color.red;
                    tb.background.transform.parent = scrollArea.transform;
                }
                else
                {
                    db = new DialogBox(
                        new Vector2(2, offset),
                        new Vector2(UIScaler.GetWidthUnits() - 8, 1.2f),
                        new StringKey("val", "INDENT", questName),
                        Color.black);
                    db.AddBorder();
                    db.background.GetComponent <UnityEngine.UI.Image>().color = new Color(0.07f, 0.07f, 0.07f);
                    db.background.transform.parent = scrollArea.transform;
                    db.textObj.GetComponent <UnityEngine.UI.Text>().alignment = TextAnchor.MiddleLeft;
                    db.textObj.GetComponent <UnityEngine.UI.Text>().material  = (Material)Resources.Load("Fonts/FontMaterial");
                    tb = new TextButton(
                        new Vector2(UIScaler.GetWidthUnits() - 6, offset),
                        new Vector2(3, 1.2f),
                        new StringKey("val", "DELETE"),
                        delegate { Delete(file); },
                        Color.black, offset);

                    tb.button.GetComponent <UnityEngine.UI.Text>().fontSize   = UIScaler.GetSmallFont();
                    tb.button.GetComponent <UnityEngine.UI.Text>().material   = (Material)Resources.Load("Fonts/FontMaterial");
                    tb.background.GetComponent <UnityEngine.UI.Image>().color = Color.red;
                    tb.background.transform.parent = scrollArea.transform;
                }
            }
            else
            {
                tb = new TextButton(
                    new Vector2(2, offset),
                    new Vector2(UIScaler.GetWidthUnits() - 5, 1.2f),
                    new StringKey("val", "INDENT", questName),
                    delegate { Selection(file); },
                    Color.black, offset);

                tb.button.GetComponent <UnityEngine.UI.Text>().fontSize   = UIScaler.GetSmallFont();
                tb.button.GetComponent <UnityEngine.UI.Text>().material   = (Material)Resources.Load("Fonts/FontMaterial");
                tb.button.GetComponent <UnityEngine.UI.Text>().alignment  = TextAnchor.MiddleLeft;
                tb.background.GetComponent <UnityEngine.UI.Image>().color = Color.white;
                tb.background.transform.parent = scrollArea.transform;
            }
            offset += 2;
        }

        foreach (KeyValuePair <string, Dictionary <string, string> > kv in localManifest.data)
        {
            // Only looking for files missing from remote
            if (remoteManifest.data.ContainsKey(kv.Key))
            {
                continue;
            }
            string type = localManifest.Get(kv.Key, "type");

            // Only looking for packages of this game type
            if (!game.gameType.TypeName().Equals(type))
            {
                continue;
            }

            string file = kv.Key + ".valkyrie";
            // Size is 1.2 to be clear of characters with tails
            if (File.Exists(saveLocation() + "/" + file))
            {
                db = new DialogBox(
                    new Vector2(2, offset),
                    new Vector2(UIScaler.GetWidthUnits() - 8, 1.2f),
                    new StringKey("val", "INDENT", file),
                    Color.black);
                db.AddBorder();
                db.background.GetComponent <UnityEngine.UI.Image>().color = new Color(0.07f, 0.07f, 0.07f);
                db.background.transform.parent = scrollArea.transform;
                db.textObj.GetComponent <UnityEngine.UI.Text>().alignment = TextAnchor.MiddleLeft;
                db.textObj.GetComponent <UnityEngine.UI.Text>().material  = (Material)Resources.Load("Fonts/FontMaterial");
                tb = new TextButton(
                    new Vector2(UIScaler.GetWidthUnits() - 6, offset),
                    new Vector2(3, 1.2f),
                    new StringKey("val", "DELETE"),
                    delegate { Delete(file); },
                    Color.black, offset);

                tb.button.GetComponent <UnityEngine.UI.Text>().fontSize   = UIScaler.GetSmallFont();
                tb.button.GetComponent <UnityEngine.UI.Text>().material   = (Material)Resources.Load("Fonts/FontMaterial");
                tb.background.GetComponent <UnityEngine.UI.Image>().color = Color.red;
                tb.background.transform.parent = scrollArea.transform;
            }
        }

        scrollInnerRect.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, 0, (offset - 5) * UIScaler.GetPixelsPerUnit());

        tb = new TextButton(
            new Vector2(1, UIScaler.GetBottom(-3)),
            new Vector2(8, 2), CommonStringKeys.BACK, delegate { Cancel(); }, Color.red);

        tb.SetFont(game.gameType.GetHeaderFont());
    }
Ejemplo n.º 23
0
    public void DrawList()
    {
        localManifest = IniRead.ReadFromString("");
        if (File.Exists(saveLocation() + "/manifest.ini"))
        {
            localManifest = IniRead.ReadFromIni(saveLocation() + "/manifest.ini");
        }

        // Heading
        DialogBox db = new DialogBox(new Vector2(2, 1), new Vector2(UIScaler.GetWidthUnits() - 4, 3), "Download " + game.gameType.QuestName());

        db.textObj.GetComponent <UnityEngine.UI.Text>().fontSize = UIScaler.GetLargeFont();
        db.SetFont(game.gameType.GetHeaderFont());

        db = new DialogBox(new Vector2(1, 5f), new Vector2(UIScaler.GetWidthUnits() - 2f, 21f), "");
        db.AddBorder();
        db.background.AddComponent <UnityEngine.UI.Mask>();
        UnityEngine.UI.ScrollRect scrollRect = db.background.AddComponent <UnityEngine.UI.ScrollRect>();

        GameObject    scrollArea      = new GameObject("scroll");
        RectTransform scrollInnerRect = scrollArea.AddComponent <RectTransform>();

        scrollArea.transform.parent = db.background.transform;
        scrollInnerRect.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Left, 0, (UIScaler.GetWidthUnits() - 3f) * UIScaler.GetPixelsPerUnit());
        scrollInnerRect.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, 0, 1);

        scrollRect.content    = scrollInnerRect;
        scrollRect.horizontal = false;

        TextButton tb;
        // Start here
        int offset = 5;

        // Loop through all available quests
        foreach (KeyValuePair <string, Dictionary <string, string> > kv in remoteManifest.data)
        {
            string file = kv.Key + ".valkyrie";
            // Size is 1.2 to be clear of characters with tails
            if (File.Exists(saveLocation() + "/" + file))
            {
                int localVersion  = 0;
                int remoteVersion = 0;
                int.TryParse(localManifest.Get(kv.Key, "version"), out localVersion);
                int.TryParse(remoteManifest.Get(kv.Key, "version"), out remoteVersion);
                if (localVersion < remoteVersion)
                {
                    tb = new TextButton(new Vector2(2, offset), new Vector2(UIScaler.GetWidthUnits() - 5, 1.2f), "  [Update] " + kv.Value["name"], delegate { Selection(file); }, Color.black, offset);
                    tb.button.GetComponent <UnityEngine.UI.Text>().fontSize   = UIScaler.GetSmallFont();
                    tb.button.GetComponent <UnityEngine.UI.Text>().material   = (Material)Resources.Load("Fonts/FontMaterial");
                    tb.button.GetComponent <UnityEngine.UI.Text>().alignment  = TextAnchor.MiddleLeft;
                    tb.background.GetComponent <UnityEngine.UI.Image>().color = new Color(0.7f, 0.7f, 1f);
                    tb.background.transform.parent = scrollArea.transform;
                }
                else
                {
                    db = new DialogBox(new Vector2(2, offset), new Vector2(UIScaler.GetWidthUnits() - 5, 1.2f), "  " + kv.Value["name"], Color.black);
                    db.AddBorder();
                    db.background.GetComponent <UnityEngine.UI.Image>().color = new Color(0.07f, 0.07f, 0.07f);
                    db.background.transform.parent = scrollArea.transform;
                    db.textObj.GetComponent <UnityEngine.UI.Text>().alignment = TextAnchor.MiddleLeft;
                    db.textObj.GetComponent <UnityEngine.UI.Text>().material  = (Material)Resources.Load("Fonts/FontMaterial");
                }
            }
            else
            {
                tb = new TextButton(new Vector2(2, offset), new Vector2(UIScaler.GetWidthUnits() - 5, 1.2f), "  " + kv.Value["name"], delegate { Selection(file); }, Color.black, offset);
                tb.button.GetComponent <UnityEngine.UI.Text>().fontSize   = UIScaler.GetSmallFont();
                tb.button.GetComponent <UnityEngine.UI.Text>().material   = (Material)Resources.Load("Fonts/FontMaterial");
                tb.button.GetComponent <UnityEngine.UI.Text>().alignment  = TextAnchor.MiddleLeft;
                tb.background.GetComponent <UnityEngine.UI.Image>().color = Color.white;
                tb.background.transform.parent = scrollArea.transform;
            }
            offset += 2;
        }

        scrollInnerRect.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, 0, (offset - 5) * UIScaler.GetPixelsPerUnit());

        tb = new TextButton(new Vector2(1, UIScaler.GetBottom(-3)), new Vector2(8, 2), "Back", delegate { Cancel(); }, Color.red);
        tb.SetFont(game.gameType.GetHeaderFont());
    }
Ejemplo n.º 24
0
        public void TestLoadLocalIni()
        {
            IniData result = IniRead.ReadFromIni(currentPath);

            Assert.IsNotNull(result);
        }
Ejemplo n.º 25
0
    /// <summary>
    /// Draw download options screen
    /// </summary>
    public void DrawList()
    {
        Destroyer.Dialog();
        localManifest = IniRead.ReadFromString("");
        if (File.Exists(saveLocation() + "/manifest.ini"))
        {
            localManifest = IniRead.ReadFromIni(saveLocation() + "/manifest.ini");
        }

        // Heading
        UIElement ui = new UIElement();

        ui.SetLocation(2, 1, UIScaler.GetWidthUnits() - 4, 3);
        ui.SetText(new StringKey("val", "QUEST_NAME_DOWNLOAD", game.gameType.QuestName()));
        ui.SetFont(game.gameType.GetHeaderFont());
        ui.SetFontSize(UIScaler.GetLargeFont());

        UIElementScrollVertical scrollArea = new UIElementScrollVertical();

        scrollArea.SetLocation(1, 5, UIScaler.GetWidthUnits() - 2f, 21f);
        new UIElementBorder(scrollArea);

        // Start here
        float offset = 0;

        // Loop through all available quests
        foreach (RemoteQuest rq in remoteQuests)
        {
            string file      = rq.name + ".valkyrie";
            string questName = rq.GetData("name." + game.currentLang);
            if (questName.Length == 0)
            {
                questName = rq.GetData("name." + rq.GetData("defaultlanguage"));
            }
            if (questName.Length == 0)
            {
                questName = rq.name;
            }

            int remoteFormat = 0;
            int.TryParse(rq.GetData("format"), out remoteFormat);
            bool formatOK = (remoteFormat >= QuestData.Quest.minumumFormat) && (remoteFormat <= QuestData.Quest.currentFormat);

            if (!formatOK)
            {
                continue;
            }

            bool exists = File.Exists(saveLocation() + "/" + file);
            bool update = true;
            if (exists)
            {
                string localHash  = localManifest.Get(rq.name, "version");
                string remoteHash = rq.GetData("version");

                update = !localHash.Equals(remoteHash);
            }

            Color bg = Color.white;
            if (exists)
            {
                bg = new Color(0.7f, 0.7f, 1f);
                if (!update)
                {
                    bg = new Color(0.1f, 0.1f, 0.1f);
                }
            }

            // Frame
            ui = new UIElement(scrollArea.GetScrollTransform());
            ui.SetLocation(0.95f, offset, UIScaler.GetWidthUnits() - 4.9f, 3.1f);
            ui.SetBGColor(bg);
            if (update)
            {
                ui.SetButton(delegate { Selection(rq); });
            }
            offset += 0.05f;

            // Draw Image
            ui = new UIElement(scrollArea.GetScrollTransform());
            ui.SetLocation(1, offset, 3, 3);
            ui.SetBGColor(bg);
            if (update)
            {
                ui.SetButton(delegate { Selection(rq); });
            }

            if (rq.image != null)
            {
                ui.SetImage(rq.image);
            }

            ui = new UIElement(scrollArea.GetScrollTransform());
            ui.SetBGColor(Color.clear);
            ui.SetLocation(4, offset, UIScaler.GetWidthUnits() - 8, 3f);
            ui.SetTextPadding(1.2f);
            if (update && exists)
            {
                ui.SetText(new StringKey("val", "QUEST_NAME_UPDATE", questName), Color.black);
            }
            else
            {
                ui.SetText(questName, Color.black);
            }
            if (update)
            {
                ui.SetButton(delegate { Selection(rq); });
            }
            ui.SetTextAlignment(TextAnchor.MiddleLeft);
            ui.SetFontSize(Mathf.RoundToInt(UIScaler.GetSmallFont() * 1.3f));

            // Duration
            int lengthMax = 0;
            int.TryParse(rq.GetData("lengthmax"), out lengthMax);
            if (lengthMax > 0)
            {
                int lengthMin = 0;
                int.TryParse(rq.GetData("lengthmin"), out lengthMin);

                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetLocation(UIScaler.GetRight(-11), offset, 2, 1);
                ui.SetText(lengthMin.ToString(), Color.black);
                ui.SetBGColor(Color.clear);

                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetLocation(UIScaler.GetRight(-9), offset, 1, 1);
                ui.SetText("-", Color.black);
                ui.SetBGColor(Color.clear);

                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetLocation(UIScaler.GetRight(-8), offset, 2, 1);
                ui.SetText(lengthMax.ToString(), Color.black);
                ui.SetBGColor(Color.clear);
            }

            // Difficulty
            float difficulty = 0;
            float.TryParse(rq.GetData("difficulty"), out difficulty);
            if (difficulty != 0)
            {
                string symbol = "π"; // will
                if (game.gameType is MoMGameType)
                {
                    symbol = new StringKey("val", "ICON_SUCCESS_RESULT").Translate();
                }
                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetLocation(UIScaler.GetRight(-13), offset + 1, 9, 2);
                ui.SetText(symbol + symbol + symbol + symbol + symbol, Color.black);
                ui.SetBGColor(Color.clear);
                ui.SetFontSize(UIScaler.GetMediumFont());

                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetLocation(UIScaler.GetRight(-11.95f) + (difficulty * 6.9f), offset + 1, (1 - difficulty) * 6.9f, 2);
                Color filter = bg;
                filter.a = 0.7f;
                ui.SetBGColor(filter);
            }

            // Size is 1.2 to be clear of characters with tails
            if (exists)
            {
                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetLocation(((UIScaler.GetWidthUnits() - 3) / 2) - 4, offset + 2.5f, 8, 1.2f);
                ui.SetBGColor(new Color(0.7f, 0, 0));
                ui.SetText(CommonStringKeys.DELETE, Color.black);
                ui.SetButton(delegate { Delete(file); });
                offset += 0.5f;
            }
            offset += 4;
        }

        foreach (KeyValuePair <string, Dictionary <string, string> > kv in localManifest.data)
        {
            // Only looking for files missing from remote
            bool onRemote = false;
            foreach (RemoteQuest rq in remoteQuests)
            {
                if (rq.name.Equals(kv.Key))
                {
                    onRemote = true;
                }
            }
            if (onRemote)
            {
                continue;
            }

            string type = localManifest.Get(kv.Key, "type");

            // Only looking for packages of this game type
            if (!game.gameType.TypeName().Equals(type))
            {
                continue;
            }

            string file = kv.Key + ".valkyrie";
            // Size is 1.2 to be clear of characters with tails
            if (File.Exists(saveLocation() + "/" + file))
            {
                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetLocation(1, offset, UIScaler.GetWidthUnits() - 8, 1.2f);
                ui.SetTextPadding(1.2f);
                ui.SetText(file, Color.black);
                ui.SetBGColor(new Color(0.1f, 0.1f, 0.1f));
                ui.SetTextAlignment(TextAnchor.MiddleLeft);

                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetLocation(UIScaler.GetWidthUnits() - 12, offset, 8, 1.2f);
                ui.SetText(CommonStringKeys.DELETE, Color.black);
                ui.SetTextAlignment(TextAnchor.MiddleLeft);
                ui.SetButton(delegate { Delete(file); });
                ui.SetBGColor(new Color(0.7f, 0, 0));
                offset += 2;
            }
        }

        scrollArea.SetScrollSize(offset);

        ui = new UIElement();
        ui.SetLocation(1, UIScaler.GetBottom(-3), 8, 2);
        ui.SetText(CommonStringKeys.BACK, Color.red);
        ui.SetButton(delegate { Cancel(); });
        ui.SetFont(game.gameType.GetHeaderFont());
        ui.SetFontSize(UIScaler.GetMediumFont());
        new UIElementBorder(ui, Color.red);
    }
Ejemplo n.º 26
0
    /// <summary>
    /// Draw download options screen
    /// </summary>
    public void DrawList()
    {
        Destroyer.Dialog();
        localManifest = IniRead.ReadFromString("");
        if (File.Exists(saveLocation() + "/manifest.ini"))
        {
            localManifest = IniRead.ReadFromIni(saveLocation() + "/manifest.ini");
        }

        // Heading
        UIElement ui = new UIElement();

        ui.SetLocation(2, 1, UIScaler.GetWidthUnits() - 4, 3);
        ui.SetText(new StringKey("val", "QUEST_NAME_DOWNLOAD", game.gameType.QuestName()));
        ui.SetFont(game.gameType.GetHeaderFont());
        ui.SetFontSize(UIScaler.GetLargeFont());

        UIElementScrollVertical scrollArea = new UIElementScrollVertical();

        scrollArea.SetLocation(1, 5, UIScaler.GetWidthUnits() - 2f, 21f);
        new UIElementBorder(scrollArea);

        // Start here
        float offset = 0;

        // Loop through all available quests
        foreach (RemoteQuest rq in remoteQuests)
        {
            string file      = rq.name + ".valkyrie";
            string questName = rq.GetData("name." + game.currentLang);
            if (questName.Length == 0)
            {
                questName = rq.GetData("name." + rq.GetData("defaultlanguage"));
            }
            if (questName.Length == 0)
            {
                questName = rq.name;
            }

            int remoteFormat = 0;
            int.TryParse(rq.GetData("format"), out remoteFormat);
            bool formatOK = (remoteFormat >= QuestData.Quest.minumumFormat) && (remoteFormat <= QuestData.Quest.currentFormat);

            if (!formatOK)
            {
                continue;
            }

            bool exists = File.Exists(saveLocation() + Path.DirectorySeparatorChar + file);
            bool update = true;
            if (exists)
            {
                string localHash  = localManifest.Get(rq.name, "version");
                string remoteHash = rq.GetData("version");

                update = !localHash.Equals(remoteHash);
            }

            bool has_stats_bar = false;


            Color bg         = Color.white;
            Color text_color = Color.black;
            if (exists)
            {
                if (update)
                {
                    // light pink
                    bg         = new Color(0.7f, 0.7f, 1f);
                    text_color = Color.black;
                }
                else
                {
                    // dark grey
                    bg         = new Color(0.1f, 0.1f, 0.1f);
                    text_color = Color.grey;
                }
            }

            // Frame
            ui = new UIElement(scrollArea.GetScrollTransform());
            ui.SetLocation(0.95f, offset, UIScaler.GetWidthUnits() - 4.9f, 3.6f);
            ui.SetBGColor(bg);
            if (update)
            {
                ui.SetButton(delegate { Selection(rq); });
            }
            offset += 0.05f;
            new UIElementBorder(ui, Color.grey);

            // Draw Image
            ui = new UIElement(scrollArea.GetScrollTransform());
            ui.SetLocation(1, offset, 3.5f, 3.5f);
            ui.SetBGColor(bg);
            if (update)
            {
                ui.SetButton(delegate { Selection(rq); });
            }

            if (rq.image != null)
            {
                ui.SetImage(rq.image);
            }

            ui = new UIElement(scrollArea.GetScrollTransform());
            ui.SetBGColor(Color.clear);
            ui.SetLocation(5, offset, UIScaler.GetWidthUnits() - 8, 2.5f);
            ui.SetTextPadding(1.2f);
            if (update && exists)
            {
                ui.SetText(new StringKey("val", "QUEST_NAME_UPDATE", questName), text_color);
            }
            else
            {
                ui.SetText(questName, text_color);
            }
            if (update)
            {
                ui.SetButton(delegate { Selection(rq); });
            }
            ui.SetTextAlignment(TextAnchor.MiddleLeft);
            ui.SetFontSize(Mathf.RoundToInt(UIScaler.GetSmallFont() * 1.4f));

            // Duration
            int lengthMax = 0;
            int.TryParse(rq.GetData("lengthmax"), out lengthMax);
            if (lengthMax > 0)
            {
                int lengthMin = 0;
                int.TryParse(rq.GetData("lengthmin"), out lengthMin);


                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetLocation(7f, offset + 2.3f, 4, 1);
                ui.SetText(new StringKey("val", "DURATION"), text_color);
                ui.SetTextAlignment(TextAnchor.MiddleLeft);
                ui.SetBGColor(Color.clear);
                if (update)
                {
                    ui.SetButton(delegate { Selection(rq); });
                }

                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetLocation(11f, offset + 2.3f, 5, 1);
                ui.SetText(lengthMin + "  -  " + lengthMax, text_color);
                ui.SetTextAlignment(TextAnchor.MiddleLeft);
                ui.SetBGColor(Color.clear);
                if (update)
                {
                    ui.SetButton(delegate { Selection(rq); });
                }
            }

            // Difficulty
            float difficulty = 0f;
            float.TryParse(rq.GetData("difficulty"), out difficulty);
            if (difficulty != 0)
            {
                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetLocation(UIScaler.GetHCenter() - 5.5f, offset + 2.3f, 6, 1);
                ui.SetText(new StringKey("val", "DIFFICULTY"), text_color);
                if (update)
                {
                    ui.SetButton(delegate { Selection(rq); });
                }
                ui.SetTextAlignment(TextAnchor.MiddleRight);
                ui.SetBGColor(Color.clear);

                string symbol = "π"; // will
                if (game.gameType is MoMGameType)
                {
                    symbol = new StringKey("val", "ICON_SUCCESS_RESULT").Translate();
                }

                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetLocation(UIScaler.GetHCenter(), offset + 1.8f, 9, 2);
                ui.SetText(symbol + symbol + symbol + symbol + symbol, text_color);
                ui.SetBGColor(Color.clear);
                ui.SetFontSize(UIScaler.GetMediumFont());
                if (update)
                {
                    ui.SetButton(delegate { Selection(rq); });
                }

                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetLocation(UIScaler.GetHCenter() + 1.05f + (difficulty * 6.9f), offset + 1.8f, (1 - difficulty) * 6.9f, 1.6f);
                Color filter = bg;
                filter.a = 0.7f;
                ui.SetBGColor(filter);
                if (update)
                {
                    ui.SetButton(delegate { Selection(rq); });
                }
            }

            // Statistics
            string filename = file.ToLower();
            if (game.stats != null && game.stats.scenarios_stats != null && game.stats.scenarios_stats.ContainsKey(filename))
            {
                ScenarioStats q_stats   = game.stats.scenarios_stats[filename];
                int           win_ratio = (int)(q_stats.scenario_avg_win_ratio * 100);

                StringKey STATS_AVERAGE_WIN_RATIO    = new StringKey("val", "STATS_AVERAGE_WIN_RATIO", win_ratio);
                StringKey STATS_NO_AVERAGE_WIN_RATIO = new StringKey("val", "STATS_NO_AVERAGE_WIN_RATIO", win_ratio);
                StringKey STATS_NB_USER_REVIEWS      = new StringKey("val", "STATS_NB_USER_REVIEWS", q_stats.scenario_play_count);
                StringKey STATS_AVERAGE_DURATION     = new StringKey("val", "STATS_AVERAGE_DURATION", (int)(q_stats.scenario_avg_duration));
                StringKey STATS_NO_AVERAGE_DURATION  = new StringKey("val", "STATS_NO_AVERAGE_DURATION");

                //  rating
                string symbol = "★";
                if (game.gameType is MoMGameType)
                {
                    symbol = new StringKey("val", "ICON_TENTACLE").Translate();
                }
                float rating           = q_stats.scenario_avg_rating / 10;
                float score_text_width = 0;

                ui = new UIElement(scrollArea.GetScrollTransform());

                ui.SetText(symbol + symbol + symbol + symbol + symbol, text_color);
                score_text_width = ui.GetStringWidth(symbol + symbol + symbol + symbol + symbol, (int)System.Math.Round(UIScaler.GetMediumFont() * 1.4f)) + 1;
                ui.SetLocation(UIScaler.GetRight(-12f), offset + 0.6f, score_text_width, 2);
                ui.SetBGColor(Color.clear);
                ui.SetFontSize((int)System.Math.Round(UIScaler.GetMediumFont() * 1.4f));
                ui.SetTextAlignment(TextAnchor.MiddleLeft);
                if (update)
                {
                    ui.SetButton(delegate { Selection(rq); });
                }

                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetLocation(UIScaler.GetRight(-12) + (rating * (score_text_width - 1)), offset + 0.6f, (1 - rating) * score_text_width, 2);
                Color filter = bg;
                filter.a = 0.7f;
                ui.SetBGColor(filter);
                if (update)
                {
                    ui.SetButton(delegate { Selection(rq); });
                }

                //  Number of user reviews
                float user_review_text_width = 0;
                ui = new UIElement(scrollArea.GetScrollTransform());
                user_review_text_width = ui.GetStringWidth(STATS_NB_USER_REVIEWS, UIScaler.GetSmallFont()) + 1;
                ui.SetText(STATS_NB_USER_REVIEWS, text_color);
                ui.SetLocation(UIScaler.GetRight(-12) + (score_text_width / 2) - (user_review_text_width / 2), offset + 2.3f, user_review_text_width, 1);
                ui.SetTextAlignment(TextAnchor.MiddleLeft);
                ui.SetBGColor(Color.clear);
                ui.SetFontSize(UIScaler.GetSmallFont());
                if (update)
                {
                    ui.SetButton(delegate { Selection(rq); });
                }

                if (q_stats.scenario_avg_duration > 0 || win_ratio >= 0)
                {
                    has_stats_bar = true;

                    // Additional information in frame
                    ui = new UIElement(scrollArea.GetScrollTransform());
                    ui.SetLocation(3.5f + 1f, offset + 3.6f, UIScaler.GetWidthUnits() - 4.9f - 3.5f - 0.05f, 1.2f);
                    if (exists)
                    {
                        ui.SetBGColor(bg);
                    }
                    else
                    {
                        ui.SetBGColor(new Color(0.8f, 0.8f, 0.8f));
                    }
                    if (update)
                    {
                        ui.SetButton(delegate { Selection(rq); });
                    }

                    //  average duration
                    ui = new UIElement(scrollArea.GetScrollTransform());
                    ui.SetLocation(6f, offset + 3.8f, 14, 1);
                    if (q_stats.scenario_avg_duration > 0)
                    {
                        ui.SetText(STATS_AVERAGE_DURATION, text_color);
                    }
                    else
                    {
                        ui.SetText(STATS_NO_AVERAGE_DURATION, text_color);
                    }
                    ui.SetTextAlignment(TextAnchor.MiddleLeft);
                    ui.SetBGColor(Color.clear);
                    if (update)
                    {
                        ui.SetButton(delegate { Selection(rq); });
                    }

                    //  average win ratio
                    ui = new UIElement(scrollArea.GetScrollTransform());
                    ui.SetLocation(UIScaler.GetHCenter() - 5.5f, offset + 3.8f, 15, 1);
                    if (win_ratio >= 0)
                    {
                        ui.SetText(STATS_AVERAGE_WIN_RATIO, text_color);
                    }
                    else
                    {
                        ui.SetText(STATS_NO_AVERAGE_WIN_RATIO, text_color);
                    }
                    ui.SetBGColor(Color.clear);
                    ui.SetTextAlignment(TextAnchor.MiddleCenter);
                    if (update)
                    {
                        ui.SetButton(delegate { Selection(rq); });
                    }
                }
            }

            // Size is 1.2 to be clear of characters with tails
            if (exists)
            {
                float string_width = 0;

                if (update)
                {
                    ui = new UIElement(scrollArea.GetScrollTransform());
                    ui.SetText(CommonStringKeys.UPDATE, Color.black);
                    string_width = ui.GetStringWidth(CommonStringKeys.UPDATE, UIScaler.GetSmallFont()) + 1.3f;
                    ui.SetButton(delegate { Delete(file); Selection(rq); });
                    ui.SetLocation(0.95f, offset + 3.6f, string_width, 1.2f);
                    ui.SetBGColor(new Color(0, 0.5f, 0.68f));           // 0080AF
                    new UIElementBorder(ui, new Color(0, 0.3f, 0.43f)); // 00516f
                }

                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetText(CommonStringKeys.DELETE, Color.black);
                string_width = ui.GetStringWidth(CommonStringKeys.DELETE, UIScaler.GetSmallFont()) + 1.3f;
                ui.SetButton(delegate { Delete(file); });
                ui.SetLocation(0.95f + UIScaler.GetWidthUnits() - 4.9f - string_width, offset + 3.6f, string_width, 1.2f);
                ui.SetBGColor(new Color(0.7f, 0, 0));
                new UIElementBorder(ui, new Color(0.45f, 0, 0));
            }

            if (has_stats_bar || exists)
            {
                offset += 1.2f;
            }

            offset += 4.6f;
        }

        foreach (KeyValuePair <string, Dictionary <string, string> > kv in localManifest.data)
        {
            // Only looking for files missing from remote
            bool onRemote = false;
            foreach (RemoteQuest rq in remoteQuests)
            {
                if (rq.name.Equals(kv.Key))
                {
                    onRemote = true;
                }
            }
            if (onRemote)
            {
                continue;
            }

            string type = localManifest.Get(kv.Key, "type");

            // Only looking for packages of this game type
            if (!game.gameType.TypeName().Equals(type))
            {
                continue;
            }

            string file = kv.Key + ".valkyrie";
            // Size is 1.2 to be clear of characters with tails
            if (File.Exists(saveLocation() + Path.DirectorySeparatorChar + file))
            {
                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetLocation(1, offset, UIScaler.GetWidthUnits() - 8, 1.2f);
                ui.SetTextPadding(1.2f);
                ui.SetText(file, Color.black);
                ui.SetBGColor(new Color(0.1f, 0.1f, 0.1f));
                ui.SetTextAlignment(TextAnchor.MiddleLeft);

                ui = new UIElement(scrollArea.GetScrollTransform());
                ui.SetLocation(UIScaler.GetWidthUnits() - 12, offset, 8, 1.2f);
                ui.SetText(CommonStringKeys.DELETE, Color.black);
                ui.SetTextAlignment(TextAnchor.MiddleLeft);
                ui.SetButton(delegate { Delete(file); });
                ui.SetBGColor(new Color(0.7f, 0, 0));
                offset += 2;
            }
        }

        scrollArea.SetScrollSize(offset);

        ui = new UIElement();
        ui.SetLocation(1, UIScaler.GetBottom(-3), 8, 2);
        ui.SetText(CommonStringKeys.BACK, Color.red);
        ui.SetButton(delegate { Cancel(); });
        ui.SetFont(game.gameType.GetHeaderFont());
        ui.SetFontSize(UIScaler.GetMediumFont());
        new UIElementBorder(ui, Color.red);
    }