internal static void IdentifyItem(bool selected = false) { if (!selected) { DungeonGameEngine.ProcessMessageQueue(false, "What do you want to identify?"); currentSelectionAction = SelectionActions.Identify; } else { DungeonGameEngine.ProcessMessageQueue(true); // Acknowledge the "What do you want to identify" prompt // Get old text before item gets renamed var listKey = currentItem.SortingValue; // Retrieving this property should cause the item to be identified as well DungeonGameEngine.ProcessMessageQueue(false, currentItem.IdentifyText); currentSelectionAction = SelectionActions.None; // Update inventory list text GameText textItem = inventoryList[listKey]; textItem.Text = currentItem.InventoryTitle; inventoryList.Remove(listKey); inventoryList.Add(currentItem.SortingValue, textItem); closingWindow = true; } }
/// <summary> /// To be called with each new floor, identifies blocked tiles in the pathCounters array with /// a value of -1. When hero discovers hidden doors or bashes open locked doors, call this /// again to update the map so new routes can be plotted. /// </summary> internal static void InitializeDistanceMap() { pathCounters = new int[FloorGenerator.FloorWidth, FloorGenerator.FloorHeight]; // DEBUG Feature if (GameConstants.DEBUG_MODE_DRAW_STEPS_TO_HERO) { pathCounterText = new GameText[FloorGenerator.FloorWidth, FloorGenerator.FloorHeight]; } for (int x = 0; x < FloorGenerator.FloorWidth; x++) { for (int y = 0; y < FloorGenerator.FloorHeight; y++) { pathCounters[x, y] = unmappedValue; if (!FloorGenerator.TileIsPassible(FloorGenerator.GetTileAt(x, y))) { pathCounters[x, y] = -1; } // DEBUG Feature if (GameConstants.DEBUG_MODE_DRAW_STEPS_TO_HERO) { pathCounterText[x, y] = new GameText(graphicsDevice); } } } }
/// <summary> /// Allows player to rename some items /// </summary> /// <param name="item">Item to be renamed</param> /// <param name="receivedResponse">Result message returned to the player</param> private static void Rename(InventoryItem item, bool receivedResponse = false) { if (!receivedResponse) { usingRenameItemScreen = true; resetInputWindow = true; RenameItemScreen.Value = string.Empty; } else { string itemKey = inventoryList.ElementAt(selectedIndex).Key; if (item is INamable) { GameText gameText = inventoryList[itemKey]; inventoryList.Remove(itemKey); (item as INamable).Rename(response); if (item is IWearable) { gameText.Text = item.InventoryTitle + (item as IWearable).WornOn; } else { gameText.Text = item.InventoryTitle; } inventoryList.Add(item.SortingValue, gameText); } usingRenameItemScreen = false; } }
internal static void Initialize(GraphicsDevice gd) { oldKeyboard = Keyboard.GetState(); string prompt = "How shall thou be remembered (enter your name)?"; string instructions = "Enter - Except Esc - Cancel"; window.Initialize(gd, prompt, userResponse, instructions); userResponseText = new GameText(gd); // Used solely for measuring text length during input }
internal void Initialize(GraphicsDevice gd, string prompt, StringBuilder userInput, string instructions = "Esc - Exit") { viewPort = new Viewport(); if (!initComplete) { Init(gd); } firstIndexToShowOnScreen = 0; userResponse = userInput; userResponseText = new GameText(gd); instructionText = new GameText(instructions, new Point(), gd); promptText = new GameText(prompt, gd); }
internal void Initialize(GraphicsDevice gd, List <string> listSource, string header = "", string instructions = "Esc - Exit") { viewPort = new Viewport(); if (!initComplete) { Init(gd); } firstIndexToShowOnScreen = 0; if (header != "") { headerText = new GameText(header, gd); } instructionText = new GameText(instructions, new Point(), gd); bodySource = listSource; }
internal void Initialize(GraphicsDevice gd, SortedDictionary <string, GameText> sortedListSource, string header = "", string instructions = "Esc - Exit") { viewPort = new Viewport(); if (!initComplete) { Init(gd); } firstIndexToShowOnScreen = 0; if (header != "") { headerText = new GameText(header, gd); } instructionText = new GameText(instructions, new Point(), gd); sortedList = sortedListSource; bodySource = new List <string>(); selectable = true; // The only class using the SortedDictionary is Inventory and it needs selectable enabled to work }
/// <summary> /// Attempts to put on a wearable InventoryItem if there is space. Does not remove items to do so. /// </summary> /// <param name="item">Item to put on</param> private static void Equip(InventoryItem item) { if (item == null || !(item is IWearable)) { return; } var wornItem = item as IWearable; if (wornItem.Equipped) { return; } // Identify all items of the same class that are equiped. Most classes will have only // one item equiped at a time, but rings may have more than one. This list is used to // handle removing and replacing one worn item with another. List <InventoryItem> replaces = new List <InventoryItem>(); foreach (var kvPair in inventoryContents) // UniqueID, InventoryItem { if (kvPair.Value.Class != item.Class) { continue; } // If they are the same class, then assume IWearable if ((kvPair.Value as IWearable).Equipped) { replaces.Add(kvPair.Value); } } string attemptResponse = wornItem.Equip(replaces); if (attemptResponse != string.Empty) { InventoryEffectManager.AddMessageToQueue(attemptResponse); closingWindow = true; } GameText inventoryText = inventoryList[searchString]; inventoryText.Text = item.InventoryTitle + wornItem.WornOn; inventoryList.Remove(searchString); inventoryList.Add(item.SortingValue, inventoryText); }
/// <summary> /// Reduces length of text to fit within window. This should only be necessary for magical /// names produced in excess of the limits as user name changes will be guarded against over /// run. /// </summary> /// <param name="textToFit"></param> private void FitCurrentTextToWindow(GameText textToFit) { modifiedText.Clear(); modifiedText.Append(textToFit.Text); currentText.Text = modifiedText.ToString(); // If text is too wide to fit window, append elipses and keep reducing it // until it fits if (currentText.Width > GameConstants.INV_MAX_TITLE_WIDTH) { modifiedText.Append("..."); currentText.Text = modifiedText.ToString(); while (currentText.Width > GameConstants.INV_MAX_TITLE_WIDTH) { modifiedText.Remove(modifiedText.Length - 4, 1); currentText.Text = modifiedText.ToString(); } } }
/// <summary> /// Separates a consumable from the stack (if stackable) and consumes it triggering its effect. /// The weight is adjusted with the loss of the item and the item is removed from the list if it /// is the last of its kind in the stack or otherwise not stackable. Consumed items do not get dropped /// to the floor. /// </summary> /// <param name="item">Item to be consumed.</param> private static void Consume(InventoryItem item) { if (item == null || !(item is IConsumable)) { return; } IConsumable consumedItem; bool lastOfStack = false; if (item is IStackable && (item as IStackable).Qty > 1) { // Preserve old inventoryList Dictionary values on item var oldItemSortingValue = item.SortingValue; var oldItemInventoryGameText = inventoryList[oldItemSortingValue]; // Remove old item from inventoryList (not contents though) inventoryList.Remove(oldItemSortingValue); // Get the consumed item by removing it from the stack consumedItem = (IConsumable)((item as IStackable).Remove()); // Update the GameText object using the new InventoryTitle (incorperates qty change) oldItemInventoryGameText.Text = item.InventoryTitle; // Insert the updated data back into the Dictionary (because the key is different, we couldn't just change it) inventoryList.Add(item.SortingValue, oldItemInventoryGameText); } else { consumedItem = item as IConsumable; lastOfStack = true; } string listKey = item.SortingValue; // Preserve old key in case using an item renames it. // Consume the item and get the string response from it for the message log // Note, that in order for remaining items in the stack to get the new name, Consume must be // called on the stack, not the item being tossed away. string attemptResponse = (item as IConsumable).Consume(); if (attemptResponse != string.Empty) { InventoryEffectManager.AddMessageToQueue(attemptResponse); } if (InventoryEffectManager.HasMessages && currentSelectionAction == SelectionActions.None) { closingWindow = true; } // If last in the stack, remove the stack and update inventory weight if (lastOfStack && inventoryContents.Remove(item.UniqueID)) { inventoryList.Remove(listKey); weight -= item.InventoryWeight; } else // otherwise just update the inventory weight and text if (!lastOfStack) { weight -= (consumedItem as InventoryItem).InventoryWeight; if (item.SortingValue != listKey) { GameText textItem = inventoryList[listKey]; textItem.Text = item.InventoryTitle; inventoryList.Remove(listKey); inventoryList.Add(item.SortingValue, textItem); } } else { throw new IndexOutOfRangeException("Item to be removed not found in the Inventory's Contents List"); } UpdateCurrentItem(); }
internal void Draw(SpriteBatch spriteBatch, Rectangle viewPortBounds) { Color fontColor; viewPort.Bounds = viewPortBounds; graphicsDevice.Viewport = viewPort; spriteBatch.Begin(); // Draw black canvas with frame over viewport Rectangle frame = new Rectangle(0, 0, viewPortBounds.Width, viewPortBounds.Height); Rectangle blackCanvas = new Rectangle(2, 2, frame.Width - 4, frame.Height - 4); spriteBatch.Draw(pixel, frame, frameColor); spriteBatch.Draw(pixel, blackCanvas, Color.Black); int nextTextTop = blackCanvas.Top + GameConstants.TOP_MARGIN; // Displays a header if used if (headerText != null) { // Show header text with underline headerText.Y = nextTextTop; headerText.ForeColor = headerFontColor; headerText.Scale = new Vector2(1.5f, 1.25f); headerText.X = blackCanvas.Left + GameConstants.HEAD_FOOT_LEFT; nextTextTop += (int)(headerText.Height * headerText.Scale.Y); headerText.Draw(spriteBatch); underline.X = headerText.X; underline.Y = nextTextTop; underline.Width = (int)(headerText.Width * headerText.Scale.X); underline.Height = (int)(headerText.Height * GameConstants.UNDERLINE_RATIO); spriteBatch.Draw(pixel, underline, headerFontColor); nextTextTop += underline.Height + (int)(headerText.Height * 0.25f) + GameConstants.LINE_SPACING; } // First, decide which list is provided and update bodySource if sorted dictionary if (sortedList != null) { bodySource.Clear(); foreach (var kvPair in sortedList) { bodySource.Add(kvPair.Value.Text); } } // Display body text when used (May only be a portion of the full list) if (bodySource != null) { // Count how many items will fit in the current view, leaving room at the bottom for instructions viewableListItems = (int)Math.Floor((decimal)(viewPortBounds.Height - nextTextTop) / (bodyText[0].Height + GameConstants.LINE_SPACING)) - 3; //If current selection is below range, move range down if (firstIndexToShowOnScreen < 0 && bodySource.Count > 0) { firstIndexToShowOnScreen = 0; } while (selectedIndex > firstIndexToShowOnScreen + viewableListItems - 1) { firstIndexToShowOnScreen++; } //and the reverse if it is above the range while (selectedIndex < firstIndexToShowOnScreen) { firstIndexToShowOnScreen--; } // Iterate through the list of text to display for (int i = firstIndexToShowOnScreen; i > -1 && i < bodySource.Count && i < firstIndexToShowOnScreen + viewableListItems; i++) { fontColor = selectedIndex == i && selectable ? selectedFontColor : normalFontColor; if (bodyText.Count < i + 1) { bodyText.Add(new GameText(graphicsDevice)); } currentText = bodyText[i]; // Gives currentText a reference to an existing reusable object FitCurrentTextToWindow(bodyText[i]); // changes currentText.Text currentText = new GameText(bodySource[i], graphicsDevice) { X = GameConstants.LIST_LEFT, Y = nextTextTop }; nextTextTop += currentText.Height + GameConstants.LINE_SPACING; currentText.ForeColor = fontColor; currentText.Draw(spriteBatch); } } // Display prompt when used if (promptText != null) { promptText.Y = nextTextTop; promptText.ForeColor = normalFontColor; promptText.X = blackCanvas.Left + GameConstants.HEAD_FOOT_LEFT; nextTextTop += promptText.Height + GameConstants.LINE_SPACING; promptText.Draw(spriteBatch); } // Display user typed text when used if (userResponse != null) { userResponseText.Text = userResponse.ToString().Length == 0 ? " " : userResponse.ToString(); userResponseText.ForeColor = normalFontColor; userResponseText.X = blackCanvas.X + blackCanvas.Width / 2 - userResponseText.Width / 2; userResponseText.Y = nextTextTop; nextTextTop += userResponseText.Height + GameConstants.LINE_SPACING; userResponseText.Draw(spriteBatch); underline.Y = nextTextTop; int minWidth = 100; underline.Width = MathHelper.Max(minWidth, (int)(userResponseText.Width * userResponseText.Scale.X)); underline.Height = (int)(userResponseText.Height * GameConstants.UNDERLINE_RATIO); underline.X = blackCanvas.X + blackCanvas.Width / 2 - underline.Width / 2; spriteBatch.Draw(pixel, underline, userResponseText.ForeColor); nextTextTop += underline.Height + (int)(userResponseText.Height * 0.25f) + GameConstants.LINE_SPACING; } // Display current screen instructions instructionText.Y = (blackCanvas.Top + blackCanvas.Height - instructionText.Height - GameConstants.LINE_SPACING); instructionText.X = blackCanvas.Left + GameConstants.HEAD_FOOT_LEFT; instructionText.ForeColor = screenInstructionFontColor; instructionText.Draw(spriteBatch); spriteBatch.End(); }