/// <summary> /// Choose which offensive action to perform. /// </summary> /// <returns>The chosen action, or null if no action is desired.</returns> private CombatAction ChooseOffensiveAction() { List <CombatantPlayer> players = CombatEngine.Players; // be sure that there is a valid combat in progress if ((players == null) || (players.Count <= 0)) { return(null); } // randomly choose a living target from the party int targetIndex; do { targetIndex = Session.Random.Next(players.Count); }while (players[targetIndex].IsDeadOrDying); CombatantPlayer target = players[targetIndex]; // the action lists are sorted by descending potential, // so find the first eligible action foreach (CombatAction action in offensiveActions) { // check the restrictions on the action if (action.IsCharacterValidUser) { action.Target = target; return(action); } } // no eligible actions found return(null); }
/// <summary> /// Start the given player's combat turn. /// </summary> private void BeginPlayerTurn(CombatantPlayer player) { // check the parameter if (player == null) { throw new ArgumentNullException("player"); } // set the highlight sprite highlightedCombatant = player; primaryTargetedCombatant = null; secondaryTargetedCombatants.Clear(); Session.Hud.ActionText = "Choose an Action"; }
private void DrawCombatPlayerDetails(CombatantPlayer player, Vector2 position) { SpriteBatch spriteBatch = screenManager.SpriteBatch; PlankState plankState; bool isPortraitActive = false; bool isCharDead = false; Color color; portraitPosition.X = position.X + 7f; portraitPosition.Y = position.Y + 7f; namePosition.X = position.X + 84f; namePosition.Y = position.Y + 12f; levelPosition.X = position.X + 84f; levelPosition.Y = position.Y + 39f; detailPosition.X = position.X + 25f; detailPosition.Y = position.Y + 66f; position.X -= 2; position.Y -= 4; // check click for select slab // TODO NEXT NOW bool bracketClicked = false; if (actionText.Contains("Choose")) { Rectangle rectBrackets = new Rectangle((int)portraitPosition.X, (int)portraitPosition.Y, selectionBracketTexture.Width, selectionBracketTexture.Height); bracketClicked = InputManager.IsButtonClicked(rectBrackets); } if (bracketClicked && !player.IsTurnTaken &&!player.IsDeadOrDying) { CombatEngine.HighlightedCombatant = player; } if (player.IsTurnTaken) { plankState = PlankState.CantUse; isPortraitActive = false; } else { plankState = PlankState.InActive; isPortraitActive = true; } if (currentHighlight == null) currentHighlight = player; if (((CombatEngine.HighlightedCombatant == player) && !player.IsTurnTaken) || (CombatEngine.PrimaryTargetedCombatant == player) || (CombatEngine.SecondaryTargetedCombatants.Contains(player))) { plankState = PlankState.Active; if (currentHighlight != player) { // System.Diagnostics.Debug.WriteLine("Switched Player"); } } if (player.IsDeadOrDying) { isCharDead = true; isPortraitActive = false; plankState = PlankState.CantUse; } // Draw Info Slab if (plankState == PlankState.Active) { color = activeNameColor; spriteBatch.Draw(activeCharInfoTexture, position, Color.White); // Draw Brackets if ((CombatEngine.HighlightedCombatant == player) && !player.IsTurnTaken) { spriteBatch.Draw(selectionBracketTexture, position, Color.White); } if (isPortraitActive && (CombatEngine.HighlightedCombatant == player) && (CombatEngine.HighlightedCombatant.CombatAction == null) && !CombatEngine.IsDelaying) { position.X += activeCharInfoTexture.Width / 2; position.X -= combatPopupTexture.Width / 2; position.Y -= combatPopupTexture.Height; InputManager.IsHubActive = true; // Draw Action DrawActionsMenu(position); } } else if (plankState == PlankState.InActive) { color = inActiveNameColor; spriteBatch.Draw(inActiveCharInfoTexture, position, Color.White); } else { color = Color.Black; spriteBatch.Draw(cantUseCharInfoTexture, position, Color.White); } if (isCharDead) { spriteBatch.Draw(deadPortraitTexture, portraitPosition, Color.White); } else { // Draw Player Portrait DrawPortrait(player.Player, portraitPosition, plankState); } // Draw Player Name spriteBatch.DrawString(Fonts.PlayerStatisticsFont, player.Player.Name, namePosition, color); color = Color.Black; // Draw Player Details spriteBatch.DrawString(Fonts.HudDetailFont, "Lvl: " + player.Player.CharacterLevel, levelPosition, color); spriteBatch.DrawString(Fonts.HudDetailFont, "HP: " + player.Statistics.HealthPoints + "/" + player.Player.CharacterStatistics.HealthPoints, detailPosition, color); detailPosition.Y += 30f; spriteBatch.DrawString(Fonts.HudDetailFont, "MP: " + player.Statistics.MagicPoints + "/" + player.Player.CharacterStatistics.MagicPoints, detailPosition, color); }
/// <summary> /// Draws Player Details /// </summary> /// <param name="playerIndex">Index of player details to draw</param> /// <param name="position">Position where to draw</param> private void DrawCombatPlayerDetails(CombatantPlayer player, Vector2 position) { SpriteBatch spriteBatch = screenManager.SpriteBatch; PlankState plankState; bool isPortraitActive = false; bool isCharDead = false; Color color; portraitPosition.X = position.X + 7f * ScaledVector2.ScaleFactor; portraitPosition.Y = position.Y + 7f * ScaledVector2.ScaleFactor; namePosition.X = position.X + 84f * ScaledVector2.ScaleFactor; namePosition.Y = position.Y + 12f * ScaledVector2.ScaleFactor; levelPosition.X = position.X + 84f * ScaledVector2.ScaleFactor; levelPosition.Y = position.Y + 39f * ScaledVector2.ScaleFactor; detailPosition.X = position.X + 25f * ScaledVector2.ScaleFactor; detailPosition.Y = position.Y + 66f * ScaledVector2.ScaleFactor; position.X -= 2 * ScaledVector2.ScaleFactor; position.Y -= 4 * ScaledVector2.ScaleFactor; if (player.IsTurnTaken) { plankState = PlankState.CantUse; isPortraitActive = false; } else { plankState = PlankState.InActive; isPortraitActive = true; } if (((CombatEngine.HighlightedCombatant == player) && !player.IsTurnTaken) || (CombatEngine.PrimaryTargetedCombatant == player) || (CombatEngine.SecondaryTargetedCombatants.Contains(player))) { plankState = PlankState.Active; } if (player.IsDeadOrDying) { isCharDead = true; isPortraitActive = false; plankState = PlankState.CantUse; } // Draw Info Slab if (plankState == PlankState.Active) { color = activeNameColor; spriteBatch.Draw(activeCharInfoTexture, position,null, Color.White,0f, Vector2.Zero, ScaledVector2.DrawFactor, SpriteEffects.None, 0f); // Draw Brackets if ((CombatEngine.HighlightedCombatant == player) && !player.IsTurnTaken) { spriteBatch.Draw(selectionBracketTexture, position,null, Color.White,0f, Vector2.Zero, ScaledVector2.DrawFactor, SpriteEffects.None, 0f); } if (isPortraitActive && (CombatEngine.HighlightedCombatant == player) && (CombatEngine.HighlightedCombatant.CombatAction == null) && !CombatEngine.IsDelaying) { position.X += (activeCharInfoTexture.Width * ScaledVector2.DrawFactor ) / 2; position.X -= (combatPopupTexture.Width * ScaledVector2.DrawFactor) / 2; position.Y -= (combatPopupTexture.Height * ScaledVector2.DrawFactor); // Draw Action DrawActionsMenu(position); } } else if (plankState == PlankState.InActive) { color = inActiveNameColor; spriteBatch.Draw(inActiveCharInfoTexture, position,null, Color.White,0f, Vector2.Zero, ScaledVector2.DrawFactor, SpriteEffects.None, 0f); } else { color = Color.Black; spriteBatch.Draw(cantUseCharInfoTexture, position,null, Color.White,0f, Vector2.Zero, ScaledVector2.DrawFactor, SpriteEffects.None, 0f); } if (isCharDead) { spriteBatch.Draw(deadPortraitTexture, portraitPosition,null, Color.White,0f, Vector2.Zero, ScaledVector2.DrawFactor, SpriteEffects.None, 0f); } else { // Draw Player Portrait DrawPortrait(player.Player, portraitPosition, plankState); } // Draw Player Name spriteBatch.DrawString(Fonts.PlayerStatisticsFont, player.Player.Name, namePosition, color); color = Color.Black; // Draw Player Details spriteBatch.DrawString(Fonts.HudDetailFont, "Lvl: " + player.Player.CharacterLevel, levelPosition, color); spriteBatch.DrawString(Fonts.HudDetailFont, "HP: " + player.Statistics.HealthPoints + "/" + player.Player.CharacterStatistics.HealthPoints, detailPosition, color); detailPosition.Y += 30f * ScaledVector2.ScaleFactor; spriteBatch.DrawString(Fonts.HudDetailFont, "MP: " + player.Statistics.MagicPoints + "/" + player.Player.CharacterStatistics.MagicPoints, detailPosition, color); }
/// <summary> /// Draws Player Details /// </summary> /// <param name="playerIndex">Index of player details to draw</param> /// <param name="position">Position where to draw</param> private void DrawCombatPlayerDetails(CombatantPlayer player, Vector2 position) { SpriteBatch spriteBatch = screenManager.SpriteBatch; PlankState plankState; bool isPortraitActive = false; bool isCharDead = false; Color color; portraitPosition.X = position.X + 7f; portraitPosition.Y = position.Y + 7f; namePosition.X = position.X + 84f; namePosition.Y = position.Y + 12f; levelPosition.X = position.X + 84f; levelPosition.Y = position.Y + 39f; detailPosition.X = position.X + 25f; detailPosition.Y = position.Y + 66f; position.X -= 2; position.Y -= 4; if (player.IsTurnTaken) { plankState = PlankState.CantUse; isPortraitActive = false; } else { plankState = PlankState.InActive; isPortraitActive = true; } if (((CombatEngine.HighlightedCombatant == player) && !player.IsTurnTaken) || (CombatEngine.PrimaryTargetedCombatant == player) || (CombatEngine.SecondaryTargetedCombatants.Contains(player))) { plankState = PlankState.Active; } if (player.IsDeadOrDying) { isCharDead = true; isPortraitActive = false; plankState = PlankState.CantUse; } // Draw Info Slab if (plankState == PlankState.Active) { color = activeNameColor; // Draw Brackets if ((CombatEngine.HighlightedCombatant == player) && !player.IsTurnTaken) { spriteBatch.Draw(selectionBracketTexture, position, Color.White); } if (isPortraitActive && (CombatEngine.HighlightedCombatant == player) && (CombatEngine.HighlightedCombatant.CombatAction == null) && !CombatEngine.IsDelaying) { position.X += activeCharInfoTexture.Width / 2; position.X -= combatPopupTexture.Width / 2; position.Y -= combatPopupTexture.Height; // Draw Action DrawActionsMenu(position); } } else if (plankState == PlankState.InActive) { color = inActiveNameColor; spriteBatch.Draw(inActiveCharInfoTexture, new Rectangle(0, 0, 205, 138), Color.White); } else { color = Color.Black; spriteBatch.Draw(cantUseCharInfoTexture, position, Color.White); } if (isCharDead) { spriteBatch.Draw(deadPortraitTexture, portraitPosition, Color.White); } else { // Draw Player Portrait //(player.Player, portraitPosition, plankState); } }
/// <summary> /// Update the combat engine for this frame. /// </summary> private void UpdateCombatEngine(GameTime gameTime) { // check for the end of combat if (ArePlayersDefeated) { EndCombat(CombatEndingState.Loss); return; } else if (AreMonstersDefeated) { EndCombat(CombatEndingState.Victory); return; } // update the target selections if ((highlightedCombatant != null) && (highlightedCombatant.CombatAction != null)) { SetTargets(highlightedCombatant.CombatAction.Target, highlightedCombatant.CombatAction.AdjacentTargets); } //update active battle timers foreach (CombatantPlayer player in players) { if (player.AC > 5000 && player.readyForQueue) { player.AC = 5000; //add player if hes not already there if (!selectionQueue.Contains(player)) { selectionQueue.Enqueue(player); player.readyForQueue = false; } } else if(!player.IsDeadOrDying) player.AC += gameTime.ElapsedGameTime.Milliseconds; } foreach (CombatantMonster monster in monsters) { if (monster.AC > 4000 && monster.readyForQueue) { monster.AC = 4000; //add player if hes not already there if (!actionQueue.Contains(monster)) { actionQueue.Enqueue(monster); monster.readyForQueue = false; } } else if(!monster.IsDeadOrDying) monster.AC += gameTime.ElapsedGameTime.Milliseconds; } //show action menu if player's turn is ready if (selectionQueue.Count > 0 && !selectionQueueLocked) { if (currentSelector == null) { isPlayersTurn = true; currentSelector = selectionQueue.Peek(); currentSelector.IsTurnTaken = false; BeginPlayerTurn((CombatantPlayer)selectionQueue.Peek()); selectionQueue.Dequeue(); selectionQueueLocked = true; } } //resolve actions bool removeAction = false; //remove dead people in the front of the queue while(actionQueue.Count > 0 && actionQueue.Peek().IsDeadOrDying) actionQueue.Dequeue(); if (actionQueue.Count > 0 ) { //unlock queue after current combatant finishes its action. if(currentCombatant != null) if(currentCombatant.CombatAction == null) actionQueueLocked = false; else if(currentCombatant.CombatAction.Stage == CombatAction.CombatActionStage.NotStarted) actionQueueLocked = false; if (actionQueue.Peek().GetType() == typeof(CombatantPlayer) && !actionQueueLocked) { //execute player action actionQueue.Peek().CombatAction.Start(); currentCombatant = actionQueue.Peek(); removeAction = true; } if (actionQueue.Peek().GetType() == typeof(CombatantMonster) && !actionQueueLocked) { //execute monster action BeginMonsterTurn((CombatantMonster)actionQueue.Peek() ); currentCombatant = actionQueue.Peek(); removeAction = true; } if (removeAction) { actionQueue.Dequeue(); actionQueueLocked = true; } } // update the delay UpdateDelay(gameTime.ElapsedGameTime.Milliseconds); // UpdateDelay might cause combat to end due to a successful escape, // which will set the singleton to null. if (singleton == null) { return; } // update the players foreach (CombatantPlayer player in players) { player.Update(gameTime); } // update the monsters foreach (CombatantMonster monster in monsters) { monster.Update(gameTime); } // check for completion of the highlighted combatant if ((delayType == DelayType.NoDelay) && (highlightedCombatant != null) && highlightedCombatant.IsTurnTaken) { delayType = DelayType.EndCharacterTurn; } // handle any player input HandleInput(); }
/// <summary> /// Handle player input that affects the combat engine. /// </summary> private void HandleInput() { // only accept input during the players' turn // -- exit game, etc. is handled by GameplayScreen if (!IsPlayersTurn || IsPlayersTurnComplete || (highlightedCombatant == null)) { return; } #if DEBUG // cheat key if (InputManager.IsGamePadRightShoulderTriggered() || InputManager.IsKeyTriggered(Keys.W)) { EndCombat(CombatEndingState.Victory); return; } #endif // handle input while choosing an action if (highlightedCombatant.CombatAction != null) { // skip if its turn is over or the action is already going if (highlightedCombatant.IsTurnTaken || (highlightedCombatant.CombatAction.Stage != CombatAction.CombatActionStage.NotStarted)) { return; } // back out of the action if (InputManager.IsActionTriggered(InputManager.Action.Back)) { highlightedCombatant.CombatAction = null; SetTargets(null, 0); return; } // start the action if (InputManager.IsActionTriggered(InputManager.Action.Ok)) { actionQueue.Enqueue(highlightedCombatant); currentSelector = null; highlightedCombatant.IsTurnTaken = true; highlightedCombatant = null; primaryTargetedCombatant = null; secondaryTargetedCombatants.Clear(); isPlayersTurn = false; selectionQueueLocked = false; return; } // go to the next target if (InputManager.IsActionTriggered(InputManager.Action.TargetUp)) { // cycle through monsters or party members if (highlightedCombatant.CombatAction.IsOffensive) { // find the index of the current target int newIndex = monsters.FindIndex( delegate(CombatantMonster monster) { return (primaryTargetedCombatant == monster); }); // find the next living target do { newIndex = (newIndex + 1) % monsters.Count; } while (monsters[newIndex].IsDeadOrDying); // set the new target highlightedCombatant.CombatAction.Target = monsters[newIndex]; } else { // find the index of the current target int newIndex = players.FindIndex( delegate(CombatantPlayer player) { return (primaryTargetedCombatant == player); }); // find the next active, living target do { newIndex = (newIndex + 1) % players.Count; } while (players[newIndex].IsDeadOrDying); // set the new target highlightedCombatant.CombatAction.Target = players[newIndex]; } return; } // go to the previous target else if (InputManager.IsActionTriggered(InputManager.Action.TargetDown)) { // cycle through monsters or party members if (highlightedCombatant.CombatAction.IsOffensive) { // find the index of the current target int newIndex = monsters.FindIndex( delegate(CombatantMonster monster) { return (primaryTargetedCombatant == monster); }); // find the previous active, living target do { newIndex--; while (newIndex < 0) { newIndex += monsters.Count; } } while (monsters[newIndex].IsDeadOrDying); // set the new target highlightedCombatant.CombatAction.Target = monsters[newIndex]; } else { // find the index of the current target int newIndex = players.FindIndex( delegate(CombatantPlayer player) { return (primaryTargetedCombatant == player); }); // find the previous living target do { newIndex--; while (newIndex < 0) { newIndex += players.Count; } } while (players[newIndex].IsDeadOrDying); // set the new target highlightedCombatant.CombatAction.Target = players[newIndex]; } return; } } else // choosing which character will act { // move to the previous living character if (InputManager.IsActionTriggered( InputManager.Action.ActiveCharacterLeft)) { int newHighlightedPlayer = highlightedPlayer; do { newHighlightedPlayer--; while (newHighlightedPlayer < 0) { newHighlightedPlayer += players.Count; } } while (players[newHighlightedPlayer].IsDeadOrDying || players[newHighlightedPlayer].IsTurnTaken); if (newHighlightedPlayer != highlightedPlayer) { highlightedPlayer = newHighlightedPlayer; BeginPlayerTurn(players[highlightedPlayer]); } return; } // move to the next living character else if (InputManager.IsActionTriggered( InputManager.Action.ActiveCharacterRight)) { int newHighlightedPlayer = highlightedPlayer; do { newHighlightedPlayer = (newHighlightedPlayer + 1) % players.Count; } while (players[newHighlightedPlayer].IsDeadOrDying || players[newHighlightedPlayer].IsTurnTaken); if (newHighlightedPlayer != highlightedPlayer) { highlightedPlayer = newHighlightedPlayer; BeginPlayerTurn(players[highlightedPlayer]); } return; } Session.Hud.UpdateActionsMenu(); } }
/// <summary> /// Draws Player Details /// </summary> /// <param name="playerIndex">Index of player details to draw</param> /// <param name="position">Position where to draw</param> private void DrawCombatPlayerDetails(CombatantPlayer player, Vector2 position) { SpriteBatch spriteBatch = screenManager.SpriteBatch; PlankState plankState; bool isPortraitActive = false; bool isCharDead = false; Color color; portraitPosition.X = position.X + 7f * ScaledVector2.ScaleFactor; portraitPosition.Y = position.Y + 7f * ScaledVector2.ScaleFactor; namePosition.X = position.X + 84f * ScaledVector2.ScaleFactor; namePosition.Y = position.Y + 12f * ScaledVector2.ScaleFactor; levelPosition.X = position.X + 84f * ScaledVector2.ScaleFactor; levelPosition.Y = position.Y + 39f * ScaledVector2.ScaleFactor; detailPosition.X = position.X + 25f * ScaledVector2.ScaleFactor; detailPosition.Y = position.Y + 66f * ScaledVector2.ScaleFactor; position.X -= 2 * ScaledVector2.ScaleFactor; position.Y -= 4 * ScaledVector2.ScaleFactor; if (player.IsTurnTaken) { plankState = PlankState.CantUse; isPortraitActive = false; } else { plankState = PlankState.InActive; isPortraitActive = true; } if (((CombatEngine.HighlightedCombatant == player) && !player.IsTurnTaken) || (CombatEngine.PrimaryTargetedCombatant == player) || (CombatEngine.SecondaryTargetedCombatants.Contains(player))) { plankState = PlankState.Active; } if (player.IsDeadOrDying) { isCharDead = true; isPortraitActive = false; plankState = PlankState.CantUse; } // Draw Info Slab if (plankState == PlankState.Active) { color = activeNameColor; spriteBatch.Draw(activeCharInfoTexture, position, null, Color.White, 0f, Vector2.Zero, ScaledVector2.DrawFactor, SpriteEffects.None, 0f); // Draw Brackets if ((CombatEngine.HighlightedCombatant == player) && !player.IsTurnTaken) { spriteBatch.Draw(selectionBracketTexture, position, null, Color.White, 0f, Vector2.Zero, ScaledVector2.DrawFactor, SpriteEffects.None, 0f); } if (isPortraitActive && (CombatEngine.HighlightedCombatant == player) && (CombatEngine.HighlightedCombatant.CombatAction == null) && !CombatEngine.IsDelaying) { position.X += (activeCharInfoTexture.Width * ScaledVector2.DrawFactor) / 2; position.X -= (combatPopupTexture.Width * ScaledVector2.DrawFactor) / 2; position.Y -= (combatPopupTexture.Height * ScaledVector2.DrawFactor); // Draw Action DrawActionsMenu(position); } } else if (plankState == PlankState.InActive) { color = inActiveNameColor; spriteBatch.Draw(inActiveCharInfoTexture, position, null, Color.White, 0f, Vector2.Zero, ScaledVector2.DrawFactor, SpriteEffects.None, 0f); } else { color = Color.Black; spriteBatch.Draw(cantUseCharInfoTexture, position, null, Color.White, 0f, Vector2.Zero, ScaledVector2.DrawFactor, SpriteEffects.None, 0f); } if (isCharDead) { spriteBatch.Draw(deadPortraitTexture, portraitPosition, null, Color.White, 0f, Vector2.Zero, ScaledVector2.DrawFactor, SpriteEffects.None, 0f); } else { // Draw Player Portrait DrawPortrait(player.Player, portraitPosition, plankState); } // Draw Player Name spriteBatch.DrawString(Fonts.PlayerStatisticsFont, player.Player.Name, namePosition, color); color = Color.Black; // Draw Player Details spriteBatch.DrawString(Fonts.HudDetailFont, "Lvl: " + player.Player.CharacterLevel, levelPosition, color); spriteBatch.DrawString(Fonts.HudDetailFont, "HP: " + player.Statistics.HealthPoints + "/" + player.Player.CharacterStatistics.HealthPoints, detailPosition, color); detailPosition.Y += 30f * ScaledVector2.ScaleFactor; spriteBatch.DrawString(Fonts.HudDetailFont, "MP: " + player.Statistics.MagicPoints + "/" + player.Player.CharacterStatistics.MagicPoints, detailPosition, color); }