using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using MaidStatus; using UnityEngine; [Serializable] public class ScenarioData { public ScenarioData(CsvParser csv, int cy) { ScenarioData $this = this; Action action = delegate(ScenarioData.PlayableCondition condition, int cx) { if (csv.IsCellToExistData(cx, cy) && !$this.m_PlayableData.ContainsKey(condition)) { string cellAsString2 = csv.GetCellAsString(cx, cy); if (condition == ScenarioData.PlayableCondition.関係 && cellAsString2.Contains(",")) { HashSet hashSet = new HashSet(); IEnumerator enumerator = Enum.GetValues(typeof(AdditionalRelation)).GetEnumerator(); try { while (enumerator.MoveNext()) { object obj = enumerator.Current; hashSet.Add(EnumConvert.GetString((AdditionalRelation)obj)); } } finally { IDisposable disposable; if ((disposable = (enumerator as IDisposable)) != null) { disposable.Dispose(); } } foreach (string text in cellAsString2.Split(new char[] { ',' })) { string text2 = text.Trim(); if (hashSet.Contains(text2)) { if (!$this.m_PlayableData.ContainsKey(ScenarioData.PlayableCondition.追加関係)) { $this.m_PlayableData.Add(ScenarioData.PlayableCondition.追加関係, new ScenarioData.PlayableData(text2, ScenarioData.PlayableCondition.追加関係)); } } else if (text2 == "嫁") { $this.m_PlayableData.Add(ScenarioData.PlayableCondition.特殊関係, new ScenarioData.PlayableData(text2, ScenarioData.PlayableCondition.特殊関係)); } else if (!$this.m_PlayableData.ContainsKey(condition)) { $this.m_PlayableData.Add(condition, new ScenarioData.PlayableData(text2, condition)); } } } else { $this.m_PlayableData.Add(condition, new ScenarioData.PlayableData(cellAsString2, condition)); } } }; for (int i = 0; i < csv.max_cell_x; i++) { switch (i) { case 0: this.ID = csv.GetCellAsInteger(i, cy); break; case 1: this.Title = csv.GetCellAsString(i, cy); break; case 2: this.EventContents = csv.GetCellAsString(i, cy); break; case 3: action(ScenarioData.PlayableCondition.好感度, i); break; case 4: action(ScenarioData.PlayableCondition.時間帯, i); break; case 5: action(ScenarioData.PlayableCondition.シナリオ, i); break; case 6: action(ScenarioData.PlayableCondition.属性, i); break; case 7: action(ScenarioData.PlayableCondition.パラメ\u30FCタ, i); break; case 8: action(ScenarioData.PlayableCondition.性癖, i); break; case 9: action(ScenarioData.PlayableCondition.ジョブクラス, i); break; case 10: action(ScenarioData.PlayableCondition.夜伽クラス, i); break; case 11: action(ScenarioData.PlayableCondition.関係, i); break; case 12: action(ScenarioData.PlayableCondition.アイテム, i); break; case 13: action(ScenarioData.PlayableCondition.施設, i); break; case 14: action(ScenarioData.PlayableCondition.NTRブロック, i); break; case 15: this.IconName = csv.GetCellAsString(i, cy); break; case 16: this.ScenarioScript = csv.GetCellAsString(i, cy); break; case 17: { string cellAsString = csv.GetCellAsString(i, cy); if (!string.IsNullOrEmpty(cellAsString)) { this.ScriptLabel = ((cellAsString.IndexOf("*") < 0) ? ("*" + cellAsString) : cellAsString); } break; } case 18: this.EventMaidNum = ((!csv.IsCellToExistData(i, cy)) ? 0 : csv.GetCellAsInteger(i, cy)); break; case 19: this.IsImportant = (csv.GetCellAsString(i, cy) == "重要"); break; case 20: this.IsOncePlayOnly = !csv.IsCellToExistData(i, cy); break; case 21: this.Notification = csv.GetCellAsString(i, cy); break; case 22: this.ConditionText = csv.GetCellAsString(i, cy).Replace("\n", "&").Replace("\"", string.Empty).Split(new char[] { '&' }); break; case 23: action(ScenarioData.PlayableCondition.性経験, i); break; case 24: action(ScenarioData.PlayableCondition.契約, i); break; case 25: action(ScenarioData.PlayableCondition.新ボディブロック, i); break; case 26: action(ScenarioData.PlayableCondition.メインキャラとのボディ一致チェック, i); break; } } this.CheckPlayableCondition(false); } public ScenarioData() { } public bool IsOncePlayed { get; private set; } public bool IsPlayable { get { return (!this.IsOncePlayOnly || !this.IsOncePlayed) && (this.ConditionCount == 0 || this.CheckPlayableCondition(false)); } } public bool ImportantPlayable { get { return (!this.IsOncePlayOnly || !this.IsOncePlayed) && this.IsImportant && this.CheckPlayableCondition(true); } } private bool m_ContainsConditionScenario { get { return this.m_PlayableData.ContainsKey(ScenarioData.PlayableCondition.シナリオ); } } public int ConditionCount { get { return this.m_PlayableData.Count; } } public int EventMaidCount { get { return this.m_EventMaid.Count; } } public bool NotPlayAgain { get { return this.IsOncePlayOnly && this.IsOncePlayed; } } public string NotLineTitle { get { return this.Title.Replace("\n", string.Empty); } } public string TitleTerm { get { return "SceneScenarioSelect/" + this.ID.ToString() + "/タイトル"; } } public string EventContentTerm { get { return "SceneScenarioSelect/" + this.ID.ToString() + "/内容"; } } public string NotificationTerm { get { return "SceneScenarioSelect/通知時表記/" + this.Notification; } } public string[] ConditionTextTerms { get { List list = new List(); foreach (string str in this.ConditionText) { list.Add("SceneScenarioSelect/条件文/" + str); } return list.ToArray(); } } public bool IsFixedMaid { get; private set; } public static bool operator true(ScenarioData data) { return data != null; } public static bool operator false(ScenarioData data) { return data == null; } public static bool operator !(ScenarioData data) { return data == null; } private bool CheckPlayableCondition(bool update_important = false) { bool flag = false; this.m_EventMaid.Clear(); if (this.m_PlayableData == null) { return false; } this.m_ExistMaidUpdate = false; bool flag2 = true; bool flag3 = false; foreach (ScenarioData.PlayableCondition playableCondition in this.m_PlayableData.Keys) { if (!update_important || playableCondition != ScenarioData.PlayableCondition.時間帯) { List before = new List(this.m_EventMaid); flag = this.CheckPlayableCondition(playableCondition, true); if (!flag) { break; } if (!flag2 && flag3 && this.m_ExistMaidUpdate) { this.m_EventMaid = (from e in this.m_EventMaid where before.Contains(e) select e).ToList(); if (this.m_EventMaid.Count == 0) { flag = false; break; } } flag2 = false; if (!flag3) { flag3 = (this.m_EventMaid.Count > 0); if (this.m_ExistMaidUpdate && this.EventMaidCount == 0) { flag = false; break; } } } } flag &= this.IsEnoughEventMaid(); return flag; } public bool CheckPlayableCondition(ScenarioData.PlayableCondition condition, bool maid_update = true) { if (!this.m_PlayableData.ContainsKey(condition)) { return false; } ScenarioData.PlayableData playableData = this.m_PlayableData[condition]; CharacterMgr characterMgr = GameMain.Instance.CharacterMgr; FacilityManager facilityMgr = GameMain.Instance.FacilityMgr; bool and_operator = playableData.StringData.IndexOf("&") >= 0; bool or_operator = playableData.StringData.IndexOf("|") >= 0; char c = ','; if (and_operator && or_operator) { Debug.LogError("条件演算子が混在してます"); } else if (and_operator) { c = '&'; } else if (or_operator) { c = '|'; } bool isOk = and_operator; Action set_ok = delegate(bool set_val) { if (and_operator) { isOk = (isOk && set_val); } else { isOk = (isOk || set_val); } }; Action add_maid = delegate(Maid maid) { if (maid_update) { this.AddEventMaid(maid); } set_ok(true); }; Action remove_maid = delegate(Maid maid) { if (and_operator && this.m_EventMaid.Contains(maid)) { set_ok(false); } if (maid_update && !or_operator) { this.RemoveEventMaid(maid, false); } }; Action action = delegate(Maid maid, bool check_ok) { if (check_ok) { add_maid(maid); } else { remove_maid(maid); } }; bool maid_check = false; Action action2 = delegate() { if (!maid_check && maid_update) { this.m_EventMaid.Clear(); } this.m_ExistMaidUpdate = true; maid_check = true; }; foreach (string text in playableData.StringData.Split(new char[] { c })) { switch (condition) { case ScenarioData.PlayableCondition.好感度: { int num = int.Parse(text); action2(); for (int j = 0; j < characterMgr.GetStockMaidCount(); j++) { Maid stockMaid = characterMgr.GetStockMaid(j); action(stockMaid, stockMaid.status.likability >= num); } break; } case ScenarioData.PlayableCondition.時間帯: if (text == "昼") { set_ok(characterMgr.status.isDaytime); } else { set_ok(!characterMgr.status.isDaytime); } break; case ScenarioData.PlayableCondition.属性: { string[] array2 = text.Split(new char[] { '.' }); action2(); for (int k = 0; k < characterMgr.GetStockMaidCount(); k++) { Maid stockMaid2 = characterMgr.GetStockMaid(k); if (text.IndexOf("NPCキャラ") >= 0) { this.IsFixedMaid = true; if (stockMaid2.status.heroineType == HeroineType.Sub && stockMaid2.status.subCharaData.uniqueName == array2[1]) { add_maid(stockMaid2); } } else if (text.IndexOf("NPC以外") >= 0) { action(stockMaid2, stockMaid2.status.heroineType != HeroineType.Sub); } else if (text.IndexOf("移籍") >= 0) { if (stockMaid2.status.heroineType == HeroineType.Transfer) { if (text != null) { if (text == "移籍メイド") { add_maid(stockMaid2); goto IL_463; } if (text == "雇用移籍メイド") { action(stockMaid2, !stockMaid2.status.mainChara); goto IL_463; } } string convertPersonal = GameMain.Instance.ScenarioSelectMgr.GetConvertPersonal(stockMaid2); if (text.IndexOf("固定") >= 0) { this.IsFixedMaid = true; if (text == "固定移籍メイド") { action(stockMaid2, stockMaid2.status.mainChara && ScenarioData.m_MainMaidList.Contains(convertPersonal)); } else { action(stockMaid2, stockMaid2.status.mainChara && text == "固定移籍" + convertPersonal); } } else if (GameMain.Instance.ScenarioSelectMgr.ExistConvertData(convertPersonal)) { action(stockMaid2, "移籍" + convertPersonal == text); } } IL_463:; } else if (stockMaid2.status.heroineType == HeroineType.Original) { if (text != null) { if (text == "オリジナルメイド") { add_maid(stockMaid2); goto IL_5A3; } if (text == "雇用メイド") { action(stockMaid2, !stockMaid2.status.mainChara); goto IL_5A3; } } string convertPersonal2 = GameMain.Instance.ScenarioSelectMgr.GetConvertPersonal(stockMaid2); if (text.IndexOf("固定") >= 0) { this.IsFixedMaid = true; if (text == "固定メイド") { action(stockMaid2, stockMaid2.status.mainChara && ScenarioData.m_MainMaidList.Contains(convertPersonal2)); } else { action(stockMaid2, stockMaid2.status.mainChara && text == "固定" + convertPersonal2); } } else if (GameMain.Instance.ScenarioSelectMgr.ExistConvertData(convertPersonal2)) { action(stockMaid2, convertPersonal2 == text); } } IL_5A3:; } break; } case ScenarioData.PlayableCondition.シナリオ: { int id = -1; ScenarioData scenarioData; if (int.TryParse(text, out id)) { scenarioData = GameMain.Instance.ScenarioSelectMgr.GetScenarioData(id); } else { scenarioData = GameMain.Instance.ScenarioSelectMgr.GetScenarioData(text); } if (scenarioData != null) { action2(); for (int l = 0; l < characterMgr.GetStockMaidCount(); l++) { Maid stockMaid3 = characterMgr.GetStockMaid(l); action(stockMaid3, scenarioData.IsOncePlayed && stockMaid3.status.GetEventEndFlag(scenarioData.ID)); } } else if (text.IndexOf("シナリオフラグ") >= 0) { set_ok(characterMgr.status.GetFlag(text.Split(new char[] { ':' })[1]) == 1); } else if (text.IndexOf("メイドフラグ") >= 0) { action2(); for (int m = 0; m < characterMgr.GetStockMaidCount(); m++) { Maid stockMaid4 = characterMgr.GetStockMaid(m); action(stockMaid4, stockMaid4.status.GetFlag(text.Split(new char[] { ':' })[1]) == 1); } } break; } case ScenarioData.PlayableCondition.パラメ\u30FCタ: { action2(); ParametersPack parametersPack = new ParametersPack(); for (int n = 0; n < characterMgr.GetStockMaidCount(); n++) { Maid stockMaid5 = characterMgr.GetStockMaid(n); parametersPack.Clear(); parametersPack.Parse(text, ','); action(stockMaid5, parametersPack.GreaterThanOrEqualToStatus(stockMaid5.status)); } break; } case ScenarioData.PlayableCondition.性癖: action2(); for (int num2 = 0; num2 < characterMgr.GetStockMaidCount(); num2++) { Maid stockMaid6 = characterMgr.GetStockMaid(num2); Propensity.Data[] valueArray = stockMaid6.status.propensitys.GetValueArray(); bool flag = false; for (int num3 = 0; num3 < valueArray.Count(); num3++) { if (valueArray[num3].drawName == text) { flag = true; add_maid(stockMaid6); break; } } if (!flag) { remove_maid(stockMaid6); } } break; case ScenarioData.PlayableCondition.ジョブクラス: action2(); for (int num4 = 0; num4 < characterMgr.GetStockMaidCount(); num4++) { Maid stockMaid7 = characterMgr.GetStockMaid(num4); SortedDictionary> allDatas = stockMaid7.status.jobClass.GetAllDatas(); bool flag2 = false; for (int num5 = 0; num5 < allDatas.Count>>(); num5++) { if (allDatas[num5].data.drawName == text) { flag2 = true; add_maid(stockMaid7); break; } } if (!flag2) { remove_maid(stockMaid7); } } break; case ScenarioData.PlayableCondition.夜伽クラス: action2(); for (int num6 = 0; num6 < characterMgr.GetStockMaidCount(); num6++) { Maid stockMaid8 = characterMgr.GetStockMaid(num6); SortedDictionary> allDatas2 = stockMaid8.status.yotogiClass.GetAllDatas(); bool flag3 = false; for (int num7 = 0; num7 < allDatas2.Count>>(); num7++) { if (allDatas2[num7].data.drawName == text) { flag3 = true; add_maid(stockMaid8); break; } } if (!flag3) { remove_maid(stockMaid8); } } break; case ScenarioData.PlayableCondition.関係: action2(); for (int num8 = 0; num8 < characterMgr.GetStockMaidCount(); num8++) { Maid stockMaid9 = characterMgr.GetStockMaid(num8); action(stockMaid9, EnumConvert.GetString(stockMaid9.status.relation) == text); } break; case ScenarioData.PlayableCondition.追加関係: action2(); for (int num9 = 0; num9 < characterMgr.GetStockMaidCount(); num9++) { Maid stockMaid10 = characterMgr.GetStockMaid(num9); action(stockMaid10, EnumConvert.GetString(stockMaid10.status.additionalRelation) == text); } break; case ScenarioData.PlayableCondition.特殊関係: action2(); for (int num10 = 0; num10 < characterMgr.GetStockMaidCount(); num10++) { Maid stockMaid11 = characterMgr.GetStockMaid(num10); action(stockMaid11, EnumConvert.GetString(stockMaid11.status.specialRelation) == text); } break; case ScenarioData.PlayableCondition.アイテム: { int facilityPowerUpMaterialID = FacilityDataTable.GetFacilityPowerUpMaterialID(text); set_ok(facilityMgr.GetFacilityPowerUpItemEnable(facilityPowerUpMaterialID)); break; } case ScenarioData.PlayableCondition.施設: { string[] array3 = text.Replace("Lv", " ").Split(new char[] { ' ' }); int facilityTypeID = -1; if (!int.TryParse(array3[0], out facilityTypeID)) { facilityTypeID = FacilityDataTable.GetFacilityTypeID(array3[0]); } if (array3.Count() > 1) { set_ok(facilityMgr.IsExistTypeFacility(facilityTypeID) && facilityMgr.GetFacilityLevel(facilityTypeID) >= int.Parse(array3[1])); } else { set_ok(facilityMgr.IsExistTypeFacility(facilityTypeID)); } break; } case ScenarioData.PlayableCondition.NTRブロック: if (text == "○") { set_ok(GameMain.Instance.CharacterMgr.status.lockNTRPlay); } else { set_ok(!GameMain.Instance.CharacterMgr.status.lockNTRPlay); } break; case ScenarioData.PlayableCondition.性経験: action2(); for (int num11 = 0; num11 < characterMgr.GetStockMaidCount(); num11++) { Maid stockMaid12 = characterMgr.GetStockMaid(num11); action(stockMaid12, EnumConvert.GetString(stockMaid12.status.seikeiken) == text); } break; case ScenarioData.PlayableCondition.契約: action2(); for (int num12 = 0; num12 < characterMgr.GetStockMaidCount(); num12++) { Maid stockMaid13 = characterMgr.GetStockMaid(num12); action(stockMaid13, EnumConvert.GetString(stockMaid13.status.contract) == text); } break; case ScenarioData.PlayableCondition.新ボディブロック: { action2(); bool flag4 = text == "○" || text == "◯"; for (int num13 = 0; num13 < characterMgr.GetStockMaidCount(); num13++) { Maid stockMaid14 = characterMgr.GetStockMaid(num13); action(stockMaid14, !flag4 || (flag4 && !stockMaid14.IsCrcBody)); } break; } case ScenarioData.PlayableCondition.メインキャラとのボディ一致チェック: { action2(); CharacterMgr characterMgr2 = GameMain.Instance.CharacterMgr; Maid maid3 = null; for (int num14 = 0; num14 < characterMgr2.GetStockMaidCount(); num14++) { Maid stockMaid15 = characterMgr2.GetStockMaid(num14); if (stockMaid15 != null && stockMaid15.status.mainChara) { string convertPersonal3 = GameMain.Instance.ScenarioSelectMgr.GetConvertPersonal(stockMaid15); if (convertPersonal3 == text) { maid3 = stockMaid15; break; } } } if (!maid3) { set_ok(false); } else if (this.m_EventMaid.Count > 0) { List list = new List(this.m_EventMaid); for (int num15 = 0; num15 < list.Count; num15++) { Maid maid2 = list[num15]; if (maid2 == maid3) { this.m_EventMaid.Remove(maid2); } else { action(maid2, maid3.IsCrcBody == maid2.IsCrcBody); } } } else { for (int num16 = 0; num16 < characterMgr.GetStockMaidCount(); num16++) { Maid stockMaid16 = characterMgr.GetStockMaid(num16); action(stockMaid16, maid3 != stockMaid16 && maid3.IsCrcBody == stockMaid16.IsCrcBody); } } break; } } if (maid_check && maid_update) { if (and_operator) { isOk &= (this.m_EventMaid.Count > 0); } else { isOk |= (this.m_EventMaid.Count > 0); } } } return isOk; } public bool IsEnoughEventMaid() { if (!this.IsFixedMaid || this.EventMaidNum > 0) { return this.EventMaidNum <= this.m_EventMaid.Count; } return this.m_EventMaid.Count != 0; } public Maid GetEventMaid(int no) { return this.m_EventMaid[no]; } public List GetEventMaidList() { return this.m_EventMaid; } public bool ExistEventMaid(Maid maid) { return this.m_EventMaid.Contains(maid); } public void AddEventMaid(Maid maid) { if (!this.m_EventMaid.Contains(maid) && !maid.status.GetEventEndFlag(this.ID)) { this.m_EventMaid.Add(maid); } } public void RemoveEventMaid(List maid_list, bool not_again = false) { foreach (Maid maid in maid_list) { this.RemoveEventMaid(maid, not_again); } } public void RemoveEventMaid(Maid maid, bool not_again = false) { if (this.m_EventMaid.Contains(maid)) { this.m_EventMaid.Remove(maid); if (not_again) { maid.status.SetEventEndFlag(this.ID, true); } } } public void ScenarioPlay(List maid_list) { if (!this.IsFixedMaid) { for (int i = 0; i < maid_list.Count; i++) { GameMain.Instance.CharacterMgr.SetActiveMaid(maid_list[i], i); } } this.RemoveEventMaid(maid_list, this.m_NotMaidAgain); this.IsOncePlayed = true; } public ScenarioData.PlayableData[] GetPlayableDataArray() { return this.m_PlayableData.Values.ToArray(); } public ScenarioData.PlayableData GetPlayableData(int index) { return this.m_PlayableData.Values.ElementAt(index); } public ScenarioData.PlayableData GetPlayableData(ScenarioData.PlayableCondition condition) { return (!this.m_PlayableData.ContainsKey(condition)) ? null : this.m_PlayableData[condition]; } public void Serialize(BinaryWriter writer) { writer.Write(this.IsOncePlayed); } public void Deserialize(BinaryReader reader) { try { this.IsOncePlayed = reader.ReadBoolean(); if (GameMain.Instance.ScenarioSelectMgr.nSaveVer >= 1f) { if (GameMain.Instance.ScenarioSelectMgr.nSaveVer < 1.2f) { reader.ReadInt32(); } } else { reader.ReadBoolean(); } if (GameMain.Instance.ScenarioSelectMgr.nSaveVer >= 1.1f && GameMain.Instance.ScenarioSelectMgr.nSaveVer < 1.3f) { reader.ReadBoolean(); } } catch { if (GameMain.Instance.ScenarioSelectMgr.DeserializeFiled) { Debug.Log("ScenarioSelectMgr.cs:前のバージョンのデータです(2017/10/24より前)"); } else { Debug.LogError("ScenarioSelectMgr.cs:読み込みエラー"); } } } public void Recet() { this.IsOncePlayed = false; } public const string TermPrefixNotification = "SceneScenarioSelect/通知時表記/"; private static string[] m_MainMaidList = new string[] { "無垢", "真面目", "凜デレ", "純真", "クーデレ", "ツンデレ" }; public readonly int ID; public readonly Dictionary m_PlayableData = new Dictionary(); public readonly string Title; public readonly string EventContents; public readonly string ScenarioScript; public readonly string ScriptLabel; public readonly int EventMaidNum; public readonly string IconName; public readonly bool IsImportant; public readonly bool IsOncePlayOnly; public readonly string[] ConditionText; public readonly string Notification; private List m_EventMaid = new List(); private bool m_NotMaidAgain = true; private bool m_ExistMaidUpdate; public enum PlayableCondition { 好感度, 時間帯, 属性, シナリオ, パラメ\u30FCタ, 性癖, ジョブクラス, 夜伽クラス, 関係, 追加関係, 特殊関係, アイテム, 施設, NTRブロック, 性経験, 契約, 新ボディブロック, メインキャラとのボディ一致チェック, MAX } public class PlayableData { public PlayableData(string data, ScenarioData.PlayableCondition condition) { this.Condition = condition; this.StringData = data.Replace('.', '.').Replace(',', ',').Replace(',', '&'); } public string[] StrdataArray { get { return this.StringData.Split(new char[] { ',' }); } } public readonly string StringData; public readonly ScenarioData.PlayableCondition Condition; } }