/* * DungeonScreen.cs * Authors: Karl Orosz, Brian Chesbrough * Copyright (c) 2007-2008 Cornell University This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty ofz MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ using System; using System.Collections.Generic; using System.IO; using System.Xml; using ColonySim.GUI; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using tAC_Engine.GUI; using Util; namespace StarJack { /// /// This will be where a level will be drawn /// public class DungeonScreen:GameScreen { SpriteBatch mSpriteBatch; //SpriteFont mSpriteFont; InputHandler mInputHandler; Viewport mScreenSpace; Viewport mGamePort; Viewport mUIPort; Point mMousePos; Entity mMouse; Entity mGameFrame; //Screen for the User interface DungeonUIScreen mUIScreen; List mDialogList; List> mTutDiag; DialogScreen mDialogScreen; protected CSMessageDisplayPanel mMessagePanel; private String mMessageString; Texture2D[] mMessageTextures; private PlayerObject mPlayer; private List mEasyLevels; private List mMediumLevels; private List mHardLevels; private Level mCurLevel; public PlayerObject Player { get { return mPlayer; } } //Levelpicking variables private int mDiffRating; private Dictionary mCompletedLevels = new Dictionary(); private Dictionary mFailedLevels = new Dictionary(); private HackingPhaseScreen mHackScreen; private SallyAnneScreen mSallyScreen; private EndScreen mEndScreen; private readonly Logger mLogger; private readonly bool mTutorial; private readonly string mLevelFilePath; //Menu Font TextEntity mSpaceText; public DungeonScreen(Viewport screenSpace, bool tutorial) { mLogger = GetLogger(); mLogger.Initialize(); mTutorial = tutorial; mScreenSpace = screenSpace; } public DungeonScreen(string levelFilePath, Viewport screenSpace, bool tutorial) { mLogger = GetLogger(); mLogger.Initialize(); mTutorial = tutorial; mLevelFilePath = levelFilePath; mScreenSpace = screenSpace; } /// /// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// public override void Initialize() { mDialogList = new List(); mGamePort = new Viewport(); mUIPort = new Viewport(); mUIPort.X = 0; mUIPort.Y = 0; mUIPort.Width = (int)(mScreenSpace.Width * 0.20f); mUIPort.Height = mScreenSpace.Height; mGamePort.X = mUIPort.Width; mGamePort.Y = 0; mGamePort.Width = mScreenSpace.Width - mUIPort.Width; mGamePort.Height = mUIPort.Height; Tile.HEIGHT = mGamePort.Height / Room.TILECOUNT; Tile.WIDTH = mGamePort.Width / Room.TILECOUNT; //Creates the UI Screen mUIScreen = new DungeonUIScreen(mUIPort, this); Raise(mUIScreen); mUIScreen.UIPort = mUIPort; mGameFrame = new Entity("Frame"); mGameFrame.TextureName = "GameFrame"; mGameFrame.X = 0; mGameFrame.Y = 0; mGameFrame.Width = mGamePort.Width; mGameFrame.Height = mGamePort.Height; mGameFrame.Depth = Room.Depth.UI; mInputHandler = GetInputHandler(); mInputHandler.Initialize(); mInputHandler.BindButton(Keys.Down, Trigger.Activated, (int)SJInputEvent.Down); mInputHandler.BindButton(Keys.Up, Trigger.Activated, (int)SJInputEvent.Up); mInputHandler.BindButton(Keys.Right, Trigger.Activated, (int)SJInputEvent.Right); mInputHandler.BindButton(Keys.Left, Trigger.Activated, (int)SJInputEvent.Left); mInputHandler.BindButton(Keys.Space, Trigger.Activated, (int)SJInputEvent.Interact); mInputHandler.BindButton(Keys.LeftShift, Trigger.Activated, (int)SJInputEvent.Trap); mInputHandler.BindButton(Keys.RightShift, Trigger.Activated, (int)SJInputEvent.Trap); mInputHandler.BindButton(Keys.LeftControl, Trigger.Activated, (int)SJInputEvent.Cloak); mInputHandler.BindButton(Keys.RightControl, Trigger.Activated, (int)SJInputEvent.Cloak); mInputHandler.BindButton(Keys.Enter, Trigger.Activated, (int)SJInputEvent.Skip); mInputHandler.BindButton(Keys.L, Trigger.Activated, (int)SJInputEvent.LOSDrawToggle); #if DEBUG mInputHandler.BindButton(Keys.OemTilde, Trigger.Activated, (int)SJInputEvent.SkipRoom); #endif //message panel stuff for tutorial mMessagePanel = new CSMessageDisplayPanel("dialogfontLarge"); LoadDataFile(); mPlayer = new PlayerObject("player", true); mPlayer.Facing = GameObject.Direction.Down; mPlayer.Collision = true; // Initialize level(s) if (!mTutorial) { if (string.IsNullOrEmpty(mLevelFilePath)) { LoadLevels(); PickLevel(); } else { mCurLevel = Level.Load(mLevelFilePath, this); } } else //Start tutorial { mCurLevel = Level.Load(RootDirectory + @"\tutorialLevel.xml", this); } mCurLevel.curRoom = mCurLevel.Rooms[0]; mPlayer.MyRoom = mCurLevel.curRoom; mPlayer.Position = mCurLevel.curRoom.PlayerStartingPos; mCurLevel.curRoom.Player = mPlayer; mLogger.Write((int)EventCode.RoomStart, "SJ_START Level=" + mCurLevel.Name + " Room=" + mCurLevel.curRoom.Name); mMousePos = new Point(0, 0); mMouse = new Entity("Mouse"); mMouse.TextureName = "Cursor"; mMouse.Width = 32; mMouse.Height = 32; mMouse.X = mMousePos.X; mMouse.Y = mMousePos.Y; mMouse.Depth = Room.Depth.Mouse; LOSCheckAI.Mouse = mMouse; LOSCheckAI.MouseOver = true; mUIScreen.Player = mPlayer; mSpaceText = new TextEntity("Press space to continue"); mSpaceText.FontName = "dialogfont"; base.Initialize(); //Press Space to contiune dialog //mSpaceText.SpriteFont = mSpriteFont; mSpaceText.Width = 300; mSpaceText.Height = mSpaceText.SpriteFont.LineSpacing; mSpaceText.Color = Color.White; mSpaceText.Depth = Room.Depth.Mouse; //mMessagePanel.LayerDepth = 1; mTutDiag = new List>(); if (mTutorial) { mMessageTextures = new Texture2D[0]; mMessageString = "Welcome to Star Jack!"; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\Icons\pirate"); mMessageString = "Pirates # are stealing our cargo. Your mission is to help get the cargo back."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\Tutorial\TerminalRed"); mMessageString = "You must sneak into the pirates' base, and hack into their computers # to get information."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\Tutorial\ArrowKeys"); mMessageString = "To move, use the arrow keys #."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); } } /// /// Checks for the starjack data file /// If it exists, loads the levels completed, levels failed, and difficulty rating /// private void LoadDataFile() { mCompletedLevels = new Dictionary(); mFailedLevels = new Dictionary(); if (File.Exists(GlobalRootStorageDirectory + UserProfileUtility.OutputDirectory + "starjack.xml")) { // read the xml data XmlTextReader xmlRdr = new XmlTextReader(GlobalRootStorageDirectory + UserProfileUtility.OutputDirectory + "starjack.xml"); while (xmlRdr.Read()) { //if the node is an element aka if (xmlRdr.NodeType == XmlNodeType.Element) { if (xmlRdr.Name == "PlayerData") { if (xmlRdr.HasAttributes) { mDiffRating = Convert.ToInt32(xmlRdr.GetAttribute("DifficultyRating")); } } else if (xmlRdr.Name == "LevelsCompleted") { XmlReader xmlRdrCompleted = xmlRdr.ReadSubtree(); xmlRdrCompleted.Read(); xmlRdrCompleted.Read(); while (xmlRdrCompleted.NodeType == XmlNodeType.Element ) mCompletedLevels[xmlRdrCompleted.Name] = xmlRdrCompleted.ReadElementContentAsInt(); } else if (xmlRdr.Name == "LevelsFailed") { XmlReader xmlRdrFailed = xmlRdr.ReadSubtree(); xmlRdrFailed.Read(); xmlRdrFailed.Read(); while (xmlRdrFailed.NodeType == XmlNodeType.Element) mFailedLevels[xmlRdrFailed.Name] = xmlRdrFailed.ReadElementContentAsInt(); } } } } } private void SaveDataFile() { //if starjack datafile doesnt exist yet, create one if (!File.Exists(GameScreen.GlobalRootStorageDirectory + Util.UserProfileUtility.OutputDirectory + "starjack.xml")) { //create a new data file FileStream sdf = File.Create(GameScreen.GlobalRootStorageDirectory + Util.UserProfileUtility.OutputDirectory + "starjack.xml"); sdf.Close(); } //Update the Data file with the new data XmlWriter writer = XmlWriter.Create(GameScreen.GlobalRootStorageDirectory + Util.UserProfileUtility.OutputDirectory + "starjack.xml"); writer.WriteStartDocument(); writer.WriteStartElement("PlayerData"); writer.WriteStartAttribute("DifficultyRating"); writer.WriteValue(mDiffRating); writer.WriteEndAttribute(); writer.WriteStartElement("LevelsCompleted"); Dictionary.Enumerator completedEnumerator = mCompletedLevels.GetEnumerator(); while (completedEnumerator.MoveNext()) { KeyValuePair levelCompleted = completedEnumerator.Current; writer.WriteStartElement(levelCompleted.Key); writer.WriteValue(levelCompleted.Value); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteStartElement("LevelsFailed"); Dictionary.Enumerator failedEnumerator = mFailedLevels.GetEnumerator(); while (failedEnumerator.MoveNext()) { KeyValuePair levelFailed = failedEnumerator.Current; writer.WriteStartElement(levelFailed.Key); writer.WriteValue(levelFailed.Value); writer.WriteEndElement(); } writer.WriteEndElement(); // end PlayerData writer.WriteEndElement(); writer.WriteEndDocument(); writer.Flush(); writer.Close(); } private void LoadLevels() { mEasyLevels = new List(); mMediumLevels = new List(); mHardLevels = new List(); string[] levelFileNames = Directory.GetFiles(RootDirectory + @"\Levels"); foreach (string fileName in levelFileNames) { Level level = Level.Load(fileName, this); switch (level.difficulty) { case 1: mEasyLevels.Add(level); break; case 2: mMediumLevels.Add(level); break; case 3: mHardLevels.Add(level); break; } } } /// /// LoadContent will be called once per game and is the place to load /// all of your content. /// protected override void LoadContent() { mSpriteBatch = new SpriteBatch(GraphicsDevice); //mSpriteFont = Content.Load(@"Fonts\dialogfont"); AnimationManager.LoadContent(Content); mCurLevel.curRoom.LoadContent(Content); mPlayer.LoadContent(Content); mMouse.LoadContent(Content); mGameFrame.LoadContent(Content); mSpaceText.LoadContent(Content); mMessagePanel.Position = new Vector2(2 * GraphicsDevice.Viewport.Width / 20f, 2 * GraphicsDevice.Viewport.Height / 10f); mMessagePanel.Size = new Vector2((6 * GraphicsDevice.Viewport.Width / 10f), (4 * GraphicsDevice.Viewport.Height / 10f)); mMessagePanel.DisplayTime = 5000.0f; mMessagePanel.ClickThrough = true; mMessagePanel.Visible = false; mMessagePanel.Initialize(); mMessagePanel.AddColor = new Color(255, 255, 255, 220); mMessagePanel.LoadContent(Content, this); // Set a SpriteBatchProxy (normally done by parent GUIScreen) mMessagePanel.Batch = new SpriteBatchProxy(mSpriteBatch); base.LoadContent(); } /// /// Picks a level calculated from the players Difficulty rating and levels completed /// private void PickLevel() { List possibleLevels = new List(); System.Random random = new System.Random(); int randomLvlNum; bool addLevel; //Calculate what levels to pick from based off levels completed/failed list if (mDiffRating < mEasyLevels.Count || (mMediumLevels.Count == 0 && mHardLevels.Count == 0)) { //pick an easy level for (int i = 0; i < mEasyLevels.Count; i++) { addLevel = true; //for (int j = 0; j < mCompletedLevels.Count; j++) //{ //if (mEasyLevels[i].Name == mCompletedLevels[j]) if(mCompletedLevels.ContainsKey(mEasyLevels[i].Name)) { addLevel = false; } //} if (addLevel) { possibleLevels.Add(mEasyLevels[i]); } } //pick level if (possibleLevels.Count != 0) //player has undefeated levels in this level bracket { randomLvlNum = random.Next(0, (possibleLevels.Count)); mCurLevel = possibleLevels[randomLvlNum]; } else //player has lost in next difficulty bracket and needs to replay a level at random from this bracket { randomLvlNum = random.Next(0, (mEasyLevels.Count)); mCurLevel = mEasyLevels[randomLvlNum]; } } else if (mDiffRating < mEasyLevels.Count + mMediumLevels.Count || mHardLevels.Count == 0) { // pick a medium level for (int i = 0; i < mMediumLevels.Count; i++) { addLevel = true; //for (int j = 0; j < mCompletedLevels.Count; j++) //{ if (mCompletedLevels.ContainsKey(mMediumLevels[i].Name)) //if (mMediumLevels[i].Name == mCompletedLevels[i]) { addLevel = false; } //} if (addLevel) { possibleLevels.Add(mMediumLevels[i]); } } //pick level if (possibleLevels.Count != 0) //player has undefeated levels in this level bracket { randomLvlNum = random.Next(0, (possibleLevels.Count)); mCurLevel = possibleLevels[randomLvlNum]; } else //player has lost in next difficulty bracket and needs to replay a level at random from this bracket { randomLvlNum = random.Next(0, (mMediumLevels.Count)); mCurLevel = mMediumLevels[randomLvlNum]; } } else if (mDiffRating >= mEasyLevels.Count + mMediumLevels.Count) //pick a hard level { for (int i = 0; i < mHardLevels.Count; i++) { addLevel = true; //for (int j = 0; j < mCompletedLevels.Count; j++) //{ if (mCompletedLevels.ContainsKey(mHardLevels[i].Name)) //if (mHardLevels[i].Name == mCompletedLevels[i]) { addLevel = false; } //} if (addLevel) { possibleLevels.Add(mHardLevels[i]); } } //pick level if (possibleLevels.Count != 0) //player has undefeated levels in this level bracket { randomLvlNum = random.Next(0, (possibleLevels.Count)); mCurLevel = possibleLevels[randomLvlNum]; } else //player has beaten all levels in the game, pick a level from hard at random { randomLvlNum = random.Next(0, (mHardLevels.Count)); mCurLevel = mHardLevels[randomLvlNum]; } } mCurLevel.curRoom = mCurLevel.Rooms[0]; } /// /// UnloadContent will be called once per game and is the place to unload /// all content. /// protected override void UnloadContent() { } public override void Reinitialize() { mInputHandler.Enable(); Enabled = true; Visible = true; mUIScreen.Visible = true; mUIScreen.Enabled = true; } /// /// Disposes of any IDisposables in DungeonScreen. /// /// Whether or not this is currently being disposed protected override void Dispose(bool disposing) { if (disposing) { if(mSpriteBatch != null) mSpriteBatch.Dispose(); } base.Dispose(disposing); } /// /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// /// Provides a snapshot of timing values. public override void Update(GameTime gameTime) { base.Update(gameTime); bool playerAction = false; //Point mousePoint = mInputHandler.MouseLocation; mMousePos = MouseViewportLocation(mInputHandler.MouseLocation, mGamePort); mMouse.X = mMousePos.X; mMouse.Y = mMousePos.Y; if (mMessagePanel.Visible) { mMessagePanel.Update(gameTime); } if (mPlayer.mLogList.Count > 0) { LogPlayerEvent(); } foreach (GameObject go in mCurLevel.curRoom.GameObjects) { Enemy enm = go as Enemy; if (enm != null) { if (enm.mTraped == false && enm.AIEnable == false) { enm.mTraped = true; mLogger.Write((int)EventCode.GuardTrapped, "SJ_GuardTrapped X=" + enm.X + " Y=" + enm.Y); } } } if (mPlayer.MyRoom.State != Room.GameState.TurnRoutines) { while (mInputHandler.HasEvent() && !playerAction) { InputEvent e = mInputHandler.GetNextEvent(); if (mMessagePanel.Visible) { switch ((SJInputEvent)e.EventCode) { case SJInputEvent.Interact: e.WriteToLog(mLogger, "SJ_INPUT_Interact"); mMessagePanel.Visible = false; break; default: e.WriteToLog(mLogger, "IGNORE"); break; } } else { //int[] pos = new int[2]; switch ((SJInputEvent)e.EventCode) { #if DEBUG case SJInputEvent.SkipRoom: e.WriteToLog(mLogger, "SJ_INPUT_SkipRoom"); mCurLevel.curRoom.State = Room.GameState.End; break; #endif case SJInputEvent.Skip: e.WriteToLog(mLogger, "SJ_INPUT_SkipTurn"); mPlayer.TakeTurn(0, false); playerAction = true; break; case SJInputEvent.Cloak: e.WriteToLog(mLogger, "SJ_INPUT_Cloak"); mPlayer.Cloak = PlayerObject.CloakTime; playerAction = true; break; case SJInputEvent.Up: e.WriteToLog(mLogger, "SJ_INPUT_Move_Up"); mPlayer.Move(GameObject.Direction.Up, true); playerAction = true; break; case SJInputEvent.Down: e.WriteToLog(mLogger, "SJ_INPUT_Move_Down"); mPlayer.Move(GameObject.Direction.Down, true); playerAction = true; break; case SJInputEvent.Left: e.WriteToLog(mLogger, "SJ_INPUT_Move_Left"); mPlayer.Move(GameObject.Direction.Left, true); playerAction = true; break; case SJInputEvent.Right: e.WriteToLog(mLogger, "SJ_INPUT_Move_Right"); mPlayer.Move(GameObject.Direction.Right, true); playerAction = true; break; case SJInputEvent.Interact: e.WriteToLog(mLogger, "SJ_INPUT_Interact"); mPlayer.Interact(); playerAction = true; break; case SJInputEvent.Trap: e.WriteToLog(mLogger, "SJ_INPUT_PlaceTrap"); mPlayer.PlaceTrap(); playerAction = true; break; case SJInputEvent.LOSDrawToggle: e.WriteToLog(mLogger, "SJ_INPUT_LineOfSight_Toggle"); LOSCheckAI.ToggleLOSDraw(); break; } } mInputHandler.ClearEvents(); } } else { mInputHandler.ClearEvents(); } //Check the player for any tutorial events that may have occured. if (mTutorial) { //check player object for tutorial events, then fire off any messages that need to be told to the player if (mPlayer.mEventList.Count > 0) { DisplayDialog(mPlayer.mEventList[0]); } } switch (mCurLevel.curRoom.State) { case Room.GameState.Dungeon: mCurLevel.curRoom.Update(gameTime); break; case Room.GameState.Hacking: if (mHackScreen == null) { mHackScreen = new HackingPhaseScreen(mCurLevel.curRoom.Hacked); Raise(mHackScreen); mInputHandler.Disable(); Visible = false; Enabled = false; mUIScreen.Visible = false; mUIScreen.Enabled = false; } else { if (mHackScreen.Win && !(mCurLevel.curRoom.Hacked is SallyAnneObject)) { mDialogList.Add(new Dialog("Hack Result", ColorFinder.GetString(mCurLevel.curRoom.Hacked.LinkedColor) + " objects deactivated", null, Corner.BottomLeft, 0, true)); } mCurLevel.curRoom.EndHackingPhase(mHackScreen.Win); mHackScreen = null; } break; case Room.GameState.SallyAnne: if (mSallyScreen == null) { mSallyScreen = new SallyAnneScreen(); Raise(mSallyScreen); mInputHandler.Disable(); Visible = false; Enabled = false; mUIScreen.Visible = false; mUIScreen.Enabled = false; } else { mDialogList.Add(new Dialog("Comm Terminal Result", "Transport and Resource comm logs retrieved!\nProceed to the active transporter!", null, Corner.BottomLeft, -1, true)); mCurLevel.curRoom.EndSallyPhase(false); mSallyScreen = null; mHackScreen = null; } break; case Room.GameState.End: //log end mLogger.Write((int)EventCode.RoomEnd, "SJ_END Level=" + mCurLevel.Name + " Room=" + mCurLevel.curRoom.Name); //increase room/level //true means more rooms, false means level completed if (mCurLevel.NextRoom()) { //TODO: some sort of fade perhaps? //start up next room mPlayer.MyRoom = mCurLevel.curRoom; mPlayer.Position = mCurLevel.curRoom.PlayerStartingPos; mCurLevel.curRoom.Player = mPlayer; mLogger.Write((int)EventCode.RoomStart, "SJ_START Level=" + mCurLevel.Name + " Room=" + mCurLevel.curRoom.Name); LoadContent(); } else // Level completed { mDiffRating++; // updated completed level data if (mCompletedLevels.ContainsKey(mCurLevel.Name)) mCompletedLevels[mCurLevel.Name]++; else mCompletedLevels.Add(mCurLevel.Name, 1); SaveDataFile(); // TODO: SCORING + FINISH SCREEN MiniGameInfo.HasPlayed = true; MiniGameInfo.ScoreValue += 5000; //Load end game screen //TODO: Incorprate info from play sessioin into the EndGame constructor mEndScreen = new EndScreen(true); Raise(mEndScreen); mInputHandler.Disable(); Visible = false; Enabled = false; mUIScreen.Visible = false; mUIScreen.Enabled = false; } break; case Room.GameState.TurnRoutines: mCurLevel.curRoom.Update(gameTime); if (mCurLevel.curRoom.State == Room.GameState.Dungeon && mTutDiag.Count > 0 && mMessagePanel.Visible == false) { mMessagePanel.MessageIcons = mTutDiag[0].Value; mMessagePanel.DisplayMessage(mTutDiag[0].Key); mTutDiag.RemoveAt(0); } break; case Room.GameState.Failure: //Player ran out of energy. mLogger.Write((int)EventCode.RoomEnd, "SJ_END_FAILURE Level=" + mCurLevel.Name); mDiffRating--; // update failed levels data if (mFailedLevels.ContainsKey(mCurLevel.Name)) mFailedLevels[mCurLevel.Name]++; else mFailedLevels.Add(mCurLevel.Name, 1); SaveDataFile(); // TODO: SCORING + FINISH SCREEN MiniGameInfo.HasPlayed = true; //Load end game fail screen mEndScreen = new EndScreen(false); Raise(mEndScreen); mInputHandler.Disable(); Visible = false; Enabled = false; mUIScreen.Visible = false; mUIScreen.Enabled = false; break; } // mPlayer.Update(gameTime); switch (mPlayer.StateOfPlayer) { case PlayerObject.PlayerState.Caught: mPlayer.StateOfPlayer = PlayerObject.PlayerState.Normal; mDialogList.Add(new Dialog("Secuity System", "Intruder Detected!!!", null, Corner.BottomLeft, -1, true)); break; case PlayerObject.PlayerState.NoPower: //This is where we will handle mission failure mPlayer.StateOfPlayer = PlayerObject.PlayerState.Normal; mDialogList.Add(new Dialog("Commander", "Oh no! You're out of energy! We need to get you out now!", null, Corner.BottomLeft, -1, true)); mCurLevel.curRoom.State = Room.GameState.Failure; break; } //If there's dialog to be displayed display it! if (mDialogList.Count > 0) { mDialogScreen = new DialogScreen(mDialogList); Raise(mDialogScreen); //Disable the dungeon screen mInputHandler.Disable(); Enabled = false; mDialogList.Clear(); } if (mTutDiag.Count > 0 && mMessagePanel.Visible == false && mCurLevel.curRoom.State != Room.GameState.TurnRoutines) { mMessagePanel.MessageIcons = mTutDiag[0].Value; mMessagePanel.DisplayMessage(mTutDiag[0].Key); mTutDiag.RemoveAt(0); } } public void LogPlayerEvent() { switch (mPlayer.mLogList[0]) { case 1: mLogger.Write((int)EventCode.CaughtByGuard, "SJ_Caught_TeleportToStart"); break; case 2: mLogger.Write((int)EventCode.CloackStart, "SJ_Cloak_Start"); break; case 3: mLogger.Write((int)EventCode.CloackEnd, "SJ_Cloak_End"); break; case 4: mLogger.Write((int)EventCode.TrapPlaced, "SJ_TrapPlaced"); break; } mPlayer.mLogList.RemoveAt(0); } public void DisplayDialog(int eventNumber) { switch (eventNumber) { case 1: //Introduction to Doors and color coded terminals mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\Tutorial\DoorRed"); mMessageString = "This door # is locked!"; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\Tutorial\TerminalRed"); mMessageString = "To open the door, find the computer # with the same colour as the door. "; DisplayMessagePanel(mMessageString, mMessageTextures, -1); break; case 2: //Intro to hacking phase and terminals mMessageTextures = new Texture2D[2]; mMessageTextures[0] = Content.Load(@"Texture\Tutorial\DoorRed"); mMessageTextures[1] = Content.Load(@"Texture\Tutorial\TerminalRed"); mMessageString = "To open the door # you will need to hack into this computer! #"; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\Tutorial\TerminalRed"); mMessageString = "The computer # uses geometric codes. To hack it, find the shapes inside the codes."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\Tutorial\Left"); mMessageString = "You will press the left key # if the shape is in the code."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\Tutorial\Right"); mMessageString = "And press the right key # if the shape is not in the code."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\Start"); mMessageString = "It's okay to make mistakes: three mistakes in a row will teleport you back to the start # so you won't get caught."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[2]; mMessageTextures[0] = Content.Load(@"Texture\Tutorial\FaceTerminal"); mMessageTextures[1] = Content.Load(@"Texture\Hack"); mMessageString = "To start hacking, face the computer # and click on the hack button # or press the space bar."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); break; case 3: //exiting the room mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\LevelEnd\Active"); mMessageString = "Move onto the teleporter # to go to the next room."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); break; case 4: //Intro to Cloak, Cameras, Line of sight, and getting caught mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\Camera\Active"); mMessageString = "Be careful of the cameras! #"; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[2]; mMessageTextures[0] = Content.Load(@"Texture\LOS"); mMessageTextures[1] = Content.Load(@"Texture\Start"); mMessageString = "If you walk into the red # you'll go back to the beginning #."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\LOS"); mMessageString = "To get past the red #, use your cloak."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[2]; mMessageTextures[0] = Content.Load(@"Texture\Cloak"); mMessageTextures[1] = Content.Load(@"Texture\Tutorial\ctrl"); mMessageString = "To turn on your cloak, click on the cloak button # or press the Ctrl key #."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); break; case 5: //reminder about how to initiate a hack mMessageTextures = new Texture2D[2]; mMessageTextures[0] = Content.Load(@"Texture\Tutorial\DoorRed"); mMessageTextures[1] = Content.Load(@"Texture\Tutorial\TerminalRed"); mMessageString = "To open the door # you will need to hack into the computer! #"; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[2]; mMessageTextures[0] = Content.Load(@"Texture\Tutorial\FaceTerminal"); mMessageTextures[1] = Content.Load(@"Texture\Hack"); mMessageString = "To start hacking, face the computer # and click on the hack button # or press the space bar."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); break; case 6: //intro to guards, patrolling and traps mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\Guard\Left"); mMessageString = "The guards # always walk the same way."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\Guard\Left"); mMessageString = "Use your cloak to sneak past the guards. #"; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[2]; mMessageTextures[0] = Content.Load(@"Texture\Cloak"); mMessageTextures[1] = Content.Load(@"Texture\Tutorial\ctrl"); mMessageString = "To turn on your cloak, click on the cloak button # or press the Ctrl key #."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); break; case 7: mMessageTextures = new Texture2D[2]; mMessageTextures[0] = Content.Load(@"Texture\Mine"); mMessageTextures[1] = Content.Load(@"Texture\Guard\Left"); mMessageString = "You can set traps # to catch the guards. #"; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[3]; mMessageTextures[0] = Content.Load(@"Texture\Mine"); mMessageTextures[1] = Content.Load(@"Texture\Trap"); mMessageTextures[2] = Content.Load(@"Texture\Tutorial\Shift"); mMessageString = "To set a trap in front of you # click on the trap button # or press the Shift key #."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); break; case 8: mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\LOS"); mMessageString = "To get past the red #, use your cloak."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[2]; mMessageTextures[0] = Content.Load(@"Texture\Cloak"); mMessageTextures[1] = Content.Load(@"Texture\Tutorial\ctrl"); mMessageString = "To turn on your cloak, click on the cloak button # or press the Ctrl key #."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); break; case 9: //Terminals turning off cameras mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\Camera\Active"); mMessageString = "That's a lot of cameras! # Your cloak won't last through all of them. "; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[2]; mMessageTextures[0] = Content.Load(@"Texture\Camera\Active"); mMessageTextures[1] = Content.Load(@"Texture\Terminal\Active"); mMessageString = "To turn off a camera #, hack into the computer # with the same colour as the camera."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[2]; mMessageTextures[0] = Content.Load(@"Texture\Tutorial\FaceTerminal"); mMessageTextures[1] = Content.Load(@"Texture\Hack"); mMessageString = "To start hacking, face the computer # and click on the hack button # or press the space bar."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); break; case 10: //Intro to sally anne phase and terminals mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\Console\Active"); mMessageString = "At the end of each Level you will find the main console. #"; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\Tutorial\TerminalRed"); mMessageString = "This is harder to hack than normal computers. #"; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[1]; mMessageTextures[0] = Content.Load(@"Texture\Console\Active"); mMessageString = "After you hack the console # you can see pictures of the pirates."; DisplayMessagePanel(mMessageString, mMessageTextures, -1); mMessageTextures = new Texture2D[0]; mMessageString = "Watch the pictures, then follow the instructions to tell our commander what you see!"; DisplayMessagePanel(mMessageString, mMessageTextures, -1); break; } //pop the top event from the array mPlayer.mEventList.RemoveAt(0); } /// /// Display a message in a panel in Starjack for the given amount /// of time, in milliseconds. /// /// The string and relative icon positions. /// The icons to display. /// The amount of time to display for. public void DisplayMessagePanel(string pMessageString, Texture2D[] pIconArray, float pTime) { mMessagePanel.DisplayTime = pTime; mMessagePanel.ClickThrough = true; mTutDiag.Add(new KeyValuePair(pMessageString,pIconArray)); //mMessagePanel.DisplayMessage(pMessageString); } /// /// This is called when the game should draw itself. /// /// Provides a snapshot of timing values. public override void Draw(GameTime gameTime) { Viewport previous = GraphicsDevice.Viewport; //Dungeon Viewport draw GraphicsDevice.Viewport = mGamePort; mSpriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.BackToFront, SaveStateMode.None); mCurLevel.curRoom.Draw(mSpriteBatch); mPlayer.Draw(mSpriteBatch); mGameFrame.Draw(mSpriteBatch); mMouse.Draw(mSpriteBatch); mSpriteBatch.End(); mSpriteBatch.Begin(); if (mMessagePanel.Visible) { mSpaceText.X = (int)mMessagePanel.Position.X; mSpaceText.Y = (int)(mMessagePanel.Position.Y + mMessagePanel.Size.Y - mSpaceText.Height); mMessagePanel.Draw(gameTime); mSpaceText.Draw(mSpriteBatch); } mSpriteBatch.End(); GraphicsDevice.Viewport = previous; } public void End() { mLogger.Dispose(); Done(); } } }