/// <summary> /// If the room has changed, then performs all the necessary updates to vars, flags, /// animated objects, controllers, and other state to prepare for entry in to the /// next room. If the room hasn't changed, it returns false up front and does nothing /// else. /// </summary> /// <param name="roomNum"></param> /// <returns>true if the room has changed; otherwise false.</returns> private bool NewRoom(byte roomNum) { // Has the room changed? if (roomNum == state.CurrentRoom) { return(false); } // Simulate a slow room change if there is a text window open. if (textGraphics.IsWindowOpen()) { Thread.Sleep(1000); } // Turn off sound. soundPlayer.StopSound(); // Clear the script event buffer ready for next room. state.ScriptBuffer.InitScript(); state.ScriptBuffer.ScriptOn(); // Resets the Logics, Views, Pictures and Sounds back to new room state. state.ResetResources(); // Carry over ego's view number. // TODO: For some reason in MH2, the ego View can be null at this point. Needs investigation to determine why. if (ego.View != null) { state.Vars[Defines.CURRENT_EGO] = (byte)ego.View.Index; } // Reset state for all animated objects. foreach (AnimatedObject aniObj in state.AnimatedObjects) { aniObj.Reset(); } // Current room logic is loaded automatically on room change and not directly by load.logic Logic logic = state.Logics[roomNum]; logic.IsLoaded = true; state.ScriptBuffer.AddScript(ScriptBuffer.ScriptBufferEventType.LoadLogic, logic.Index); // If ego collided with a border, set his position in the new room to // the appropriate edge of the screen. switch (state.Vars[Defines.EGOEDGE]) { case Defines.TOP: ego.Y = Defines.MAXY; break; case Defines.RIGHT: ego.X = Defines.MINX; break; case Defines.BOTTOM: ego.Y = Defines.HORIZON + 1; break; case Defines.LEFT: ego.X = (short)(Defines.MAXX + 1 - ego.XSize); break; } // Change the room number. Note that some games, e.g. MH2, change the CURROOM VAR directly, // which is why we also track the CurrentRoom in a separate state variable. We can't rely // on the AGI VAR that stores the current room. state.Vars[Defines.PREVROOM] = state.CurrentRoom; state.Vars[Defines.CURROOM] = state.CurrentRoom = roomNum; // Set flags and vars as appropriate for a new room. state.Vars[Defines.OBJHIT] = 0; state.Vars[Defines.OBJEDGE] = 0; state.Vars[Defines.UNKNOWN_WORD] = 0; state.Vars[Defines.EGOEDGE] = 0; state.Flags[Defines.INPUT] = false; state.Flags[Defines.INITLOGS] = true; state.UserControl = true; state.Blocking = false; state.Horizon = Defines.HORIZON; state.ClearControllers(); // Draw the status line background if applicable. if (state.ShowStatusLine) { textGraphics.ClearLines(state.StatusLineRow, state.StatusLineRow, 15); } // Return true to indicate to the scan loop to rescan. return(true); }
/// <summary> /// Opens the menu system and processes all the navigation events until an item is either /// selected or the ESC key is pressed. /// </summary> public void MenuInput() { // Not sure why there is an ENABLE_MENU flag and the allow.menu command, but there is. if (state.Flags[Defines.ENABLE_MENU] && state.MenuEnabled) { // Clear the menu bar to white. textGraphics.ClearLines(0, 0, 15); // Draw each of the header titles in deselected mode. foreach (MenuHeader header in headers) { Deselect(header.Title); } // Starts by showing the currently selected menu header and item. ShowMenu(currentHeader); // Now we process all navigation keys until we the user either makes a selection // or exits the menu system. while (true) { int index; switch (userInput.WaitForKey()) { case (int)Keys.Enter: // Select the currently highlighted menu item. if (!currentItem.Enabled) { continue; } state.Controllers[currentItem.Controller] = true; PutAwayMenu(currentHeader, currentItem); RestoreMenuLine(); state.MenuOpen = false; return; case (int)Keys.Escape: // Exit the menu system without a selection. PutAwayMenu(currentHeader, currentItem); RestoreMenuLine(); state.MenuOpen = false; return; case (int)Keys.Up: // Moving up within current menu. Deselect(currentItem); index = (currentHeader.Items.IndexOf(currentItem) + currentHeader.Items.Count - 1) % currentHeader.Items.Count; currentItem = currentHeader.Items[index]; Select(currentItem); break; case (int)Keys.PageUp: // Move to top item of current menu. Deselect(currentItem); currentItem = currentHeader.Items.First(); Select(currentItem); break; case (int)Keys.Right: // Move to the menu on the right of the current menu.. PutAwayMenu(currentHeader, currentItem); index = headers.IndexOf(currentHeader); do { currentHeader = headers[(index = ((index + 1) % headers.Count))]; }while (!currentHeader.Title.Enabled); currentItem = currentHeader.CurrentItem; ShowMenu(currentHeader); break; case (int)Keys.PageDown: // Move to bottom item of current menu. Deselect(currentItem); currentItem = currentHeader.Items.Last(); Select(currentItem); break; case (int)Keys.Down: // Move down within current menu. Deselect(currentItem); index = (currentHeader.Items.IndexOf(currentItem) + 1) % currentHeader.Items.Count; currentItem = currentHeader.Items[index]; Select(currentItem); break; case (int)Keys.End: // Move to the rightmost menu. PutAwayMenu(currentHeader, currentItem); currentHeader = headers.Last(); currentItem = currentHeader.CurrentItem; ShowMenu(currentHeader); break; case (int)Keys.Left: // Move left within current menu. PutAwayMenu(currentHeader, currentItem); index = headers.IndexOf(currentHeader); do { currentHeader = headers[(index = ((index + headers.Count - 1) % headers.Count))]; }while (!currentHeader.Title.Enabled); currentItem = currentHeader.CurrentItem; ShowMenu(currentHeader); break; case (int)Keys.Home: // Move to the leftmost menu. PutAwayMenu(currentHeader, currentItem); currentHeader = headers.First(); currentItem = currentHeader.CurrentItem; ShowMenu(currentHeader); break; } } } }