public static void HandleMenuInput(MenuModel menu, UserInput input, MenuState menuState) { switch (input) { case UserInput.Up: Handle(menuState, /* navigation */ () => { menu.CurrentCursorLocation = MenuUtility.DecrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_NAVIGATION_ITEMS, MenuState.Navigation); }, /* itemsAction */ () => { }, //do nothing /* itemsShowDetails */ () => { }, //do nothing /* itemsSelectingPM */ () => { menu.CurrentCursorLocation = MenuUtility.DecrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.ItemsSelectingPartyMember, true); }, /* giftsSelectingPM */ () => { menu.CurrentCursorLocation = MenuUtility.DecrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.GiftsSelectingPartyMember, true); }, /* useGiftSelectPM */ () => { menu.CurrentCursorLocation = MenuUtility.DecrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.UseGiftSelectingPartyMember, true); }, /* equipSelectingPM */ () => { menu.CurrentCursorLocation = MenuUtility.DecrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.EquipmentSelectingPartyMember, true); }, /* equipmentAction */ () => { }, //do nothing /* equipSelectingES */ () => { if (menu.CurrentCursorLocation >= (Int32)MenuState.EquipmentSelectingEquipmentSlot + 2) { //move up only if we're not on the top menu.CurrentCursorLocation -= 2; } }, /* formation */ () => { menu.CurrentCursorLocation = MenuUtility.DecrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.Formation); }, /* statusSelectingPM */ () => { menu.CurrentCursorLocation = MenuUtility.DecrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.StatusSelectingPartyMember, true); }, /* status */ () => { }, //do nothing /* quest */ () => { }, //do nothing /* saveFileOverride */ () => { }, //do nothing /* settings */ () => { menu.CurrentCursorLocation = Math.Max((Int32)MenuState.Settings, menu.CurrentCursorLocation - 1); }, /* items */ () => { menu.CurrentCursorLocation = Math.Max((Int32)MenuState.Items, menu.CurrentCursorLocation - 2); }, /* gifts */ () => { menu.CurrentCursorLocation = Math.Max((Int32)MenuState.Gifts, menu.CurrentCursorLocation - 2); }, /* equipment */ () => { menu.CurrentCursorLocation = Math.Max((Int32)MenuState.Equipment, menu.CurrentCursorLocation - 1); }, /* save */ () => { menu.CurrentCursorLocation = Math.Max((Int32)MenuState.Save, menu.CurrentCursorLocation - 1); MenuUtility.UpdateSelectedSavedGame(menu); } ); break; case UserInput.Down: Handle(menuState, /* navigation */ () => { menu.CurrentCursorLocation = MenuUtility.IncrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_NAVIGATION_ITEMS, MenuState.Navigation); }, /* itemsAction */ () => { }, //do nothing /* itemsShowDetails */ () => { }, //do nothing /* itemsSelectingPM */ () => { menu.CurrentCursorLocation = MenuUtility.IncrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_NAVIGATION_ITEMS, MenuState.ItemsSelectingPartyMember, true); }, /* giftsSelectingPM */ () => { menu.CurrentCursorLocation = MenuUtility.IncrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.GiftsSelectingPartyMember, true); }, /* useGiftSelectPM */ () => { menu.CurrentCursorLocation = MenuUtility.IncrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_NAVIGATION_ITEMS, MenuState.UseGiftSelectingPartyMember, true); }, /* equipSelectingPM */ () => { menu.CurrentCursorLocation = MenuUtility.IncrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.EquipmentSelectingPartyMember, true); }, /* equipmentAction */ () => { }, //do nothing /* equipSelectingES */ () => { if (menu.CurrentCursorLocation <= (Int32)MenuState.EquipmentSelectingEquipmentSlot + Constants.MENU_NUMBER_OF_EQUIPMENT_SPOTS - 3) { //move down only if we're not on the bottom menu.CurrentCursorLocation += 2; } }, /* formation */ () => { menu.CurrentCursorLocation = MenuUtility.IncrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.Formation); }, /* statusSelectingPM */ () => { menu.CurrentCursorLocation = MenuUtility.IncrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.StatusSelectingPartyMember, true); }, /* status */ () => { }, //do nothing /* quest */ () => { }, //do nothing /* saveFileOverride */ () => { }, //do nothing /* settings */ () => { menu.CurrentCursorLocation = Math.Min((Int32)MenuState.Settings + Constants.MENU_NUMBER_OF_SETTINGS - 1, menu.CurrentCursorLocation + 1); }, /* items */ () => { menu.CurrentCursorLocation = Math.Min((Int32)MenuState.Items + GameModel.Instance.Inventory.AllItems.Count - 1, menu.CurrentCursorLocation + 2); }, /* gifts */() => { if (menu.SelectedPartyMember.AvailableGifts.Length > 0) { menu.CurrentCursorLocation = Math.Min((Int32)MenuState.Gifts + menu.SelectedPartyMember.AvailableGifts.Length - 1, menu.CurrentCursorLocation + 2); } }, /* equipment */ () => { menu.CurrentCursorLocation = Math.Min((Int32)MenuState.Equipment + menu.EquipableItems.Length - 1, menu.CurrentCursorLocation + 1); }, /* save */ () => { menu.CurrentCursorLocation = Math.Min((Int32)MenuState.Save + menu.GameSaveLocations.Length, menu.CurrentCursorLocation + 1); MenuUtility.UpdateSelectedSavedGame(menu); } ); break; case UserInput.Left: Handle(menuState, /* navigation */ () => { }, //do nothing /* itemsAction */ () => { menu.CurrentCursorLocation = MenuUtility.DecrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_ITEM_ACTIONS, MenuState.ItemsAction); }, /* itemsShowDetails */ () => { }, //do nothing /* itemsSelectingPM */ () => { }, //do nothing /* giftsSelectingPM */ () => { }, //do nothing /* useGiftSelectPM */ () => { }, //do nothing /* equipSelectingPM */ () => { }, //do nothing /* equipmentAction */ () => { menu.CurrentCursorLocation = MenuUtility.DecrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_EQUIPMENT_ACTIONS, MenuState.EquipmentAction); }, /* equipSelectingES */ () => { if (menu.CurrentCursorLocation % 2 == 1) { //move to the left only if we're on the right side menu.CurrentCursorLocation--; } }, /* formation */ () => { }, //do nothing /* statusSelectingPM */ () => { }, //do nothing /* status */ () => { var partyMemberIndex = MenuUtility.GetPartyMemberIndex(menu.SelectedPartyMember); var newCursorLocation = MenuUtility.DecrementCycle((Int32)MenuState.StatusSelectingPartyMember + partyMemberIndex, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.StatusSelectingPartyMember, true); var newPartyMember = MenuUtility.GetPartyMemberByCursorLocation(newCursorLocation); MenuUtility.SwitchMenuContent((Int32)MenuState.Status); MenuUtility.WaitFadeDelay(() => menu.SelectedPartyMember = newPartyMember); }, /* quest */ () => { }, //do nothing /* saveFileOverride */ () => { menu.CurrentCursorLocation = MenuUtility.DecrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_SAVE_FILE_OVERRIDE_ACTIONS, MenuState.SaveFileOverride); }, /* settings */ () => { var settings = SettingsModel.Instance; switch (menu.CurrentCursorLocation) { case 800: settings.Difficulty = (Difficulty)MenuUtility.DecrementCycle((Int32)settings.Difficulty, Constants.MENU_SETTINGS_NUMBER_OF_DIFFICULTIES); break; case 801: settings.MessageSpeed = (MessageSpeed)MenuUtility.DecrementCycle((Int32)settings.MessageSpeed, Constants.MENU_SETTINGS_NUMBER_OF_MESSAGE_SPEEDS); break; case 802: settings.BattleSpeed = (BattleSpeed)MenuUtility.DecrementCycle((Int32)settings.BattleSpeed, Constants.MENU_SETTINGS_NUMBER_OF_BATTLE_SPEEDS); break; case 803: settings.SoundOn = !settings.SoundOn; break; case 804: settings.CursorType = (CursorType)MenuUtility.DecrementCycle((Int32)settings.CursorType, Constants.MENU_SETTINGS_NUMBER_OF_CURSOR_TYPES); break; case 805: settings.GiftSortOrder = (GiftSortOrder)MenuUtility.DecrementCycle((Int32)settings.GiftSortOrder, Constants.MENU_SETTINGS_NUMBER_OF_GIFT_SORT_ORDERS); break; case 806: settings.BackgroundRed = Math.Max(Constants.MENU_SETTINGS_MIN_COLOR, settings.BackgroundRed - 1); break; case 807: settings.BackgroundGreen = Math.Max(Constants.MENU_SETTINGS_MIN_COLOR, settings.BackgroundGreen - 1); break; case 808: settings.BackgroundBlue = Math.Max(Constants.MENU_SETTINGS_MIN_COLOR, settings.BackgroundBlue - 1); break; case 809: settings.BorderRed = Math.Max(Constants.MENU_SETTINGS_MIN_COLOR, settings.BorderRed - 1); break; case 810: settings.BorderGreen = Math.Max(Constants.MENU_SETTINGS_MIN_COLOR, settings.BorderGreen - 1); break; case 811: settings.BorderBlue = Math.Max(Constants.MENU_SETTINGS_MIN_COLOR, settings.BorderBlue - 1); break; } }, /* items */ () => { menu.CurrentCursorLocation = Math.Max((Int32)MenuState.Items, menu.CurrentCursorLocation - 1); }, /* gifts */ () => { menu.CurrentCursorLocation = Math.Max((Int32)MenuState.Gifts, menu.CurrentCursorLocation - 1); }, /* equipment */ () => { }, //do nothing /* save */ () => { } //do nothing ); break; case UserInput.Right: Handle(menuState, /* navigation */ () => { }, //do nothing /* itemsAction */ () => { menu.CurrentCursorLocation = MenuUtility.IncrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_ITEM_ACTIONS, MenuState.ItemsAction); }, /* itemsShowDetails */ () => { }, //do nothing /* itemsSelectingPM */ () => { }, //do nothing /* giftsSelectingPM */ () => { }, //do nothing /* useGiftSelectPM */ () => { }, //do nothing /* equipSelectingPM */ () => { }, //do nothing /* equipmentAction */ () => { menu.CurrentCursorLocation = MenuUtility.IncrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_EQUIPMENT_ACTIONS, MenuState.EquipmentAction); }, /* equipSelectingES */ () => { if (menu.CurrentCursorLocation % 2 == 0) { //move to the right only if we're on the left side menu.CurrentCursorLocation++; } }, /* formation */ () => { }, //do nothing /* statusSelectingPM */ () => { }, //do nothing /* status */ () => { var partyMemberIndex = MenuUtility.GetPartyMemberIndex(menu.SelectedPartyMember); var newCursorLocation = MenuUtility.IncrementCycle((Int32)MenuState.StatusSelectingPartyMember + partyMemberIndex, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.StatusSelectingPartyMember, true); var newPartyMember = MenuUtility.GetPartyMemberByCursorLocation(newCursorLocation); MenuUtility.SwitchMenuContent((Int32)MenuState.Status); MenuUtility.WaitFadeDelay(() => menu.SelectedPartyMember = newPartyMember); }, /* quest */ () => { }, //do nothing /* saveFileOverride */ () => { menu.CurrentCursorLocation = MenuUtility.IncrementCycle(menu.CurrentCursorLocation, Constants.MENU_NUMBER_OF_SAVE_FILE_OVERRIDE_ACTIONS, MenuState.SaveFileOverride); }, /* settings */ () => { var settings = SettingsModel.Instance; switch (menu.CurrentCursorLocation) { case 800: settings.Difficulty = (Difficulty)MenuUtility.IncrementCycle((Int32)settings.Difficulty, Constants.MENU_SETTINGS_NUMBER_OF_DIFFICULTIES); break; case 801: settings.MessageSpeed = (MessageSpeed)MenuUtility.IncrementCycle((Int32)settings.MessageSpeed, Constants.MENU_SETTINGS_NUMBER_OF_MESSAGE_SPEEDS); break; case 802: settings.BattleSpeed = (BattleSpeed)MenuUtility.IncrementCycle((Int32)settings.BattleSpeed, Constants.MENU_SETTINGS_NUMBER_OF_BATTLE_SPEEDS); break; case 803: settings.SoundOn = !settings.SoundOn; break; case 804: settings.CursorType = (CursorType)MenuUtility.IncrementCycle((Int32)settings.CursorType, Constants.MENU_SETTINGS_NUMBER_OF_CURSOR_TYPES); break; case 805: settings.GiftSortOrder = (GiftSortOrder)MenuUtility.IncrementCycle((Int32)settings.GiftSortOrder, Constants.MENU_SETTINGS_NUMBER_OF_GIFT_SORT_ORDERS); break; case 806: settings.BackgroundRed = Math.Min(Constants.MENU_SETTINGS_MAX_COLOR, settings.BackgroundRed + 1); break; case 807: settings.BackgroundGreen = Math.Min(Constants.MENU_SETTINGS_MAX_COLOR, settings.BackgroundGreen + 1); break; case 808: settings.BackgroundBlue = Math.Min(Constants.MENU_SETTINGS_MAX_COLOR, settings.BackgroundBlue + 1); break; case 809: settings.BorderRed = Math.Min(Constants.MENU_SETTINGS_MAX_COLOR, settings.BorderRed + 1); break; case 810: settings.BorderGreen = Math.Min(Constants.MENU_SETTINGS_MAX_COLOR, settings.BorderGreen + 1); break; case 811: settings.BorderBlue = Math.Min(Constants.MENU_SETTINGS_MAX_COLOR, settings.BorderBlue + 1); break; } }, /* items */ () => { menu.CurrentCursorLocation = Math.Min((Int32)MenuState.Items + GameModel.Instance.Inventory.AllItems.Count - 1, menu.CurrentCursorLocation + 1); }, /* gifts */() => { if (menu.SelectedPartyMember.AvailableGifts.Length > 0) { menu.CurrentCursorLocation = Math.Min((Int32)MenuState.Gifts + menu.SelectedPartyMember.AvailableGifts.Length - 1, menu.CurrentCursorLocation + 1); } }, /* equipment */ () => { }, //do nothing /* save */ () => { } //do nothing ); break; case UserInput.Confirm: Handle(menuState, /* navigation */ () => { switch (menu.CurrentCursorLocation) { case 0: { menu.AdditionalCursorLocations = new[] { (Int32)MenuState.ItemsAction }; MenuUtility.SwitchMenuContent(menu.LastItemLocation); break; } case 1: { menu.AdditionalCursorLocations = new[] { menu.CurrentCursorLocation }; menu.CurrentCursorLocation = MenuUtility.IncrementCycle((Int32)MenuState.GiftsSelectingPartyMember - 1, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.GiftsSelectingPartyMember, true); break; } case 2: { menu.AdditionalCursorLocations = new[] { menu.CurrentCursorLocation }; menu.CurrentCursorLocation = MenuUtility.IncrementCycle((Int32)MenuState.EquipmentSelectingPartyMember - 1, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.EquipmentSelectingPartyMember, true); break; } case 3: { menu.AdditionalCursorLocations = new[] { menu.CurrentCursorLocation }; menu.CurrentCursorLocation = (Int32)MenuState.Formation; break; } case 4: { menu.AdditionalCursorLocations = new[] { menu.CurrentCursorLocation }; menu.CurrentCursorLocation = MenuUtility.IncrementCycle((Int32)MenuState.StatusSelectingPartyMember - 1, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.StatusSelectingPartyMember, true); break; } case 5: MenuUtility.SwitchMenuContent((Int32)MenuState.Quest); break; case 6: { menu.GameSaveLocations = GameSaveUtility.GetGameSaveFiles(); MenuUtility.SwitchMenuContent((Int32)MenuState.Save); break; } case 7: MenuUtility.SwitchMenuContent((Int32)MenuState.Settings); break; } }, /* itemsAction */ () => { switch (menu.CurrentCursorLocation) { case 100: { menu.AdditionalCursorLocations = new[] { menu.CurrentCursorLocation }; menu.CurrentCursorLocation = menu.LastItemLocation; break; } case 101: { GameModel.Instance.Inventory.Organize(); MenuUtility.ClearAdditionalCursorLocations(menu); menu.CurrentCursorLocation--; break; } } }, /* itemsShowDetails */ () => { MenuUtility.WaitFadeDelay(() => menu.SelectedItem = null); menu.CurrentCursorLocation = menu.AdditionalCursorLocations[0]; MenuUtility.ClearAdditionalCursorLocations(menu); }, /* itemsSelectingPM */ () => { var item = menu.SelectedItem as ConsumableItem; var itemAbility = item.GetAbility(); //steps: //1. Remove item from inventory //2. Throttle input for as long as the animation will take //3. for each ability step: // 3a. Get secondary targets, based on primary targets // 3b. Handle ability animation from source to targets // 3c. Apply effects to targets //4. If the item quantity remaining is 0, back up. If not, we're done //remove item from inventory GameModel.Instance.Inventory.Remove(menu.SelectedItem); var quantityRemaining = GameModel.Instance.Inventory.GetQuantity(item); //TODO: Sanity check: all item abilities applied to consumable items can call GetAbilitySteps with a null source and not fail/return something useful //throttle input for as long as the animation will take //total delay is each step * (duration + display duration + 1 (for targeting step)), then +4 if we're transitioning away from screen var totalDelay = itemAbility.GetAbilitySteps(null).Sum(x => x.GetTotalFrames(GameState.InMenu) + Constants.BATTLE_TIMING_DISPLAY_DAMAGE_TICKS + 1) + (quantityRemaining == 0 ? 4 : 0); Bus.Broadcast(ThrottleInputMessage.New(GameModel.Instance.State, totalDelay)); //then, get the ability execution steps var primaryTarget = MenuUtility.GetPartyMemberByCursorLocation(menu.CurrentCursorLocation); var abilityExecutionSteps = MenuUtility.GetAbilityExecutionSteps(itemAbility, null, primaryTarget); //if the quantity is now 0, go back up if (quantityRemaining == 0) { //we wait for the effect to finish, and then remove the selected item, which will transition back to the item screen abilityExecutionSteps.Add(DelayedAction.New(() => { menu.SelectedItem = null; menu.CurrentCursorLocation = menu.AdditionalCursorLocations[0]; MenuUtility.ClearAdditionalCursorLocations(menu); MenuUtility.ThrottleInputForAnimation(); }, 0)); } TimerUtility.ExecuteChainOfActions(abilityExecutionSteps); }, /* giftsSelectingPM */ () => { menu.SelectedPartyMember = MenuUtility.GetPartyMemberByCursorLocation(menu.CurrentCursorLocation); MenuUtility.ClearAdditionalCursorLocations(menu); MenuUtility.SwitchMenuContent((Int32)MenuState.Gifts); }, /* useGiftSelectPM */ () => { var gift = menu.SelectedGift as Gift; //steps: //1. PartyMember use gift //2. Throttle input for as long as the animation will take //3. for each ability step: // 3a. Get secondary targets, based on primary targets // 3b. Handle ability animation from source to targets // 3c. Apply effects to targets //4. If the energy remaining is less than cost, back up. If not, we're done //use gift gift.Ability.ExecuteCost(menu.SelectedPartyMember); //TODO: Do we need to broadcast an event that a gift is being used from the menu? var enoughEnergyRemainingToUseAgain = menu.SelectedPartyMember.CurrentEnergy >= gift.Ability.EnergyCost; //throttle input for as long as the animation will take //total delay is each step * (duration + display duration + 1 )for targeting step)), then +4 if we're transitioning away from screen var totalDelay = gift.Ability.GetAbilitySteps(menu.SelectedPartyMember).Sum(x => x.GetTotalFrames(GameState.InMenu) + Constants.BATTLE_TIMING_DISPLAY_DAMAGE_TICKS + 1) + (enoughEnergyRemainingToUseAgain ? 0 : 4); Bus.Broadcast(ThrottleInputMessage.New(GameModel.Instance.State, totalDelay)); //then, get execution steps var primaryTarget = MenuUtility.GetPartyMemberByCursorLocation(menu.CurrentCursorLocation); var abilityExecutionSteps = MenuUtility.GetAbilityExecutionSteps(gift.Ability, menu.SelectedPartyMember, primaryTarget); //if there isn't enough energy to use again, go back up if (enoughEnergyRemainingToUseAgain == false) { //we wait for the effect to finish, and then remove the selected item, which will transition back to the item screen abilityExecutionSteps.Add(DelayedAction.New(() => { menu.SelectedGift = null; menu.CurrentCursorLocation = menu.AdditionalCursorLocations[0]; MenuUtility.ClearAdditionalCursorLocations(menu); MenuUtility.ThrottleInputForAnimation(); }, 0)); } TimerUtility.ExecuteChainOfActions(abilityExecutionSteps); }, /* equipSelectingPM */ () => { menu.SelectedPartyMember = MenuUtility.GetPartyMemberByCursorLocation(menu.CurrentCursorLocation); menu.AdditionalCursorLocations = new[] { (Int32)MenuState.EquipmentAction }; MenuUtility.SwitchMenuContent((Int32)MenuState.EquipmentSelectingEquipmentSlot); }, /* equipmentAction */ () => { switch (menu.CurrentCursorLocation) { case 310: //equip case 311: //remove //in both cases, save the action we're doing and move to equipment selecting spot menu.AdditionalCursorLocations = new[] { menu.CurrentCursorLocation }; menu.CurrentCursorLocation = (Int32)MenuState.EquipmentSelectingEquipmentSlot; break; case 312: //remove all, then move the cursor back to equip menu.SelectedPartyMember.UnequipAll(true, true); menu.CurrentCursorLocation = (Int32)MenuState.EquipmentAction; break; } }, /* equipSelectingES */ () => { //we should either have equip or remove selected switch (menu.AdditionalCursorLocations[0]) { case 310: //equip - move to the equipable items list only if there's actually something to equip if (menu.EquipableItems.Count() > 0) { menu.AdditionalCursorLocations = new[] { menu.AdditionalCursorLocations[0], menu.CurrentCursorLocation }; menu.CurrentCursorLocation = (Int32)MenuState.Equipment; } break; case 311: //remove menu.SelectedPartyMember.Unequip((EquipmentSlot)menu.CurrentCursorLocation, true, true); break; } }, /* formation */ () => { if (menu.CurrentCursorSelection == Constants.MENU_NO_SELECTION) { //no party member has been selected yet. Select one menu.CurrentCursorSelection = menu.CurrentCursorLocation; } else { //a party member has been selected. Are they the same? if (menu.CurrentCursorSelection == menu.CurrentCursorLocation) { //if they're the same, do nothing } else { //they're different, switch their position Func<PartyMember> getFirstMember = null; Func<PartyMember> getSecondMember = null; Action<PartyMember> setFirstMember = null; Action<PartyMember> setSecondMember = null; switch (MenuUtility.GetPartyMemberIndex(menu.CurrentCursorSelection)) { case 0: getFirstMember = () => GameModel.Instance.PartyMember1; setFirstMember = x => GameModel.Instance.PartyMember1 = x; break; case 1: getFirstMember = () => GameModel.Instance.PartyMember2; setFirstMember = x => GameModel.Instance.PartyMember2 = x; break; case 2: getFirstMember = () => GameModel.Instance.PartyMember3; setFirstMember = x => GameModel.Instance.PartyMember3 = x; break; case 3: getFirstMember = () => GameModel.Instance.PartyMember4; setFirstMember = x => GameModel.Instance.PartyMember4 = x; break; } switch (MenuUtility.GetPartyMemberIndex(menu.CurrentCursorLocation)) { case 0: getSecondMember = () => GameModel.Instance.PartyMember1; setSecondMember = x => GameModel.Instance.PartyMember1 = x; break; case 1: getSecondMember = () => GameModel.Instance.PartyMember2; setSecondMember = x => GameModel.Instance.PartyMember2 = x; break; case 2: getSecondMember = () => GameModel.Instance.PartyMember3; setSecondMember = x => GameModel.Instance.PartyMember3 = x; break; case 3: getSecondMember = () => GameModel.Instance.PartyMember4; setSecondMember = x => GameModel.Instance.PartyMember4 = x; break; } var temp = getFirstMember(); setFirstMember(getSecondMember()); setSecondMember(temp); } //reset the cursor selection menu.CurrentCursorSelection = Constants.MENU_NO_SELECTION; } }, /* statusSelectingPM */ () => { menu.SelectedPartyMember = MenuUtility.GetPartyMemberByCursorLocation(menu.CurrentCursorLocation); MenuUtility.ClearAdditionalCursorLocations(menu); MenuUtility.SwitchMenuContent((Int32)MenuState.Status); }, /* status */ () => { MenuUtility.SwitchMenuContent(4); MenuUtility.WaitFadeDelay(() => menu.SelectedPartyMember = null); }, /* quest */ () => { MenuUtility.SwitchMenuContent(5); }, /* saveFileOverride */ () => { if (menu.CurrentCursorLocation == (Int32)MenuState.SaveFileOverride) { //save MenuUtility.SaveGameAndSetCursor(menu); } else { //cancel, go back menu.CurrentCursorLocation = menu.AdditionalCursorLocations[0]; MenuUtility.ClearAdditionalCursorLocations(menu); } }, /* settings */ () => { var settings = SettingsModel.Instance; switch (menu.CurrentCursorLocation) { case 800: settings.Difficulty = (Difficulty)MenuUtility.IncrementCycle((Int32)settings.Difficulty, Constants.MENU_SETTINGS_NUMBER_OF_DIFFICULTIES); break; case 801: settings.MessageSpeed = (MessageSpeed)MenuUtility.IncrementCycle((Int32)settings.MessageSpeed, Constants.MENU_SETTINGS_NUMBER_OF_MESSAGE_SPEEDS); break; case 802: settings.BattleSpeed = (BattleSpeed)MenuUtility.IncrementCycle((Int32)settings.BattleSpeed, Constants.MENU_SETTINGS_NUMBER_OF_BATTLE_SPEEDS); break; case 803: settings.SoundOn = !settings.SoundOn; break; case 804: settings.CursorType = (CursorType)MenuUtility.IncrementCycle((Int32)settings.CursorType, Constants.MENU_SETTINGS_NUMBER_OF_CURSOR_TYPES); break; case 805: settings.GiftSortOrder = (GiftSortOrder)MenuUtility.IncrementCycle((Int32)settings.GiftSortOrder, Constants.MENU_SETTINGS_NUMBER_OF_GIFT_SORT_ORDERS); break; case 806: //do nothing on confirm case 807: //do nothing on confirm case 808: //do nothing on confirm case 809: //do nothing on confirm case 810: //do nothing on confirm case 811: break; //do nothing on confirm } }, /* items */ () => { if (menu.CurrentCursorSelection == Constants.MENU_NO_SELECTION) { //no item has been selected yet. Select one menu.CurrentCursorSelection = menu.CurrentCursorLocation; } else { //an item has been selected. Are the location and selection the same? if (menu.CurrentCursorSelection == menu.CurrentCursorLocation) { var itemIndex = menu.CurrentCursorLocation - (Int32)MenuState.Items; var rowItem = menu.InventoryRows.GetItemByIndex(itemIndex); if (rowItem.IsEnabled) { var item = rowItem.Item; if (item != null) { //TODO: Test this //there was an item under our cursor. Let's do something with it switch (item.Item.ItemTypeDetails.PrimaryType) { //TODO: Plan for the situation where a party member has the ability that friendly items that target single now target all. That'd be cool. case ItemType.Consumable: var consumableItem = item.Item as ConsumableItem; var consumableItemAbility = consumableItem.GetAbility(); //we will be transitioning to the select party member screen, wait for animation menu.SelectedItem = consumableItem; MenuUtility.ThrottleInputForAnimation(); //let's see on whom we can use this ability var firstPartyMemberIndex = MenuUtility.IncrementCycle((Int32)MenuState.ItemsSelectingPartyMember - 1, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.ItemsSelectingPartyMember, true); var newTargets = MenuUtility.GetAllTargetsForAbilityStep(null, MenuUtility.GetPartyMemberByCursorLocation(firstPartyMemberIndex), consumableItemAbility.Target, consumableItemAbility.GetAbilitySteps(null)[0]); //we need to set the additional cursor locations to the current cursor location + any new targets that aren't the first target var additionalTargetIndicies = newTargets .Select(x => MenuUtility.GetPartyMemberIndex(x) + (Int32)MenuState.ItemsSelectingPartyMember) .Where(x => x != firstPartyMemberIndex); menu.AdditionalCursorLocations = new[] { menu.CurrentCursorLocation }.Concat(additionalTargetIndicies).ToArray(); //clear the selection, and set the cursor to the first party member menu.CurrentCursorSelection = Constants.MENU_NO_SELECTION; menu.CurrentCursorLocation = firstPartyMemberIndex; return; //we want to return without resetting the current cursor selection, as we want that visually indicating the item in question case ItemType.Weapon: case ItemType.Shield: case ItemType.Armor: case ItemType.Helm: case ItemType.Trinket: menu.SelectedItem = item.Item; menu.AdditionalCursorLocations = new[] { menu.CurrentCursorLocation }; menu.CurrentCursorLocation = (Int32)MenuState.ItemsShowingDetails; break; } } } else { MenuUtility.IndicateInvalidAction(); } } else { //they're different, switch their position var firstItemIndex = menu.CurrentCursorSelection - (Int32)MenuState.Items; var secondItemIndex = menu.CurrentCursorLocation - (Int32)MenuState.Items; GameModel.Instance.Inventory.Swap(firstItemIndex, secondItemIndex); menu.CurrentCursorLocation = menu.CurrentCursorLocation; //to signal context update } //reset the cursor selection menu.CurrentCursorSelection = Constants.MENU_NO_SELECTION; } }, /* gifts */ () => { if (menu.SelectedPartyMember.AvailableGifts.Length > 0) { var giftIndex = menu.CurrentCursorLocation - (Int32)MenuState.Gifts; var gift = menu.SelectedPartyMember.GiftRows.GetItemByIndex(giftIndex); if (gift.IsEnabled) { //TODO: Test this var giftToUse = gift.Item; //we will be transitioning to the select party member screen, wait for animation menu.SelectedGift = giftToUse; MenuUtility.ThrottleInputForAnimation(); //let's see on whom we can use this ability var firstPartyMemberIndex = MenuUtility.IncrementCycle((Int32)MenuState.UseGiftSelectingPartyMember - 1, Constants.MENU_NUMBER_OF_PARTY_MEMBERS, MenuState.UseGiftSelectingPartyMember, true); var newTargets = MenuUtility.GetAllTargetsForAbilityStep(menu.SelectedPartyMember, MenuUtility.GetPartyMemberByCursorLocation(firstPartyMemberIndex), giftToUse.Ability.Target, giftToUse.Ability.GetAbilitySteps(menu.SelectedPartyMember)[0]); //we need to set the additional cursor locations to the current cursor location + any new targets that aren't the first target var additionalTargetIndicies = newTargets .Select(x => MenuUtility.GetPartyMemberIndex(x) + (Int32)MenuState.UseGiftSelectingPartyMember) .Where(x => x != firstPartyMemberIndex); menu.AdditionalCursorLocations = new[] { menu.CurrentCursorLocation }.Concat(additionalTargetIndicies).ToArray(); //clear the selection, and set the cursor to the first party member menu.CurrentCursorSelection = Constants.MENU_NO_SELECTION; menu.CurrentCursorLocation = firstPartyMemberIndex; } else { MenuUtility.IndicateInvalidAction(); } } }, /* equipment */ () => { //find the item under the cursor, find the slot selected, and get ready to equip it var equipableItemsIndex = menu.CurrentCursorLocation - (Int32)MenuState.Equipment; var item = menu.EquipableItems[equipableItemsIndex]; var equipmentSlot = (EquipmentSlot)menu.AdditionalCursorLocations[1]; //then, take a step back menu.CurrentCursorLocation = menu.AdditionalCursorLocations[1]; menu.AdditionalCursorLocations = new[] { (Int32)MenuState.EquipmentAction }; //back to the 'Equip' equipment action //finally, equip it //By moving the cursor first, we prevent data bindings from double-firing and flickering with some weird visuals on the preview menu.SelectedPartyMember.Equip(item, equipmentSlot, true); }, /* save */ () => { //if we don't have a game save model, we're not overwriting, so just save it and move on if (menu.SelectedSavedGame == null) { MenuUtility.SaveGameAndSetCursor(menu); } else { //bring up the save confirmation menu.AdditionalCursorLocations = new[] { menu.CurrentCursorLocation }; menu.CurrentCursorLocation = (Int32)MenuState.SaveFileOverride; } } ); break; case UserInput.Cancel: Handle(menuState, /* navigation */ () => { MenuUtility.ClearAdditionalCursorLocations(menu); //closing the actual menu is handled in the input manager }, /* itemsAction */ () => { MenuUtility.ClearAdditionalCursorLocations(menu); MenuUtility.SwitchMenuContent(0); }, /* itemsShowDetails */ () => { MenuUtility.WaitFadeDelay(() => menu.SelectedItem = null); menu.CurrentCursorLocation = menu.AdditionalCursorLocations[0]; MenuUtility.ClearAdditionalCursorLocations(menu); }, /* itemsSelectingPM */ () => { menu.SelectedItem = null; menu.CurrentCursorLocation = menu.AdditionalCursorLocations[0]; MenuUtility.ClearAdditionalCursorLocations(menu); }, /* giftsSelectingPM */ () => { MenuUtility.ClearAdditionalCursorLocations(menu); menu.CurrentCursorLocation = 1; }, /* useGiftSelectPM */ () => { menu.SelectedGift = null; menu.CurrentCursorLocation = menu.AdditionalCursorLocations[0]; MenuUtility.ClearAdditionalCursorLocations(menu); }, /* equipSelectingPM */ () => { MenuUtility.ClearAdditionalCursorLocations(menu); menu.CurrentCursorLocation = 2; }, /* equipmentAction */ () => { MenuUtility.SwitchMenuContent(2); MenuUtility.WaitFadeDelay(() => menu.SelectedPartyMember = null); }, /* equipSelectingES */ () => { menu.CurrentCursorLocation = menu.AdditionalCursorLocations[0]; MenuUtility.ClearAdditionalCursorLocations(menu); }, /* formation */ () => { //if something is selected, deselect it. Otherwise, go back if (menu.CurrentCursorSelection != Constants.MENU_NO_SELECTION) { menu.CurrentCursorSelection = Constants.MENU_NO_SELECTION; } else { MenuUtility.ClearAdditionalCursorLocations(menu); menu.CurrentCursorLocation = 3; } }, /* statusSelectingPM */ () => { MenuUtility.ClearAdditionalCursorLocations(menu); menu.CurrentCursorLocation = 4; }, /* status */ () => { MenuUtility.SwitchMenuContent(4); MenuUtility.WaitFadeDelay(() => menu.SelectedPartyMember = null); }, /* quest */ () => { MenuUtility.SwitchMenuContent(5); }, /* saveFileOverride */ () => { menu.CurrentCursorLocation = menu.AdditionalCursorLocations[0]; MenuUtility.ClearAdditionalCursorLocations(menu); }, /* settings */ () => { MenuUtility.SwitchMenuContent(7); }, /* items */ () => { //if something is selected, deselect it. Otherwise, go back if (menu.CurrentCursorSelection != Constants.MENU_NO_SELECTION) { menu.CurrentCursorSelection = Constants.MENU_NO_SELECTION; } else { menu.LastItemLocation = menu.CurrentCursorLocation; MenuUtility.ClearAdditionalCursorLocations(menu); menu.CurrentCursorLocation = (Int32)MenuState.ItemsAction; menu.CurrentCursorSelection = Constants.MENU_NO_SELECTION; } }, /* gifts */ () => { MenuUtility.SwitchMenuContent(1); MenuUtility.WaitFadeDelay(() => menu.SelectedPartyMember = null); }, /* equipment */ () => { menu.CurrentCursorLocation = menu.AdditionalCursorLocations[1]; menu.AdditionalCursorLocations = new[] { (Int32)MenuState.EquipmentAction }; //back to the 'Equip' equipment action }, /* save */ () => { MenuUtility.SwitchMenuContent(6); MenuUtility.WaitFadeDelay(() => menu.SelectedSavedGame = null); } ); break; case UserInput.Option: //do nothing break; } }
public static void UpdateSelectedSavedGame(MenuModel menu) { var savedGameIndex = menu.CurrentCursorLocation - (Int32)MenuState.Save; menu.SelectedSavedGame = menu.GameSaves[savedGameIndex]; }
public static void SaveGameAndSetCursor(MenuModel menu) { var updatedGameSaveModel = GameSaveUtility.SaveToFile(menu.SelectedSavedGame?.FileInfo.Name); //after we save, we want to refresh the saved game model menu.GameSaveLocations = GameSaveUtility.GetGameSaveFiles(); menu.CurrentCursorLocation = (Int32)MenuState.Save + 1; //move the cursor to the top of the list, which is now pointing to the latest save file ClearAdditionalCursorLocations(menu); UpdateSelectedSavedGame(menu); }
public static void ClearAdditionalCursorLocations(MenuModel menu) { menu.AdditionalCursorLocations = new Int32[0]; }