private void CreateMissionsCards() { Vector3 position = missionCard.transform.position; if (MissionsService.missions.Length > 0) { missionCard.SetActive(true); } else { noMissionsCard.SetActive(true); } foreach (Mission mission in MissionsService.missions) { position = new Vector3(position.x, position.y, position.z); GameObject card = (GameObject)Instantiate(missionCard, position, Quaternion.identity); card.transform.SetParent(GameObject.Find("List").transform, false); MissionCard missionCardScript = card.GetComponent <MissionCard>(); missionCardScript.UpdateMissionCard(mission); } missionCard.gameObject.SetActive(false); AlertsService.removeLoadingAlert(); }
public void ShowMissionCard(MissionCard cd, Action <bool> action = null) { dynamicMissionCard.gameObject.SetActive(true); dynamicMissionCard.InitCard(cd); callback = action; gameObject.SetActive(true); fader.color = new Color(0, 0, 0, 0); fader.DOFade(.95f, .5f); cg2.DOFade(1, .5f); transform.GetChild(2).localScale = new Vector3(.85f, .85f, .85f); transform.GetChild(2).DOScale(1, .5f).SetEase(Ease.OutExpo); }
public void initMissionPanel(List <Quest> list) { for (int i = 0; i < list.Count; i++) { Quest quest = list[i]; Transform C = Instantiate(_Card) as Transform; C.SetParent(CardSR.content); C.localScale = Vector3.one; C.gameObject.SetActive(true); MissionCard _c = C.GetComponent <MissionCard>(); _c.MP = this; _c.initMissionCard(quest); CardList.Add(_c); } }
} //...should allow PSSE to work longer without needing an update. #endregion Properties public Database() { //bin init MegaStone = Properties.Resources.megaStone; MissionCard = Properties.Resources.missionCard; MonAbility = Properties.Resources.pokemonAbility; MonData = Properties.Resources.pokemonData; MonLevel = Properties.Resources.pokemonLevel; StagesMain = Properties.Resources.stageData; StagesEvent = Properties.Resources.stageDataEvent; StagesExpert = Properties.Resources.stageDataExtra; byte[][] files = { MegaStone, MonData, StagesMain, StagesEvent, StagesExpert, MonLevel, MonAbility, MissionCard }; string[] filenames = { "megaStone.bin", "pokemonData.bin", "stageData.bin", "stageDataEvent.bin", "stageDataExtra.bin", "pokemonLevel.bin", "pokemonAbility.bin", "missionCard.bin" }; string resourcedir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + Path.DirectorySeparatorChar + "resources" + Path.DirectorySeparatorChar; #region old "resource" code //I don't want PSSE to populate the resource folder by itself anymore but it could still be handy //if (!Directory.Exists(resourcedir)) // Directory.CreateDirectory(resourcedir); //for (int i = 0; i < files.Length; i++) //{ // if (!File.Exists(resourcedir + filenames[i])) // File.WriteAllBytes(resourcedir + filenames[i], files[i]); // else // files[i] = File.ReadAllBytes(resourcedir + filenames[i]); //} #endregion if (Directory.Exists(resourcedir)) { for (int i = 0; i < files.Length; i++) { if (File.Exists(resourcedir + filenames[i])) { files[i] = File.ReadAllBytes(resourcedir + filenames[i]); } } } //txt init SpeciesList = Properties.Resources.species.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.RemoveEmptyEntries); MonsList = Properties.Resources.mons.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.RemoveEmptyEntries); PokathlonList = Properties.Resources.pokathlon.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.RemoveEmptyEntries); MegaStartIndex = MonsList.ToList().IndexOf("Mega Venusaur"); MonStopIndex = MonsList.ToList().IndexOf("---", 1); //megas int entrylen = BitConverter.ToInt32(MonData, 0x4); Megas = new Tuple <int, int> [BitConverter.ToUInt32(MegaStone, 0) - 1]; for (int i = 0; i < Megas.Length; i++) { int monIndex = BitConverter.ToUInt16(MegaStone, MegaStone[0x10] + (i + 1) * 4) & 0x3FF; string str = "Mega " + MonsList[monIndex]; if (monIndex == 6 || monIndex == 150) { str += (monIndex != (BitConverter.ToUInt16(MegaStone, MegaStone[0x10] + i * 4) & 0x3FF)) ? " X" : " Y"; } byte[] data = MonData.Skip(0x50 + entrylen * MonsList.ToList().IndexOf(str)).Take(entrylen).ToArray(); int maxSpeedup = (BitConverter.ToInt32(data, 0xA) >> 7) & 0x7F; Megas[i] = new Tuple <int, int>(monIndex, maxSpeedup); } MegaList = new List <int>(); for (int i = 0; i < Megas.Length; i++) { MegaList.Add(Megas[i].Item1); } HasMega = new bool[MonsList.Length][]; for (int i = 0; i < MonsList.Length; i++) { HasMega[i] = new bool[2]; } for (int i = 0; i < Megas.Length; i++) { HasMega[BitConverter.ToUInt16(MegaStone, 0x54 + i * 4) & 0x3FF][(MegaStone[0x54 + (i * 4) + 1] >> 3) & 1] = true; } //pokemons Forms = new int[SpeciesList.Length]; Mons = new Tuple <int, int, bool, int, int, int[], int, Tuple <int, int> > [BitConverter.ToUInt32(MonData, 0)]; Rest = new Tuple <int, int> [Mons.Length]; for (int i = 0; i < Mons.Length; i++) { byte[] data = MonData.Skip(0x50 + entrylen * i).Take(entrylen).ToArray(); bool isMega = i >= MegaStartIndex && i <= MonsList.Count() - 1; int spec = (isMega && i <= MegaStartIndex + Megas.Length - 1) ? SpeciesList.ToList().IndexOf(MonsList[Megas[i - MegaStartIndex].Item1].Substring(0, (MonsList[Megas[i - MegaStartIndex].Item1].LastIndexOf(' ') <= 0) ? MonsList[Megas[i - MegaStartIndex].Item1].Length : MonsList[Megas[i - MegaStartIndex].Item1].LastIndexOf(' '))) : (BitConverter.ToInt32(data, 0xE) >> 6) & 0x7FF; int raiseMaxLevel = (BitConverter.ToInt16(data, 0x4)) & 0x3F; int basePower = (BitConverter.ToInt16(data, 0x3)) & 0x7; //ranges 1-7 for now (30-90 BP), may need an update later on int[] skillsadr = new int[] { 0x02, 0x20, 0x21, 0x22, 0x23 }, skill = new int[skillsadr.Length]; int j = 0, skillCount = 0; foreach (int adr in skillsadr) { skill[j] = data[adr] & 0x7F; //ranges 1-~100 for now ("Opportunist" to "Transform"), ordered list in MESSAGE_XX/message_PokedexXX.bin if (skill[j] != 0) { skillCount++; } j++; } skillCount = Math.Max(skillCount, 1); int type = (BitConverter.ToInt16(data, 0x01) >> 3) & 0x1F; //ranges 0-17 (normal - fairy) (https://gbatemp.net/threads/psse-pokemon-shuffle-save-editor.396499/page-33#post-6278446) int index = (BitConverter.ToInt16(data, 0)) & 0x3FF; //ranges 1-999, it's the number you can see on the team selection menu Rest[i] = new Tuple <int, int>(index, skillCount); //Mons has more than 7 arguments so 8th one and beyond must be included in another Tuple Mons[i] = new Tuple <int, int, bool, int, int, int[], int, Tuple <int, int> >(spec, Forms[spec], isMega, raiseMaxLevel, basePower, skill, type, Rest[i]); Forms[spec]++; } //pokathlon PokathlonRand = new int[PokathlonList.Length / 2][]; for (int i = 0; i < PokathlonRand.Length; i++) { PokathlonRand[i] = new int[2]; Int32.TryParse(PokathlonList[2 * i], out PokathlonRand[i][0]); Int32.TryParse(PokathlonList[1 + 2 * i], out PokathlonRand[i][1]); } //missions Missions = new bool[BitConverter.ToInt32(MissionCard, 0)][]; for (int i = 0; i < Missions.Length; i++) { Missions[i] = new bool[10]; int ientrylen = BitConverter.ToInt32(MissionCard, 0x4); byte[] data = MissionCard.Skip(BitConverter.ToInt32(MissionCard, 0x10) + i * ientrylen).Take(ientrylen).ToArray(); for (int j = 0; j < Missions[i].Length; j++) { Missions[i][j] = BitConverter.ToInt16(data, 0x8 + 2 * j) != 0; } } //dictionnary, this is some really bad code here byte[] HexValue = Properties.Resources.messagePokedex_US; string StrValue = ""; List <string> List = new List <string>(); for (int i = 0; i < HexValue.Length; i += 2) { if (BitConverter.ToChar(HexValue, i) == '\0' && StrValue != "" && !(StrValue.EndsWith("\u0001ă\u0001\u0003\u0003慮敭") || StrValue.EndsWith("\u0001ă\u0001\u0003\u0005敭慧慎敭"))) { List.Add(StrValue.Replace("\u0001ă\u0001\u0003\u0003慮敭\0", "[name]").Replace("\u0001ă\u0001\u0003\u0005敭慧慎敭\0", "[name]")); StrValue = ""; } else { StrValue += BitConverter.ToChar(HexValue, i); } } SkillsList = List.Skip(List.IndexOf("Opportunist")).Take(List.IndexOf("Attacks can occasionally deal\ngreater damage than usual.") - List.IndexOf("Opportunist")).ToArray(); SkillsTextList = List.Skip(List.IndexOf("Attacks can occasionally deal\ngreater damage than usual.")).Take(List.IndexOf("Attacks can occasionally deal\ngreater damage than usual.") - List.IndexOf("Opportunist")).ToArray(); }
public void InitCard(MissionCard card) { missionCard = card; Func <string[], string, string> parse = (string[] toParse, string sep) => { string t = ""; for (int i = 0; i < toParse.Length; i++) { t += toParse[i]; if (i < toParse.Length - 1) { t += $"{sep}"; } } return(t); }; //card color if (missionCard.missionType.Any(x => x == MissionType.Finale)) { cardImage.color = Color.yellow; } else if (missionCard.missionType.Any(x => x == MissionType.Story)) { cardImage.color = new Color(0, 164f / 255f, 1); } else if (missionCard.missionType.Any(x => x == MissionType.Personal)) { cardImage.color = Color.red; } else if (missionCard.missionType.Any(x => x == MissionType.Ally)) { cardImage.color = Color.green; } else if (missionCard.missionType.Any(x => x == MissionType.Agenda)) { cardImage.color = new Color(0, 82f / 255f, 128f / 255f); } else if (missionCard.missionType.Any(x => x == MissionType.Threat)) { cardImage.color = new Color(1, 142f / 255f, 0); } else { cardImage.color = Color.gray; } //description + bonus text descriptionText.text = missionCard.descriptionText.Replace("<i>", "").Replace("</i>", "").Replace("\n", "\n\n"); descriptionText.text += $"\n\n<color=orange>{missionCard.bonusText}</color>"; //tags titleTagsText.text = $"{missionCard.name}\n<size=20><color=orange>{parse( missionCard.tagsText, " - " )}"; //reward rewardText.text = $"{DataStore.uiLanguage.uiMainApp.rewardUC}: " + missionCard.rebelRewardText + missionCard.imperialRewardText; rewardBox.SetActive(!string.IsNullOrEmpty(missionCard.rebelRewardText) || !string.IsNullOrEmpty(missionCard.imperialRewardText)); //hero/villain name heroVillainText.text = missionCard.heroText + missionCard.villainText + missionCard.allyText; heroBox.SetActive(!string.IsNullOrEmpty(heroVillainText.text)); if (!string.IsNullOrEmpty(missionCard.heroText) || !string.IsNullOrEmpty(missionCard.allyText)) { heroBox.GetComponent <Image>().color = new Color(0, 1, 160f / 255f); } else { heroBox.GetComponent <Image>().color = new Color(1, 40f / 255f, 0); } //hero icon? if (!string.IsNullOrEmpty(missionCard.heroText)) { mugshot.sprite = Resources.Load <Sprite>($"Cards/Heroes/{missionCard.hero}"); } //villain icon? else if (missionCard.villain.Length > 0) { mugshot.sprite = Resources.Load <Sprite>($"Cards/Villains/{missionCard.villain[0].Replace( "DG", "M" )}"); } //ally icon? else if (missionCard.ally.Length > 0) { mugshot.sprite = Resources.Load <Sprite>($"Cards/Allies/{missionCard.ally[0].Replace( "A", "M" )}"); } //page # and expansion string page = missionCard.page > 0 ? $"{DataStore.uiLanguage.uiMainApp.pageUC} {missionCard.page}, " : ""; typePageExpansionText.text = $"{page}{missionCard.expansionText}"; //timeline dateBox.SetActive(missionCard.timePeriod.Length > 0); if (missionCard.timePeriod.Length > 0) { dateText.text = $"Time Period: {missionCard.timePeriod[0]}-{missionCard.timePeriod[1]}"; } //expansion icon expansionImage.sprite = expansionSprites[(int)missionCard.expansion]; if (missionCard.expansion == Expansion.Other && !missionCard.missionType.Contains(MissionType.Agenda)) { expansionImage.sprite = expansionSprites[8]; } }
} //...should allow PSSE to work longer without needing an update. #endregion Properties public Database(bool shwmsg = false, bool dev = false) { //if a new resource file is needed, don't forget to add a line to Resource_Popup's TLP ! string[] filenames = { "megaStone.bin", "pokemonData.bin", "stageData.bin", "stageDataEvent.bin", "stageDataExtra.bin", "pokemonLevel.bin", "pokemonAbility.bin", "missionCard.bin", "messagePokedex_US.bin", "pokeLoad.bin" }; string resourcedir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + Path.DirectorySeparatorChar + "resources" + Path.DirectorySeparatorChar; bool[] overRide = new bool[filenames.Length]; for (int i = 0; i < overRide.Length; i++) { overRide[i] = true; } if (shwmsg) { string[] fn = new string[filenames.Length]; for (int i = 0; i < fn.Length; i++) { fn[i] = filenames[i]; } Array.Sort(fn, (x, y) => String.Compare(x, y)); using (var form = new Resources_Popup(fn, resourcedir, dev)) { form.ShowDialog(); if (form.DialogResult == DialogResult.OK && dev) { for (int i = 0; i < overRide.Length; i++) { overRide[i] = form.retChk[Array.IndexOf(fn, filenames[i])]; } } } } //bin init MegaStone = Properties.Resources.megaStone; MissionCard = Properties.Resources.missionCard; MonAbility = Properties.Resources.pokemonAbility; MonData = Properties.Resources.pokemonData; MonLevel = Properties.Resources.pokemonLevel; StagesMain = Properties.Resources.stageData; StagesEvent = Properties.Resources.stageDataEvent; StagesExpert = Properties.Resources.stageDataExtra; MessageDex = Properties.Resources.messagePokedex_US; PokeLoad = Properties.Resources.pokeLoad; //resources override if (Directory.Exists(resourcedir)) { for (int i = 0; i < filenames.Length; i++) { if (File.Exists(resourcedir + filenames[i]) && overRide[i]) { switch (i) //don't forget that part or resources files won't override Database files, add an entry if a file is added above { case 0: MegaStone = File.ReadAllBytes(resourcedir + filenames[i]); break; case 1: MonData = File.ReadAllBytes(resourcedir + filenames[i]); break; case 2: StagesMain = File.ReadAllBytes(resourcedir + filenames[i]); break; case 3: StagesEvent = File.ReadAllBytes(resourcedir + filenames[i]); break; case 4: StagesExpert = File.ReadAllBytes(resourcedir + filenames[i]); break; case 5: MonLevel = File.ReadAllBytes(resourcedir + filenames[i]); break; case 6: MonAbility = File.ReadAllBytes(resourcedir + filenames[i]); break; case 7: MissionCard = File.ReadAllBytes(resourcedir + filenames[i]); break; case 8: MessageDex = File.ReadAllBytes(resourcedir + filenames[i]); break; case 9: PokeLoad = File.ReadAllBytes(resourcedir + filenames[i]); break; default: MessageBox.Show("Error loading resources :\nfilename = " + (filenames[i] != null ? filenames[i] : "null") + "\ni = " + i); break; } } } } //txt init SpeciesList = Properties.Resources.species.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.RemoveEmptyEntries); MonsList = Properties.Resources.mons.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.RemoveEmptyEntries); //PokathlonList = Properties.Resources.pokathlon.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.RemoveEmptyEntries); MegaStartIndex = MonsList.ToList().IndexOf("Mega Venusaur"); MonStopIndex = MonsList.ToList().IndexOf("---", 1); //megas int entrylen = BitConverter.ToInt32(MonData, 0x4); Megas = new Tuple <int, int> [BitConverter.ToUInt32(MegaStone, 0) - 1]; for (int i = 0; i < Megas.Length; i++) { int monIndex = BitConverter.ToUInt16(MegaStone, MegaStone[0x10] + (i + 1) * 4) & 0x3FF; string str = "Mega " + MonsList[monIndex]; int spec = (BitConverter.ToInt32(MonData.Skip(0x50 + entrylen * monIndex).Take(entrylen).ToArray(), 0xE) >> 6) & 0x7FF; if (spec == 6 || spec == 150) { str += (monIndex != (BitConverter.ToUInt16(MegaStone, MegaStone[0x10] + i * 4) & 0x3FF)) ? " X" : " Y"; } byte[] data = MonData.Skip(0x50 + entrylen * MonsList.ToList().IndexOf(str)).Take(entrylen).ToArray(); int maxSpeedup = (BitConverter.ToInt32(data, 0xA) >> 7) & 0x7F; Megas[i] = new Tuple <int, int>(monIndex, maxSpeedup); } MegaList = new List <int>(); for (int i = 0; i < Megas.Length; i++) { MegaList.Add(Megas[i].Item1); } HasMega = new bool[MonsList.Length][]; for (int i = 0; i < MonsList.Length; i++) { HasMega[i] = new bool[2]; } for (int i = 0; i < Megas.Length; i++) { HasMega[BitConverter.ToUInt16(MegaStone, 0x54 + i * 4) & 0x3FF][(MegaStone[0x54 + (i * 4) + 1] >> 3) & 1] = true; } //pokemons Forms = new int[SpeciesList.Length]; Mons = new dbItem[BitConverter.ToUInt32(MonData, 0)]; for (int i = 0; i < Mons.Length; i++) { byte[] data = MonData.Skip(0x50 + entrylen * i).Take(entrylen).ToArray(); bool isMega = i >= MegaStartIndex && i <= MonsList.Count() - 1; int spec = (isMega && i <= MegaStartIndex + Megas.Length - 1) ? SpeciesList.ToList().IndexOf(MonsList[Megas[i - MegaStartIndex].Item1].Substring(0, (MonsList[Megas[i - MegaStartIndex].Item1].LastIndexOf(' ') <= 0) ? MonsList[Megas[i - MegaStartIndex].Item1].Length : MonsList[Megas[i - MegaStartIndex].Item1].LastIndexOf(' '))) : (BitConverter.ToInt32(data, 0xE) >> 6) & 0x7FF; int raiseMaxLevel = (BitConverter.ToInt16(data, 0x4)) & 0x3F; int basePower = (BitConverter.ToInt16(data, 0x3)) & 0x7; //ranges 1-7 for now (30-90 BP), may need an update later on int[] skillsadr = new int[] { 0x02, 0x20, 0x21, 0x22, 0x23 }, skill = new int[skillsadr.Length]; int j = 0, skillCount = 0; foreach (int adr in skillsadr) { skill[j] = data[adr]; //ranges 1-~130 for now, ordered list in MESSAGE_XX/message_PokedexXX.bin ("Opportunist" to "Transform" then a bunch more with a lot of placeholders) if (skill[j] != 0) { skillCount++; } j++; } skillCount = Math.Max(skillCount, 1); int type = (BitConverter.ToInt16(data, 0x01) >> 3) & 0x1F; //ranges 0-17 (normal - fairy) (https://gbatemp.net/threads/psse-pokemon-shuffle-save-editor.396499/page-33#post-6278446) int index = (BitConverter.ToInt16(data, 0)) & 0x3FF; //ranges 1-999, it's the number you can see on the team selection menu Mons[i] = new dbItem(spec, Forms[spec], isMega, raiseMaxLevel, basePower, skill, type, index, skillCount); Forms[spec]++; } //Survival mode int smEntry = BitConverter.ToInt32(PokeLoad, 0x4), smSkip = BitConverter.ToInt32(PokeLoad, 0x10), smTake = BitConverter.ToInt32(PokeLoad, 0x14); Pokathlon = new List <int> [BitConverter.ToInt16(PokeLoad.Skip(smSkip + smTake - smEntry).Take(smEntry).ToArray(), 0) & 0x3FF]; //# of entries doesn't match # of steps since some are collided so I take the last entry and read its 'lowStep' value (should compare to 'highStep' but I don't want to overcomplicate thigns for now) for (int i = 0; i < BitConverter.ToInt32(PokeLoad, 0); i++) { byte[] data = PokeLoad.Skip(smSkip + i * smEntry).Take(smEntry).ToArray(); int lowStep = BitConverter.ToInt16(data, 0) & 0x3FF, highStep = (BitConverter.ToInt16(data, 0x01) >> 2) & 0x3FF; //if highStep !=0 then data[] applies to all steps in the lowStep - highStep range int min = (BitConverter.ToInt16(data, 0x02) >> 4) & 0xFFF, max = BitConverter.ToInt16(data, 0x04) & 0xFFF; //if max !=0 then all stages in min-max range are possibilities for corresponding step(s) List <int> stagesList = Enumerable.Range(min, max != 0 ? max - min + 1 : 1).ToList(); for (int j = 0x08; j < (data.Length - 3); j += 4) //weird pattern for excluded stages : each 32-bits block starting at 0x08 contains 3 10-bits long stages # { int exception = 0; for (int w = 0; w < 3; w++) { exception = (BitConverter.ToInt32(data, j) >> (w * 10)) & 0x3FF; if (exception == 0) { break; } else if (stagesList.Contains(exception)) { stagesList.Remove(exception); } } if (exception == 0) { break; } } foreach (int step in Enumerable.Range(lowStep, 1 + Math.Max(0, highStep - lowStep))) { Pokathlon[step - 1] = stagesList; } } #region old Survival //pokathlon //PokathlonRand = new int[PokathlonList.Length / 2][]; //for (int i = 0; i < PokathlonRand.Length; i++) //{ // PokathlonRand[i] = new int[2]; // Int32.TryParse(PokathlonList[2 * i], out PokathlonRand[i][0]); // Int32.TryParse(PokathlonList[1 + 2 * i], out PokathlonRand[i][1]); //} #endregion //missions Missions = new bool[BitConverter.ToInt32(MissionCard, 0)][]; for (int i = 0; i < Missions.Length; i++) { Missions[i] = new bool[10]; int ientrylen = BitConverter.ToInt32(MissionCard, 0x4); byte[] data = MissionCard.Skip(BitConverter.ToInt32(MissionCard, 0x10) + i * ientrylen).Take(ientrylen).ToArray(); for (int j = 0; j < Missions[i].Length; j++) { Missions[i][j] = BitConverter.ToInt16(data, 0x8 + 2 * j) != 0; } } //dictionnary (new) string temp = Encoding.Unicode.GetString(MessageDex.Skip(BitConverter.ToInt32(MessageDex, 0x08)).Take(BitConverter.ToInt32(MessageDex, 0x0C) - 0x17).ToArray()); //Relevant chunk specified in .bin file, UTF16 Encoding, 17 bytes at the end are a useless stamp (data.messagePokedex) temp = temp.Replace(Encoding.Unicode.GetString(MessageDex.Skip(BitConverter.ToInt32(MessageDex, 0x08)).Take(0x10).ToArray()), "[name]"); //because this variable ends with 0x00 it messes with Split() later on, so I replace it here temp = temp.Replace(Encoding.Unicode.GetString(new byte[] { 0x01, 0x00, 0x03, 0x01, 0x01, 0x00, 0x03, 0x00, 0x05, 0x00, 0x6D, 0x65, 0x67, 0x61, 0x4E, 0x61, 0x6D, 0x65, 0x00, 0x00 }), "[megaName]"); //same but this variable isn't declared on a fixed position so I copied it directly string[] arr = temp.Split((char)0x00); //split the single string in an array arr = arr.Skip(Array.IndexOf(arr, "Opportunist")).ToArray(); //we only care for skills so I get rid of anything before Opportunist for (int i = 0; i < arr.Length; i++) { if (String.IsNullOrEmpty(arr[i])) { arr[i] = "-Placeholder-"; //make sure there is no empty strings just in case } } /* This code below separates Skills entries from Text entries while ignoring a few mega-skills entries : * Right now (1.5.7) the list of strings looks like that : [Skills1][Text for Skills1][Text for mega skills][Skills2][Text for Skills2][Skills3][Text for Skills3]. * If another group of [Skills][Text for skills] is ever added this will need a 3rd string to concatenate. * Also, note that there is no [Mega Skills], which is why I didn't implement it yet (the names of Mega Skills are probably inside another file). */ int a = Array.IndexOf(arr, "Opportunist"), b = Array.IndexOf(arr, "Transform") + 1, c = Array.IndexOf(arr, "Big Wave"), d = Array.IndexOf(arr, "Super Cheer") + 1, e = Array.IndexOf(arr, "Not Caught"), f = Array.IndexOf(arr, "Hammering Streak") + 1; string[] s1 = arr.Skip(a).Take(b - a).ToArray(), s2 = arr.Skip(c).Take(d - c).ToArray(), s3 = arr.Skip(e).Take(f - e).ToArray(); string[] st1 = arr.Skip(b).Take(b - a).ToArray(), st2 = arr.Skip(d).Take(d - c).ToArray(), st3 = arr.Skip(f).Take(f - e).ToArray(); string[] Skills = new string[s1.Length + s2.Length + s3.Length], SkillsT = new string[Skills.Length];; s1.CopyTo(Skills, 0); s2.CopyTo(Skills, s1.Length); SkillsList = Skills; st1.CopyTo(SkillsT, 0); st2.CopyTo(SkillsT, s1.Length); SkillsTextList = SkillsT; }