public static SkillLevelsComponent ApplyStatModifications(StateSpaceComponents spaceComponents, Guid entity, SkillLevelsComponent originalStats) { SkillLevelsComponent newStats = originalStats; //See if the entity has an inventory to check for artifact modifications if (spaceComponents.InventoryComponents.ContainsKey(entity)) { InventoryComponent entityInventory = spaceComponents.InventoryComponents[entity]; //For each artifact in the entity' inventory, look for the statmodificationcomponent, and modify stats accordingly. foreach (Guid id in entityInventory.Artifacts) { Entity inventoryItem = spaceComponents.Entities.Where(x => x.Id == id).FirstOrDefault(); if (inventoryItem != null && (inventoryItem.ComponentFlags & ComponentMasks.Artifact) == ComponentMasks.Artifact) { StatModificationComponent statsMods = spaceComponents.StatModificationComponents[id]; newStats.Accuracy = (newStats.Accuracy + statsMods.AccuracyChange < 0) ? 0 : newStats.Accuracy + statsMods.AccuracyChange; newStats.Defense = (newStats.Defense + statsMods.DefenseChange < 0) ? 0 : newStats.Defense + statsMods.DefenseChange; newStats.DieNumber = (newStats.DieNumber + statsMods.DieNumberChange < 1) ? 1 : newStats.DieNumber + statsMods.DieNumberChange; newStats.Health = (newStats.Health + statsMods.HealthChange < 0) ? 0 : newStats.Health + statsMods.HealthChange; newStats.MaximumDamage = (newStats.MaximumDamage + statsMods.MaximumDamageChange < 1) ? 1 : newStats.MaximumDamage + statsMods.MaximumDamageChange; newStats.MinimumDamage = (newStats.MinimumDamage + statsMods.MinimumDamageChange < 1) ? 1 : newStats.MinimumDamage + statsMods.MinimumDamageChange; } } } return(newStats); }
public static void RetainPlayerStatistics(StateComponents stateComponents, StateSpaceComponents spaceComponents) { Guid id = spaceComponents.Entities.Where(x => (x.ComponentFlags & Component.COMPONENT_PLAYER) == Component.COMPONENT_PLAYER).Select(x => x.Id).First(); SkillLevelsComponent skills = spaceComponents.SkillLevelsComponents[id]; GameplayInfoComponent gameInfo = spaceComponents.GameplayInfoComponent; stateComponents.GameplayInfo = gameInfo; stateComponents.PlayerSkillLevels = skills; }
public static int CalculateMeleeDamage(StateSpaceComponents spaceComponents, SkillLevelsComponent attackingStats, Guid attacker) { attackingStats = InventorySystem.ApplyStatModifications(spaceComponents, attacker, attackingStats); int damage = 0; for (int i = 0; i < attackingStats.DieNumber; i++) { damage += spaceComponents.random.Next((int)(attackingStats.MinimumDamage / attackingStats.DieNumber), (int)(attackingStats.MaximumDamage / attackingStats.DieNumber) + 1); } return(damage); }
public static void AICheckFleeing(StateSpaceComponents spaceComponents) { if (spaceComponents.PlayerComponent.PlayerTookTurn) { foreach (Guid id in spaceComponents.Entities.Where(x => (x.ComponentFlags & ComponentMasks.CombatReadyAI) == ComponentMasks.CombatReadyAI).Select(x => x.Id)) { AIState state = spaceComponents.AIStateComponents[id]; if (state.State == AIStates.STATE_ATTACKING) { AIFlee flee = spaceComponents.AIFleeComponents[id]; if (flee.DoesFlee) { AIFieldOfView FOV = spaceComponents.AIFieldOfViewComponents[id]; SkillLevelsComponent skills = spaceComponents.SkillLevelsComponents[id]; AIAlignment alignment = spaceComponents.AIAlignmentComponents[id]; double healthPercent = ((double)skills.CurrentHealth / (double)skills.Health) * 100; if (healthPercent <= flee.FleeAtHealthPercent) { state.State = AIStates.STATE_FLEEING; FOV.Color = FOVColors.Fleeing; spaceComponents.AIStateComponents[id] = state; spaceComponents.AIFieldOfViewComponents[id] = FOV; spaceComponents.GameMessageComponent.GameMessages.Add(new Tuple <Color, string>(Colors.Messages.StatusChange, string.Format("[TURN " + spaceComponents.GameplayInfoComponent.StepsTaken + "] " + Messages.Flee[spaceComponents.random.Next(0, Messages.Flee.Count())], spaceComponents.NameComponents[id].Name))); } } } else if (state.State == AIStates.STATE_FLEEING) { AIFlee flee = spaceComponents.AIFleeComponents[id]; AIFieldOfView FOV = spaceComponents.AIFieldOfViewComponents[id]; SkillLevelsComponent skills = spaceComponents.SkillLevelsComponents[id]; double healthPercent = ((double)skills.CurrentHealth / (double)skills.Health) * 100; AIAlignment alignment = spaceComponents.AIAlignmentComponents[id]; if (healthPercent >= flee.FleeUntilHealthPercent) { state.State = AIStates.STATE_ATTACKING; spaceComponents.AIStateComponents[id] = state; FOV.Color = FOVColors.Fleeing; spaceComponents.AIStateComponents[id] = state; spaceComponents.AIFieldOfViewComponents[id] = FOV; spaceComponents.GameMessageComponent.GameMessages.Add(new Tuple <Color, string>(Colors.Messages.StatusChange, string.Format("[TURN " + spaceComponents.GameplayInfoComponent.StepsTaken + "] " + Messages.Flee[spaceComponents.random.Next(0, Messages.Flee.Count())], spaceComponents.NameComponents[id].Name))); } } } } }
public static void RegenerateHealth(StateSpaceComponents spaceComponents) { if (spaceComponents.PlayerComponent.PlayerTookTurn) { foreach (Guid id in spaceComponents.Entities.Where(x => (x.ComponentFlags & ComponentMasks.HealthRegen) == ComponentMasks.HealthRegen).Select(x => x.Id)) { HealthRegenerationComponent healthRegen = spaceComponents.HealthRegenerationComponents[id]; healthRegen.TurnsSinceLastHeal += 1; if (healthRegen.TurnsSinceLastHeal >= healthRegen.RegenerateTurnRate) { SkillLevelsComponent skills = spaceComponents.SkillLevelsComponents[id]; skills.CurrentHealth += healthRegen.HealthRegain; skills.CurrentHealth = (skills.CurrentHealth >= skills.Health) ? skills.Health : skills.CurrentHealth; spaceComponents.SkillLevelsComponents[id] = skills; } spaceComponents.HealthRegenerationComponents[id] = healthRegen; } } }
public PlayingState(IStateSpace space, Camera camera, ContentManager content, GraphicsDeviceManager graphics, IState prevState = null, MouseState mouseState = new MouseState(), GamePadState gamePadState = new GamePadState(), KeyboardState keyboardState = new KeyboardState(), DungeonInfo saveInfo = null) { this.Content = new ContentManager(content.ServiceProvider, "Content"); Graphics = graphics; PrevMouseState = mouseState; PrevGamepadState = gamePadState; PrevKeyboardState = keyboardState; SkillLevelsComponent newPlayerStats = new SkillLevelsComponent() { CurrentHealth = 100, Health = 100, Accuracy = 100, Defense = 10, Wealth = 0, MinimumDamage = 1, MaximumDamage = 3, DieNumber = 1 }; StateComponents = saveInfo == null ? new StateComponents() { PlayerSkillLevels = newPlayerStats } : saveInfo.stateComponents; SetStateSpace(space, camera, saveInfo == null); previousState = prevState; }
public static void TryPickupItems(StateSpaceComponents spaceComponents, DungeonTile[,] dungeongrid) { IEnumerable <Guid> entitiesThatCollided = spaceComponents.GlobalCollisionComponent.EntitiesThatCollided.Distinct(); foreach (Guid collidingEntity in entitiesThatCollided) { Entity colliding = spaceComponents.Entities.Where(x => x.Id == collidingEntity).FirstOrDefault(); //If the colliding entity has an inventory and messages, place the item inside the inventory. if (colliding != null && (colliding.ComponentFlags & ComponentMasks.InventoryPickup) == ComponentMasks.InventoryPickup) { CollisionComponent collidingEntityCollisions = spaceComponents.CollisionComponents[collidingEntity]; InventoryComponent collidingEntityInventory = spaceComponents.InventoryComponents[collidingEntity]; NameComponent collidingEntityName = spaceComponents.NameComponents[collidingEntity]; PositionComponent collidingEntityPosition = spaceComponents.PositionComponents[collidingEntity]; EntityMessageComponent collidingEntityMessages = spaceComponents.EntityMessageComponents[collidingEntity]; foreach (Guid collidedEntity in collidingEntityCollisions.CollidedObjects) { //Check to see if the collidedEntity is a pickup item, if it is, try to place it in the inventory if it fits. Entity collided = spaceComponents.Entities.Where(x => x.Id == collidedEntity).FirstOrDefault(); //If the collideditem is a pickup item, handle it based on pickup type. if (collided != null && (collided.ComponentFlags & ComponentMasks.PickupItem) == ComponentMasks.PickupItem) { PickupComponent itemPickup = spaceComponents.PickupComponents[collidedEntity]; ValueComponent itemValue = spaceComponents.ValueComponents[collidedEntity]; NameComponent itemName = spaceComponents.NameComponents[collidedEntity]; switch (itemPickup.PickupType) { case ItemType.GOLD: if (spaceComponents.SkillLevelsComponents.ContainsKey(collidingEntity)) { SkillLevelsComponent skills = spaceComponents.SkillLevelsComponents[collidingEntity]; skills.Wealth += itemValue.Gold; spaceComponents.SkillLevelsComponents[collidingEntity] = skills; if (dungeongrid[(int)collidingEntityPosition.Position.X, (int)collidingEntityPosition.Position.Y].InRange) { spaceComponents.GameMessageComponent.GameMessages.Add(new Tuple <Color, string>(Colors.Messages.Special, string.Format("[TURN " + spaceComponents.GameplayInfoComponent.StepsTaken + "] " + "{0} picked up {1} gold.", collidingEntityName.Name, itemValue.Gold))); } spaceComponents.EntitiesToDelete.Add(collidedEntity); } break; case ItemType.CONSUMABLE: //If the entity has room in their inventory, place the item in it if (collidingEntityInventory.Consumables.Count < collidingEntityInventory.MaxConsumables) { //Remove the position component flag and add the guid to the inventory of the entity collided.ComponentFlags &= ~Component.COMPONENT_POSITION; collidingEntityInventory.Consumables.Add(collided.Id); if (dungeongrid[(int)collidingEntityPosition.Position.X, (int)collidingEntityPosition.Position.Y].InRange && collidingEntityMessages.PickupItemMessages.Length > 0) { spaceComponents.GameMessageComponent.GameMessages.Add(new Tuple <Color, string>(Colors.Messages.LootPickup, string.Format("[TURN " + spaceComponents.GameplayInfoComponent.StepsTaken + "] " + collidingEntityMessages.PickupItemMessages[spaceComponents.random.Next(0, collidingEntityMessages.PickupItemMessages.Length)], collidingEntityName.Name, itemName.Name))); } } //If it can't fit in, and the entity has a message for the situation, display it. else if (spaceComponents.EntityMessageComponents[collidingEntity].ConsumablesFullMessages != null && spaceComponents.EntityMessageComponents[collidingEntity].ConsumablesFullMessages.Length > 0) { spaceComponents.GameMessageComponent.GameMessages.Add(new Tuple <Color, string>(Colors.Messages.Bad, "[TURN " + spaceComponents.GameplayInfoComponent.StepsTaken + "] " + spaceComponents.EntityMessageComponents[collidingEntity].ConsumablesFullMessages[spaceComponents.random.Next(0, spaceComponents.EntityMessageComponents[collidingEntity].ConsumablesFullMessages.Length)])); } break; case ItemType.ARTIFACT: //If the entity has room in their inventory, place the item in it if (collidingEntityInventory.Artifacts.Count < collidingEntityInventory.MaxArtifacts) { //Remove the position component flag and add the guid to the inventory of the entity collided.ComponentFlags &= ~Component.COMPONENT_POSITION; collidingEntityInventory.Artifacts.Add(collided.Id); if (dungeongrid[(int)collidingEntityPosition.Position.X, (int)collidingEntityPosition.Position.Y].InRange && collidingEntityMessages.PickupItemMessages.Length > 0) { spaceComponents.GameMessageComponent.GameMessages.Add(new Tuple <Color, string>(Colors.Messages.LootPickup, string.Format("[TURN " + spaceComponents.GameplayInfoComponent.StepsTaken + "] " + collidingEntityMessages.PickupItemMessages[spaceComponents.random.Next(0, collidingEntityMessages.PickupItemMessages.Length)], collidingEntityName.Name, itemName.Name))); } } //If it can't fit in, and the entity has a message for the situation, display it. else if (spaceComponents.EntityMessageComponents[collidingEntity].ArtifactsFullMessages != null && spaceComponents.EntityMessageComponents[collidingEntity].ArtifactsFullMessages.Length > 0) { spaceComponents.GameMessageComponent.GameMessages.Add(new Tuple <Color, string>(Colors.Messages.Bad, "[TURN " + spaceComponents.GameplayInfoComponent.StepsTaken + "] " + spaceComponents.EntityMessageComponents[collidingEntity].ArtifactsFullMessages[spaceComponents.random.Next(0, spaceComponents.EntityMessageComponents[collidingEntity].ArtifactsFullMessages.Length)])); } break; case ItemType.DOWNSTAIRS: //Tell the game to go to the next level if ((spaceComponents.Entities.Where(x => x.Id == collidingEntity).FirstOrDefault().ComponentFlags & Component.COMPONENT_PLAYER) == Component.COMPONENT_PLAYER) { PlayerComponent player = spaceComponents.PlayerComponent; player.GoToNextFloor = true; spaceComponents.PlayerComponent = player; } break; } } } } } }
public static void ShowInventoryMenu(StateSpaceComponents spaceComponents, SpriteBatch spriteBatch, Camera camera, SpriteFont messageFont, SpriteFont optionFont, Texture2D UI) { Entity player = spaceComponents.Entities.Where(x => (x.ComponentFlags & ComponentMasks.Player) == ComponentMasks.Player).FirstOrDefault(); if (player != null) { int messageSpacing = (int)messageFont.MeasureString("g").Y + 1; int messageNumberLeft = 0; int messageNumberMiddle = 0; int messageNumberRight = 0; int panelWidth = (int)(camera.FullViewport.Width / 3); InventoryMenuComponent menu = spaceComponents.InventoryMenuComponent; InventoryComponent playerInvo = spaceComponents.InventoryComponents[player.Id]; SkillLevelsComponent playerSkills = spaceComponents.SkillLevelsComponents[player.Id]; //Draw background spriteBatch.Draw(UI, camera.FullViewport.Bounds, Color.Black * .7f); //Draw Header Vector2 headerSize = optionFont.MeasureString(Messages.InventoryHeader); int beginningHeight = (int)headerSize.Y + messageSpacing * 2; spriteBatch.Draw(UI, new Rectangle(0, 0, camera.FullViewport.Width, beginningHeight), Color.DarkViolet * .3f); spriteBatch.DrawString(optionFont, Messages.InventoryHeader, new Vector2((int)(camera.FullViewport.Width / 2) - (int)(headerSize.X / 2), messageSpacing), Color.CornflowerBlue); beginningHeight += messageSpacing; //Draw columns //Left spriteBatch.Draw(UI, new Rectangle(0, beginningHeight, panelWidth - messageSpacing, camera.FullViewport.Height), Color.DarkBlue * .25f); //Middle spriteBatch.Draw(UI, new Rectangle(messageSpacing + panelWidth, beginningHeight, panelWidth - messageSpacing, camera.FullViewport.Height), Color.DarkBlue * .25f); //Right spriteBatch.Draw(UI, new Rectangle(messageSpacing * 2 + panelWidth * 2, beginningHeight, panelWidth - messageSpacing, camera.FullViewport.Height), Color.DarkBlue * .25f); //Draw item selection panel spriteBatch.DrawString(messageFont, string.Format("Wealth: {0}", playerSkills.Wealth), new Vector2(messageSpacing, beginningHeight), Colors.Messages.Special); messageNumberLeft += 2; spriteBatch.DrawString(messageFont, string.Format(Messages.InventoryArtifacts + " ({0}/{1})", playerInvo.Artifacts.Count, playerInvo.MaxArtifacts), new Vector2(messageSpacing, beginningHeight + (messageSpacing * messageNumberLeft)), Color.CornflowerBlue); messageNumberLeft += 1; foreach (Guid item in playerInvo.Artifacts) { Color color = (menu.SelectedItem == item) ? Colors.Messages.LootPickup : Color.NavajoWhite; string prepend = (menu.SelectedItem == item) ? "> " : string.Empty; spriteBatch.DrawString(messageFont, prepend + spaceComponents.NameComponents[item].Name, new Vector2(messageSpacing, (messageSpacing * messageNumberLeft) + beginningHeight), color); messageNumberLeft += 1; } spriteBatch.DrawString(messageFont, string.Format(Messages.InventoryConsumables + " ({0}/{1})", playerInvo.Consumables.Count, playerInvo.MaxConsumables), new Vector2(messageSpacing, (messageSpacing * 3) + (messageSpacing * messageNumberLeft) + beginningHeight), Color.CornflowerBlue); messageNumberLeft += 1; foreach (Guid item in playerInvo.Consumables) { Color color = (menu.SelectedItem == item) ? Colors.Messages.LootPickup : Color.NavajoWhite; string prepend = (menu.SelectedItem == item) ? "> " : string.Empty; spriteBatch.DrawString(messageFont, prepend + spaceComponents.NameComponents[item].Name, new Vector2(messageSpacing, (messageSpacing * 3) + (messageSpacing * messageNumberLeft) + beginningHeight), color); messageNumberLeft += 1; } messageNumberLeft += 2; //Gather item information panels if (menu.SelectedItem != Guid.Empty) { PickupComponent itemInfo = spaceComponents.PickupComponents[menu.SelectedItem]; NameComponent itemName = spaceComponents.NameComponents[menu.SelectedItem]; ValueComponent itemValue = spaceComponents.ValueComponents[menu.SelectedItem]; List <Tuple <Color, string> > centerMessages = new List <Tuple <Color, string> >(); List <Tuple <Color, string> > rightMessages = new List <Tuple <Color, string> >(); //Get name, description, and value rightMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, itemName.Name)); rightMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, itemName.Description)); centerMessages.Add(new Tuple <Color, string>(Colors.Messages.Special, string.Format("This item can be scrapped for {0} gold.", itemValue.Gold))); switch (itemInfo.PickupType) { case ItemType.ARTIFACT: //Collect item use stats for right panel //Artifact Stats ArtifactStatsComponent artifactStats = spaceComponents.ArtifactStatsComponents[menu.SelectedItem]; rightMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); rightMessages.Add(new Tuple <Color, string>(Colors.Messages.Special, string.Format("Upgrade Level: {0}", artifactStats.UpgradeLevel))); rightMessages.Add(new Tuple <Color, string>(Colors.Messages.Special, string.Format("Depth found: {0}", artifactStats.FloorFound))); rightMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); rightMessages.Add(new Tuple <Color, string>(Colors.Messages.Good, "STATISTICS WHILE EQUIPPED:")); rightMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("Kills: {0}", artifactStats.KillsWith))); rightMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("Maximum hit combo: {0}", artifactStats.MaximumComboWith))); rightMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("Damage given: {0}", artifactStats.DamageGivenWith))); rightMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("Damage taken: {0}", artifactStats.DamageTakenWith))); rightMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("Times dodged: {0}", artifactStats.DodgesWith))); rightMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("Times missed: {0}", artifactStats.MissesWith))); //Draw commands for artifact on the left panel spriteBatch.DrawString(messageFont, "Commands: ", new Vector2(messageSpacing, (messageSpacing * 3) + (messageSpacing * messageNumberLeft++) + beginningHeight), Colors.Messages.Normal); spriteBatch.DrawString(messageFont, Messages.Upgrade, new Vector2(messageSpacing, (messageSpacing * 3) + (messageSpacing * messageNumberLeft++) + beginningHeight), Colors.Messages.Normal); spriteBatch.DrawString(messageFont, Messages.Scrap, new Vector2(messageSpacing, (messageSpacing * 3) + (messageSpacing * messageNumberLeft++) + beginningHeight), Colors.Messages.Normal); spriteBatch.DrawString(messageFont, Messages.Drop, new Vector2(messageSpacing, (messageSpacing * 3) + (messageSpacing * messageNumberLeft++) + beginningHeight), Colors.Messages.Normal); //Collect info for middle panel StatModificationComponent stats = spaceComponents.StatModificationComponents[menu.SelectedItem]; centerMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); centerMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, "This artifact affects the following stats: ")); if (stats.AccuracyChange != 0) { string sign = stats.AccuracyChange > 0 ? "+" : string.Empty; Color color = stats.AccuracyChange > 0 ? Colors.Messages.Good : Colors.Messages.Bad; centerMessages.Add(new Tuple <Color, string>(color, string.Format("Accuracy {0}{1}", sign, stats.AccuracyChange))); } if (stats.DefenseChange != 0) { string sign = stats.DefenseChange > 0 ? "+" : string.Empty; Color color = stats.DefenseChange > 0 ? Colors.Messages.Good : Colors.Messages.Bad; centerMessages.Add(new Tuple <Color, string>(color, string.Format("Defense {0}{1}", sign, stats.DefenseChange))); } if (stats.HealthChange != 0) { string sign = stats.HealthChange > 0 ? "+" : string.Empty; Color color = stats.HealthChange > 0 ? Colors.Messages.Good : Colors.Messages.Bad; centerMessages.Add(new Tuple <Color, string>(color, string.Format("Maximum Health {0}{1}", sign, stats.HealthChange))); } if (stats.DieNumberChange != 0) { string sign = stats.DieNumberChange > 0 ? "+" : string.Empty; Color color = stats.DieNumberChange > 0 ? Colors.Messages.Good : Colors.Messages.Bad; centerMessages.Add(new Tuple <Color, string>(color, string.Format("Dice Number on Attack {0}{1}", sign, stats.DieNumberChange))); } if (stats.MinimumDamageChange != 0) { string sign = stats.MinimumDamageChange > 0 ? "+" : string.Empty; Color color = stats.MinimumDamageChange > 0 ? Colors.Messages.Good : Colors.Messages.Bad; centerMessages.Add(new Tuple <Color, string>(color, string.Format("Minimum Damage {0}{1}", sign, stats.MinimumDamageChange))); } if (stats.MaximumDamageChange != 0) { string sign = stats.MaximumDamageChange > 0 ? "+" : string.Empty; Color color = stats.MaximumDamageChange > 0 ? Colors.Messages.Good : Colors.Messages.Bad; centerMessages.Add(new Tuple <Color, string>(color, string.Format("Maximum Damage {0}{1}", sign, stats.MaximumDamageChange))); } //PLACEHOLDER centerMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); centerMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, "This artifact has the following effects: ")); centerMessages.Add(new Tuple <Color, string>(Colors.Messages.Good, "Passive 1: Kills with this item equipped generate 100 gold.")); centerMessages.Add(new Tuple <Color, string>(Colors.Messages.Bad, "Passive 2: Enemies will not flee (LOCKED)")); centerMessages.Add(new Tuple <Color, string>(Colors.Messages.Bad, "Passive 3: Tiles stepped on turn to lava for 5 turns (LOCKED)")); centerMessages.Add(new Tuple <Color, string>(Colors.Messages.Bad, "Bonus: ??? (Kill 40 more enemies with this item to unlock)")); break; case ItemType.CONSUMABLE: //Draw command info on left panel spriteBatch.DrawString(messageFont, "Commands: ", new Vector2(messageSpacing, (messageSpacing * 3) + (messageSpacing * messageNumberLeft++) + beginningHeight), Colors.Messages.Normal); spriteBatch.DrawString(messageFont, Messages.Scrap, new Vector2(messageSpacing, (messageSpacing * 3) + (messageSpacing * messageNumberLeft++) + beginningHeight), Colors.Messages.Normal); spriteBatch.DrawString(messageFont, Messages.Drop, new Vector2(messageSpacing, (messageSpacing * 3) + (messageSpacing * messageNumberLeft++) + beginningHeight), Colors.Messages.Normal); //Collect info for middle panel centerMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); ItemFunctionsComponent consumableInfo = spaceComponents.ItemFunctionsComponents[menu.SelectedItem]; centerMessages.Add(new Tuple <Color, string>(Colors.Messages.Good, string.Format("This item has {0} uses left.", consumableInfo.Uses))); if (consumableInfo.Uses > 1) { centerMessages.Add(new Tuple <Color, string>(Colors.Messages.Bad, string.Format("This item loses {0} value each use.", consumableInfo.CostToUse))); } if (consumableInfo.Ranged) { centerMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("This item is cast at a range."))); } else { centerMessages.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("This item is used where you stand."))); } break; } //Print out all the info foreach (Tuple <Color, string> message in centerMessages) { if (string.IsNullOrEmpty(message.Item2)) { continue; } string text = MessageDisplaySystem.WordWrap(messageFont, message.Item2, panelWidth - 30 - DevConstants.Grid.TileSpriteSize); float textHeight = messageFont.MeasureString(message.Item2).Y; spriteBatch.DrawString(messageFont, text, new Vector2(messageSpacing * 2 + panelWidth, (int)beginningHeight + (int)textHeight + 10 + (messageNumberMiddle * messageSpacing)), message.Item1); messageNumberMiddle += Regex.Matches(text, System.Environment.NewLine).Count; messageNumberMiddle += 1; } foreach (Tuple <Color, string> message in rightMessages) { if (string.IsNullOrEmpty(message.Item2)) { continue; } string text = MessageDisplaySystem.WordWrap(messageFont, message.Item2, panelWidth - 30 - DevConstants.Grid.TileSpriteSize); float textHeight = messageFont.MeasureString(message.Item2).Y; spriteBatch.DrawString(messageFont, text, new Vector2(messageSpacing * 3 + panelWidth * 2, (int)beginningHeight + (int)textHeight + 10 + (messageNumberRight * messageSpacing)), message.Item1); if (text != System.Environment.NewLine) { messageNumberRight += Regex.Matches(text, System.Environment.NewLine).Count; } messageNumberRight += 1; } } } }
public static void DropWholeInventory(StateSpaceComponents spaceComponents, Guid droppingEntity, Vector2 entityPos) { Entity entity = spaceComponents.Entities.Where(x => x.Id == droppingEntity).FirstOrDefault(); if (entity != null && (entity.ComponentFlags & Component.COMPONENT_INVENTORY) == Component.COMPONENT_INVENTORY) { InventoryComponent invo = spaceComponents.InventoryComponents[entity.Id]; foreach (Guid artifact in invo.Artifacts) { Entity item = spaceComponents.Entities.Where(x => x.Id == artifact).FirstOrDefault(); if (item != null) { item.ComponentFlags |= Component.COMPONENT_POSITION; spaceComponents.PositionComponents[item.Id] = new PositionComponent() { Position = entityPos }; invo.Artifacts.Remove(item.Id); } } foreach (Guid consumable in invo.Consumables) { Entity item = spaceComponents.Entities.Where(x => x.Id == consumable).FirstOrDefault(); if (item != null) { item.ComponentFlags |= Component.COMPONENT_POSITION; spaceComponents.PositionComponents[item.Id] = new PositionComponent() { Position = entityPos }; invo.Consumables.Remove(item.Id); } } if ((entity.ComponentFlags & Component.COMPONENT_SKILL_LEVELS) == Component.COMPONENT_SKILL_LEVELS) { SkillLevelsComponent skills = spaceComponents.SkillLevelsComponents[entity.Id]; if (skills.Wealth > 0) { spaceComponents.DelayedActions.Add(new Action(() => { Guid id = spaceComponents.CreateEntity(); spaceComponents.Entities.Where(x => x.Id == id).First().ComponentFlags = ComponentMasks.Drawable | ComponentMasks.GlowingOutline | ComponentMasks.PickupItem; spaceComponents.DisplayComponents[id] = new DisplayComponent() { AlwaysDraw = false, Color = Colors.Messages.Special, Opacity = 1f, Origin = Vector2.Zero, Rotation = 0f, Scale = 1f, SpriteEffect = SpriteEffects.None, SpriteSource = new Rectangle(0 * DevConstants.Grid.CellSize, 0 * DevConstants.Grid.CellSize, DevConstants.Grid.CellSize, DevConstants.Grid.CellSize), Symbol = "$", SymbolColor = Color.White }; Vector2 position = entityPos; spaceComponents.PositionComponents[id] = new PositionComponent() { Position = position }; spaceComponents.OutlineComponents[id] = new OutlineComponent() { Color = Color.Purple, Opacity = 1f }; spaceComponents.SecondaryOutlineComponents[id] = new SecondaryOutlineComponent() { AlternateColor = Color.LightBlue, Seconds = 0f, SwitchAtSeconds = .75f }; spaceComponents.PickupComponents[id] = new PickupComponent() { PickupType = ItemType.GOLD }; spaceComponents.ValueComponents[id] = new ValueComponent() { Gold = skills.Wealth }; spaceComponents.NameComponents[id] = new NameComponent() { Name = "Gold", Description = "Some people try and use fancy names for this mass of wealth. Credits, Stardust, Gil... it buys shelter and women all the same." }; spaceComponents.CollisionComponents[id] = new CollisionComponent() { CollidedObjects = new List <Guid>(), Solid = false }; })); } } } }
public static bool HandleInventoryInput(StateSpaceComponents spaceComponents, GameTime gameTime, KeyboardState prevKey, KeyboardState key) { bool keepInventory = true; Entity player = spaceComponents.Entities.Where(x => (x.ComponentFlags & ComponentMasks.Player) == ComponentMasks.Player).FirstOrDefault(); if (player != null) { InventoryMenuComponent menu = spaceComponents.InventoryMenuComponent; InventoryComponent playerInventory = spaceComponents.InventoryComponents[player.Id]; //Construct array of all inventory items List <Guid> items = new List <Guid>(); items.AddRange(playerInventory.Artifacts); items.AddRange(playerInventory.Consumables); int itemSelection = items.IndexOf(menu.SelectedItem); if (itemSelection < 0) { itemSelection = 0; } //Item selection //If nothing is selected, select the first item if ((menu.SelectedItem == Guid.Empty && items.Count > 0) || (items.Count > 0 && !items.Contains(menu.SelectedItem))) { menu.SelectedItem = items[itemSelection]; } if (key.IsKeyDown(Keys.Down) && prevKey.IsKeyUp(Keys.Down)) { itemSelection += 1; if (itemSelection >= items.Count) { itemSelection = 0; } } else if (key.IsKeyDown(Keys.Up) && prevKey.IsKeyUp(Keys.Up)) { itemSelection -= 1; if (itemSelection < 0) { itemSelection = items.Count - 1; } } else if (key.IsKeyDown(Keys.D) && prevKey.IsKeyUp(Keys.D)) { //Drop the selected item. PositionComponent playerPos = spaceComponents.PositionComponents[player.Id]; Entity item = spaceComponents.Entities.Where(x => x.Id == items[itemSelection]).FirstOrDefault(); if (item != null) { item.ComponentFlags |= Component.COMPONENT_POSITION; spaceComponents.PositionComponents[item.Id] = playerPos; playerInventory.Artifacts.Remove(item.Id); playerInventory.Consumables.Remove(item.Id); itemSelection = 0; items.Remove(item.Id); } } else if (key.IsKeyDown(Keys.S) && prevKey.IsKeyUp(Keys.S)) { //Scrap the selected item Entity item = spaceComponents.Entities.Where(x => x.Id == items[itemSelection]).FirstOrDefault(); if (item != null) { SkillLevelsComponent playerSkills = spaceComponents.SkillLevelsComponents[player.Id]; ValueComponent itemValue = spaceComponents.ValueComponents[item.Id]; playerSkills.Wealth += itemValue.Gold; playerInventory.Artifacts.Remove(item.Id); playerInventory.Consumables.Remove(item.Id); spaceComponents.EntitiesToDelete.Add(item.Id); spaceComponents.SkillLevelsComponents[player.Id] = playerSkills; itemSelection = 0; items.Remove(item.Id); } } //Set new selections if (items.Count > 0) { menu.SelectedItem = items[itemSelection]; spaceComponents.InventoryMenuComponent = menu; } else { menu.SelectedItem = Guid.Empty; spaceComponents.InventoryMenuComponent = menu; } } return(keepInventory); }
public static void ApplyBurnDamage(StateSpaceComponents spaceComponents, DungeonTile[,] dungeonGrid) { if (spaceComponents.PlayerComponent.PlayerTookTurn) { Entity player = spaceComponents.Entities.Where(z => (z.ComponentFlags & Component.COMPONENT_PLAYER) == Component.COMPONENT_PLAYER).FirstOrDefault(); foreach (Guid id in spaceComponents.Entities.Where(x => (x.ComponentFlags & ComponentMasks.BurningStatus) == ComponentMasks.BurningStatus).Select(x => x.Id)) { bool isPlayer = player.Id == id; bool extinguished = false; //If the entity is in water, extinguish the burning effect instead. if (spaceComponents.PositionComponents.ContainsKey(id)) { PositionComponent pos = spaceComponents.PositionComponents[id]; if (dungeonGrid[(int)pos.Position.X, (int)pos.Position.Y].Type == TileType.TILE_WATER) { spaceComponents.Entities.Where(x => x.Id == id).First().ComponentFlags &= ~Component.COMPONENT_BURNING; spaceComponents.DelayedActions.Add(new Action(() => { spaceComponents.BurningComponents.Remove(id); })); if (isPlayer) { spaceComponents.GameMessageComponent.GameMessages.Add(new Tuple <Microsoft.Xna.Framework.Color, string>(Colors.Messages.StatusChange, string.Format("[TURN " + spaceComponents.GameplayInfoComponent.StepsTaken + "] " + "You extinguish yourself in the water."))); } extinguished = true; } } if (!extinguished && spaceComponents.BurningComponents.ContainsKey(id)) { BurningComponent burning = spaceComponents.BurningComponents[id]; burning.TurnsLeft -= 1; SkillLevelsComponent skills = spaceComponents.SkillLevelsComponents[id]; int damage = spaceComponents.random.Next(burning.MinDamage, burning.MaxDamage + 1); skills.CurrentHealth -= damage; spaceComponents.SkillLevelsComponents[id] = skills; spaceComponents.BurningComponents[id] = burning; //Handle Death if (skills.CurrentHealth <= 0) { Entity deadEntity = spaceComponents.Entities.Where(x => x.Id == id).FirstOrDefault(); if (deadEntity != null) { InventorySystem.DropWholeInventory(spaceComponents, deadEntity.Id, spaceComponents.PositionComponents[deadEntity.Id].Position); deadEntity.ComponentFlags &= ~Component.COMPONENT_POSITION; } spaceComponents.EntitiesToDelete.Add(id); if (isPlayer) { //SCORE RECORD spaceComponents.GameMessageComponent.GameMessages.Add(new Tuple <Microsoft.Xna.Framework.Color, string>(Colors.Messages.Special, string.Format("[TURN " + spaceComponents.GameplayInfoComponent.StepsTaken + "] " + Messages.Deaths.FirePlayer, spaceComponents.NameComponents[id].Name))); } else { spaceComponents.GameMessageComponent.GameMessages.Add(new Tuple <Microsoft.Xna.Framework.Color, string>(Colors.Messages.Special, string.Format("[TURN " + spaceComponents.GameplayInfoComponent.StepsTaken + "] " + Messages.Deaths.Fire, spaceComponents.NameComponents[id].Name))); GameplayInfoComponent gameInfo = spaceComponents.GameplayInfoComponent; gameInfo.Kills += 1; spaceComponents.GameplayInfoComponent = gameInfo; } } //Handle Burning running out if (burning.TurnsLeft <= 0) { spaceComponents.Entities.Where(x => x.Id == id).First().ComponentFlags &= ~Component.COMPONENT_BURNING; spaceComponents.DelayedActions.Add(new Action(() => { spaceComponents.BurningComponents.Remove(id); })); } } } } }
public static void PrintObserver(StateSpaceComponents spaceComponents, SpriteFont font, SpriteBatch spriteBatch, DungeonTile[,] dungeonGrid, Camera camera, Texture2D UITexture) { ObserverComponent observer = spaceComponents.ObserverComponent; Entity observerInfo = spaceComponents.Entities.Where(x => (x.ComponentFlags & ComponentMasks.Observer) == ComponentMasks.Observer).FirstOrDefault(); if (observerInfo != null) { //Find out where the observer is PositionComponent observerPosition = spaceComponents.PositionComponents[observerInfo.Id]; //Obtain the list of entities from the observer component List <Entity> observedItems = new List <Entity>(); foreach (Guid id in observer.Observed) { Entity entity = spaceComponents.Entities.Where(x => x.Id == id).FirstOrDefault(); if (entity != null) { observedItems.Add(entity); } } //Set the initial variables int messageSpacing = (int)font.MeasureString("g").Y + 1; int messageLeft = 0; int messageRight = 0; int panelWidth = (int)((camera.DungeonViewport.Width / 2) - (DevConstants.Grid.CellSize * 2)); List <Tuple <Color, string> > leftFindings = new List <Tuple <Color, string> >(); List <Tuple <Color, string> > rightFindings = new List <Tuple <Color, string> >(); //Gather information for the left side if (!dungeonGrid[(int)observerPosition.Position.X, (int)observerPosition.Position.Y].Found) { leftFindings.Add(new Tuple <Color, string>(Colors.Messages.Bad, Messages.Observer.NotFound)); } else { if (dungeonGrid[(int)observerPosition.Position.X, (int)observerPosition.Position.Y].InRange) { leftFindings.Add(new Tuple <Color, string>(Colors.Messages.Good, Messages.Observer.InRange)); } else { leftFindings.Add(new Tuple <Color, string>(Colors.Messages.Bad, Messages.Observer.OutOfRange)); } leftFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); switch (dungeonGrid[(int)observerPosition.Position.X, (int)observerPosition.Position.Y].Type) { case TileType.TILE_FLOOR: leftFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, Messages.Observer.Floor)); break; case TileType.TILE_WALL: leftFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, Messages.Observer.Wall)); break; case TileType.TILE_ROCK: leftFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, Messages.Observer.Rock)); break; case TileType.TILE_WATER: leftFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, Messages.Observer.Water)); break; case TileType.TILE_TALLGRASS: leftFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, Messages.Observer.TallGrass)); break; case TileType.TILE_FLATTENEDGRASS: leftFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, Messages.Observer.FlatGrass)); break; case TileType.TILE_FIRE: leftFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, Messages.Observer.Fire)); break; case TileType.TILE_ASH: leftFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, Messages.Observer.Ash)); break; } } if (observer.SeeUnknown) { leftFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); leftFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, Messages.Observer.Unknown)); } if (observer.Observed.Count > 0) { leftFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); leftFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, "From here you can see the following: ")); } //Gather observed names for the left side foreach (Entity en in observedItems) { string prepend = (en.Id == observer.SelectedItem) ? "> " : string.Empty; Color color = (en.Id == observer.SelectedItem) ? Colors.Messages.LootPickup : Colors.Messages.Normal; leftFindings.Add(new Tuple <Color, string>(color, prepend + spaceComponents.NameComponents[en.Id].Name)); } //Gather information for right side Entity selectedEntity = spaceComponents.Entities.Where(x => x.Id == observer.SelectedItem).FirstOrDefault(); if (selectedEntity != null) { if (spaceComponents.NameComponents[selectedEntity.Id].Name == "You") { rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("You see yourself here."))); } else { rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, spaceComponents.NameComponents[selectedEntity.Id].Name)); } rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, spaceComponents.NameComponents[selectedEntity.Id].Description)); //If the finding is an AI, gather the information for it if ((selectedEntity.ComponentFlags & ComponentMasks.ObservableAI) == ComponentMasks.ObservableAI) { AIState state = spaceComponents.AIStateComponents[selectedEntity.Id]; AIAlignment alignment = spaceComponents.AIAlignmentComponents[selectedEntity.Id]; SkillLevelsComponent skills = spaceComponents.SkillLevelsComponents[selectedEntity.Id]; switch (alignment.Alignment) { case AIAlignments.ALIGNMENT_NONE: rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, "Neutral")); break; case AIAlignments.ALIGNMENT_HOSTILE: rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Bad, "Hostile")); break; case AIAlignments.ALIGNMENT_FRIENDLY: rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Good, "Friendly")); break; } switch (state.State) { case AIStates.STATE_SLEEPING: rightFindings.Add(new Tuple <Color, string>(Colors.Messages.StatusChange, "Sleeping")); break; case AIStates.STATE_ROAMING: rightFindings.Add(new Tuple <Color, string>(Colors.Messages.StatusChange, "Roaming")); break; case AIStates.STATE_ATTACKING: rightFindings.Add(new Tuple <Color, string>(Colors.Messages.StatusChange, "Attacking")); break; case AIStates.STATE_FLEEING: rightFindings.Add(new Tuple <Color, string>(Colors.Messages.StatusChange, "Fleeing")); break; } //Status Effects: Statuses statuses = StatusSystem.GetStatusEffectsOfEntity(spaceComponents, selectedEntity.Id, dungeonGrid); if (statuses == Statuses.NONE) { rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, Messages.StatusMessages.Normal)); rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); } //If there are status effects on the player.. else { if ((statuses & Statuses.BURNING) == Statuses.BURNING) { BurningComponent burning = spaceComponents.BurningComponents[selectedEntity.Id]; rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Bad, string.Format(Messages.StatusMessages.Burning, burning.MinDamage, burning.MaxDamage, burning.TurnsLeft))); } if ((statuses & Statuses.UNDERWATER) == Statuses.UNDERWATER) { rightFindings.Add(new Tuple <Color, string>(Colors.Caves.WaterInRange, Messages.StatusMessages.Underwater)); } if ((statuses & Statuses.HEALTHREGEN) == Statuses.HEALTHREGEN) { HealthRegenerationComponent healthRegen = spaceComponents.HealthRegenerationComponents[selectedEntity.Id]; rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Good, string.Format(Messages.StatusMessages.HealthRegen, healthRegen.HealthRegain, healthRegen.RegenerateTurnRate))); } rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); } Entity player = spaceComponents.Entities.Where(x => (x.ComponentFlags & Component.COMPONENT_PLAYER) == Component.COMPONENT_PLAYER).First(); rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("Health: {0} / {1}", skills.CurrentHealth, skills.Health))); if (alignment.Alignment != AIAlignments.ALIGNMENT_FRIENDLY) { rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Good, string.Format("You have a {0}% chance to hit.", Math.Ceiling(CombatSystem.CalculateAccuracy(spaceComponents, spaceComponents.SkillLevelsComponents[player.Id], player.Id, skills, selectedEntity.Id))))); rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Bad, string.Format("It has a {0}% chance of hitting you for a maximum of {1}.", Math.Ceiling(CombatSystem.CalculateAccuracy(spaceComponents, skills, selectedEntity.Id, spaceComponents.SkillLevelsComponents[player.Id], player.Id)), skills.MaximumDamage))); } } //If the observed item is an item, gather that information instead if ((selectedEntity.ComponentFlags & ComponentMasks.ObservableItem) == ComponentMasks.ObservableItem) { rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); PickupComponent pickup = spaceComponents.PickupComponents[selectedEntity.Id]; switch (pickup.PickupType) { case ItemType.GOLD: rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Special, "Gold")); break; case ItemType.CONSUMABLE: rightFindings.Add(new Tuple <Color, string>(Colors.Messages.LootPickup, "Consumable")); break; case ItemType.ARTIFACT: rightFindings.Add(new Tuple <Color, string>(Colors.Messages.LootPickup, "Artifact")); break; } if ((selectedEntity.ComponentFlags & ComponentMasks.ObservableValue) == ComponentMasks.ObservableValue && pickup.PickupType != ItemType.DOWNSTAIRS) { ValueComponent value = spaceComponents.ValueComponents[selectedEntity.Id]; rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Special, string.Format("This item is worth {0} gold.", value.Gold))); } if ((selectedEntity.ComponentFlags & ComponentMasks.ObservableSkillModifications) == ComponentMasks.ObservableSkillModifications) { StatModificationComponent stats = spaceComponents.StatModificationComponents[selectedEntity.Id]; rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, "This artifact affects the following stats: ")); if (stats.AccuracyChange != 0) { string sign = stats.AccuracyChange > 0 ? "+" : string.Empty; Color color = stats.AccuracyChange > 0 ? Colors.Messages.Good : Colors.Messages.Bad; rightFindings.Add(new Tuple <Color, string>(color, string.Format("Accuracy {0}{1}", sign, stats.AccuracyChange))); } if (stats.DefenseChange != 0) { string sign = stats.DefenseChange > 0 ? "+" : string.Empty; Color color = stats.DefenseChange > 0 ? Colors.Messages.Good : Colors.Messages.Bad; rightFindings.Add(new Tuple <Color, string>(color, string.Format("Defense {0}{1}", sign, stats.DefenseChange))); } if (stats.HealthChange != 0) { string sign = stats.HealthChange > 0 ? "+" : string.Empty; Color color = stats.HealthChange > 0 ? Colors.Messages.Good : Colors.Messages.Bad; rightFindings.Add(new Tuple <Color, string>(color, string.Format("Maximum Health {0}{1}", sign, stats.HealthChange))); } if (stats.DieNumberChange != 0) { string sign = stats.DieNumberChange > 0 ? "+" : string.Empty; Color color = stats.DieNumberChange > 0 ? Colors.Messages.Good : Colors.Messages.Bad; rightFindings.Add(new Tuple <Color, string>(color, string.Format("Dice Number on Attack {0}{1}", sign, stats.DieNumberChange))); } if (stats.MinimumDamageChange != 0) { string sign = stats.MinimumDamageChange > 0 ? "+" : string.Empty; Color color = stats.MinimumDamageChange > 0 ? Colors.Messages.Good : Colors.Messages.Bad; rightFindings.Add(new Tuple <Color, string>(color, string.Format("Minimum Damage {0}{1}", sign, stats.MinimumDamageChange))); } if (stats.MaximumDamageChange != 0) { string sign = stats.MaximumDamageChange > 0 ? "+" : string.Empty; Color color = stats.MaximumDamageChange > 0 ? Colors.Messages.Good : Colors.Messages.Bad; rightFindings.Add(new Tuple <Color, string>(color, string.Format("Maximum Damage {0}{1}", sign, stats.MaximumDamageChange))); } } if ((selectedEntity.ComponentFlags & ComponentMasks.ObservableUsage) == ComponentMasks.ObservableUsage) { ItemFunctionsComponent funcs = spaceComponents.ItemFunctionsComponents[selectedEntity.Id]; rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Good, string.Format("This item has {0} uses left.", funcs.Uses))); rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Bad, string.Format("This item loses {0} value per use.", funcs.CostToUse))); if (funcs.Ranged) { rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, "This item is cast at a range.")); } else { rightFindings.Add(new Tuple <Color, string>(Colors.Messages.Normal, "This item is used where you stand.")); } } } } //Draw sections //Left section spriteBatch.Draw(UITexture, new Rectangle(0, 0, panelWidth, (int)camera.DungeonViewport.Height), Color.Black * .5f); foreach (Tuple <Color, string> message in leftFindings) { if (string.IsNullOrEmpty(message.Item2)) { continue; } string text = MessageDisplaySystem.WordWrap(font, message.Item2, panelWidth - messageSpacing); float textHeight = font.MeasureString(message.Item2).Y; spriteBatch.DrawString(font, text, new Vector2(messageSpacing, messageSpacing + (messageLeft * messageSpacing)), message.Item1); messageLeft += Regex.Matches(text, System.Environment.NewLine).Count; messageLeft += 1; } //Right section if (observer.Observed.Count > 0) { spriteBatch.Draw(UITexture, new Rectangle((int)camera.DungeonViewport.Bounds.Right - panelWidth, 0, panelWidth, (int)camera.DungeonViewport.Height), Color.Black * .5f); foreach (Tuple <Color, string> message in rightFindings) { if (string.IsNullOrEmpty(message.Item2)) { continue; } string text = MessageDisplaySystem.WordWrap(font, message.Item2, panelWidth - messageSpacing); float textHeight = font.MeasureString(message.Item2).Y; spriteBatch.DrawString(font, text, new Vector2((int)camera.DungeonViewport.Bounds.Right - panelWidth + messageSpacing, messageSpacing + (messageRight * messageSpacing)), message.Item1); messageRight += Regex.Matches(text, System.Environment.NewLine).Count; messageRight += 1; } } } }
public static void HandleMeleeCombat(StateSpaceComponents spaceComponents, int cellSize) { IEnumerable <Guid> entities = spaceComponents.GlobalCollisionComponent.EntitiesThatCollided.Distinct(); foreach (Guid id in entities) { Entity collidingObject = spaceComponents.Entities.Where(x => x.Id == id).FirstOrDefault(); if (collidingObject == null || (((collidingObject.ComponentFlags & ComponentMasks.CombatReadyAI) != ComponentMasks.CombatReadyAI) && (collidingObject.ComponentFlags & Component.COMPONENT_PLAYER) != Component.COMPONENT_PLAYER)) { //If the colliding object isn't a combat ready AI or a player, don't try to do combat with it. continue; } foreach (Guid collidedEntity in spaceComponents.CollisionComponents[id].CollidedObjects) { Entity collidedObject = spaceComponents.Entities.Where(x => x.Id == collidedEntity).FirstOrDefault(); if (collidedObject != null && (((collidedObject.ComponentFlags & ComponentMasks.CombatReadyAI) == ComponentMasks.CombatReadyAI) || (collidedObject.ComponentFlags & Component.COMPONENT_PLAYER) == Component.COMPONENT_PLAYER)) { int damageDone = 0; SkillLevelsComponent collidedStats = spaceComponents.SkillLevelsComponents[collidedEntity]; SkillLevelsComponent attackingStats = spaceComponents.SkillLevelsComponents[id]; EntityMessageComponent collidedMessages = spaceComponents.EntityMessageComponents[collidedEntity]; EntityMessageComponent attackingMessages = spaceComponents.EntityMessageComponents[id]; bool isPlayerAttacking = ((spaceComponents.Entities.Where(x => x.Id == id).First().ComponentFlags & Component.COMPONENT_PLAYER) == Component.COMPONENT_PLAYER); bool isPlayerBeingAttacked = ((spaceComponents.Entities.Where(x => x.Id == collidedEntity).First().ComponentFlags & Component.COMPONENT_PLAYER) == Component.COMPONENT_PLAYER); //If the two attacking creatures don't share an alignment, allow the attack to happen. if (spaceComponents.AIAlignmentComponents[id].Alignment != spaceComponents.AIAlignmentComponents[collidedEntity].Alignment && collidedStats.CurrentHealth > 0 && attackingStats.CurrentHealth > 0) { string combatString = "[TURN " + spaceComponents.GameplayInfoComponent.StepsTaken + "] "; combatString += isPlayerBeingAttacked ? string.Format(attackingMessages.AttackPlayerMessages[spaceComponents.random.Next(0, attackingMessages.AttackPlayerMessages.Count())], spaceComponents.NameComponents[id].Name) : string.Format(attackingMessages.AttackNPCMessages[spaceComponents.random.Next(0, attackingMessages.AttackNPCMessages.Count())], spaceComponents.NameComponents[id].Name, spaceComponents.NameComponents[collidedEntity].Name); //Hit if (CombatSystem.WillMeleeAttackHit(spaceComponents.random, CombatSystem.CalculateAccuracy(spaceComponents, attackingStats, id, collidedStats, collidedEntity))) { //Determine weapon strength and die numbers here, then... damageDone = CombatSystem.CalculateMeleeDamage(spaceComponents, attackingStats, id); collidedStats.CurrentHealth -= damageDone; if (attackingStats.TimesMissed > 5) { combatString += string.Format(collidedMessages.BrokenDodgeStreakTakeDamageMessages[spaceComponents.random.Next(0, collidedMessages.BrokenDodgeStreakTakeDamageMessages.Count())], damageDone); } else { combatString += string.Format(collidedMessages.NormalTakeDamageMessages[spaceComponents.random.Next(0, collidedMessages.NormalTakeDamageMessages.Count())], damageDone); } attackingStats.TimesHit += 1; attackingStats.TimesMissed = 0; Color messageColor = (spaceComponents.AIAlignmentComponents[id].Alignment == AIAlignments.ALIGNMENT_HOSTILE) ? Colors.Messages.Bad : Colors.Messages.Good; spaceComponents.GameMessageComponent.GameMessages.Add(new Tuple <Microsoft.Xna.Framework.Color, string>(messageColor, combatString)); InventorySystem.IncrementDamageGivenWithArtifact(spaceComponents, id, damageDone); InventorySystem.UpdateMaxCombo(spaceComponents, id, (int)attackingStats.TimesHit); InventorySystem.IncrementDamageTakenWithArtifact(spaceComponents, collidedEntity, damageDone); if ((spaceComponents.Entities.Where(x => x.Id == collidedEntity).First().ComponentFlags & Component.COMPONENT_AI_STATE) == Component.COMPONENT_AI_STATE) { AIState state = spaceComponents.AIStateComponents[collidedEntity]; if (state.State == AIStates.STATE_ROAMING) { AISystem.AITryToFind(collidedEntity, spaceComponents); } } } //Miss else { attackingStats.TimesMissed += 1; if (attackingStats.TimesMissed > 5) { combatString += string.Format(collidedMessages.StreakDodgeMessages[spaceComponents.random.Next(0, collidedMessages.StreakDodgeMessages.Count())], damageDone); } else { combatString += string.Format(collidedMessages.NormalDodgeMessages[spaceComponents.random.Next(0, collidedMessages.NormalDodgeMessages.Count())], damageDone); } attackingStats.TimesHit = 0; Color messageColor = (spaceComponents.AIAlignmentComponents[id].Alignment == AIAlignments.ALIGNMENT_HOSTILE) ? Colors.Messages.Good : Colors.Messages.Bad; spaceComponents.GameMessageComponent.GameMessages.Add(new Tuple <Microsoft.Xna.Framework.Color, string>(messageColor, combatString)); InventorySystem.IncrementTimesDodgedWithArtifact(spaceComponents, collidedEntity); InventorySystem.IncrementTimesMissesWithArtifact(spaceComponents, id); } if (collidedStats.CurrentHealth <= 0) { Entity deadEntity = spaceComponents.Entities.Where(x => x.Id == collidedEntity).FirstOrDefault(); if (deadEntity != null) { InventorySystem.DropWholeInventory(spaceComponents, deadEntity.Id, spaceComponents.PositionComponents[deadEntity.Id].Position); deadEntity.ComponentFlags &= ~Component.COMPONENT_POSITION; } InventorySystem.IncrementKillsWithArtifact(spaceComponents, id); spaceComponents.EntitiesToDelete.Add(collidedEntity); if (isPlayerAttacking) { spaceComponents.GameMessageComponent.GameMessages.Add(new Tuple <Color, string>(Colors.Messages.Special, string.Format("[TURN " + spaceComponents.GameplayInfoComponent.StepsTaken + "] " + "You killed the {0}!", spaceComponents.NameComponents[collidedEntity].Name))); GameplayInfoComponent gameInfo = spaceComponents.GameplayInfoComponent; gameInfo.Kills += 1; spaceComponents.GameplayInfoComponent = gameInfo; } else if (isPlayerBeingAttacked) { spaceComponents.GameMessageComponent.GameMessages.Add(new Tuple <Color, string>(Colors.Messages.Special, string.Format("[TURN " + spaceComponents.GameplayInfoComponent.StepsTaken + "] " + "You were killed by a {0}!", spaceComponents.NameComponents[id].Name))); //SCORE RECORD } else { spaceComponents.GameMessageComponent.GameMessages.Add(new Tuple <Color, string>(Colors.Messages.Special, string.Format("[TURN " + spaceComponents.GameplayInfoComponent.StepsTaken + "] " + "{0} killed the {1}!", spaceComponents.NameComponents[id].Name, spaceComponents.NameComponents[collidedEntity].Name))); } } spaceComponents.SkillLevelsComponents[id] = attackingStats; spaceComponents.SkillLevelsComponents[collidedEntity] = collidedStats; } } } } }
public static double CalculateAccuracy(StateSpaceComponents spaceComponents, SkillLevelsComponent attacker, Guid attackerId, SkillLevelsComponent defender, Guid defenderId) { attacker = InventorySystem.ApplyStatModifications(spaceComponents, attackerId, attacker); defender = InventorySystem.ApplyStatModifications(spaceComponents, defenderId, defender); return(attacker.Accuracy * (Math.Pow(.95, defender.Defense))); }
public static void WriteMessages(StateSpaceComponents spaceComponents, SpriteBatch spriteBatch, Camera camera, SpriteFont font, DungeonTile[,] dungeonGrid) { float opacity = 1.15f; float decrement = .09f; int messageNumber = 0; int messageSpacing = (int)font.MeasureString("g").Y + 1;; //Draw message log if (spaceComponents.GameMessageComponent.IndexBegin > 0) { float textHeight = font.MeasureString(Messages.ScrollingMessages).Y; spriteBatch.DrawString(font, Messages.ScrollingMessages, new Vector2(10, (int)camera.DungeonUIViewport.Bounds.Bottom - (int)textHeight - 10 - (messageNumber * messageSpacing)), Color.MediumVioletRed); messageNumber += 1; } foreach (Tuple <Color, string> message in spaceComponents.GameMessageComponent.GameMessages.Reverse <Tuple <Color, string> >().Skip(spaceComponents.GameMessageComponent.IndexBegin)) { if (opacity < 0) { break; } opacity -= decrement; string text = MessageDisplaySystem.WordWrap(font, message.Item2, camera.DungeonUIViewport.Width - 20); float textHeight = font.MeasureString(text).Y; spriteBatch.DrawString(font, text, new Vector2(10, (int)camera.DungeonUIViewport.Bounds.Bottom - (int)textHeight - 10 - (messageNumber * messageSpacing)), message.Item1 * opacity); messageNumber += Regex.Matches(text, System.Environment.NewLine).Count; messageNumber += 1; } while (spaceComponents.GameMessageComponent.GameMessages.Count > spaceComponents.GameMessageComponent.MaxMessages) { spaceComponents.GameMessageComponent.GameMessages.RemoveAt(0); } spriteBatch.DrawString(font, spaceComponents.GameMessageComponent.GlobalMessage, new Vector2(10, camera.Bounds.Height - messageSpacing), spaceComponents.GameMessageComponent.GlobalColor); messageNumber = 0; //Draw statistics List <Tuple <Color, string> > statsToPrint = new List <Tuple <Color, string> >(); GameplayInfoComponent gameplayInfo = spaceComponents.GameplayInfoComponent; statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("Floor {0}", gameplayInfo.FloorsReached))); statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("Steps: {0}", gameplayInfo.StepsTaken))); statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("Kills: {0}", gameplayInfo.Kills))); Entity player = spaceComponents.Entities.Where(x => (x.ComponentFlags & ComponentMasks.Player) == ComponentMasks.Player).FirstOrDefault(); if (player != null) { SkillLevelsComponent skills = InventorySystem.ApplyStatModifications(spaceComponents, player.Id, spaceComponents.SkillLevelsComponents[player.Id]); InventoryComponent inventory = spaceComponents.InventoryComponents[player.Id]; statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("Health: {0} / {1}", skills.CurrentHealth, skills.Health))); statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("Wealth: {0}", skills.Wealth))); statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("Damage: {0}-{1}", skills.MinimumDamage, skills.MaximumDamage))); statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("Accuracy: {0}", skills.Accuracy))); statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, string.Format("Defense: {0}", skills.Defense))); statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); //Status Effects: Statuses statuses = StatusSystem.GetStatusEffectsOfEntity(spaceComponents, player.Id, dungeonGrid); if (statuses == Statuses.NONE) { statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, Messages.StatusMessages.Normal)); statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); } //If there are status effects on the player.. else { if ((statuses & Statuses.BURNING) == Statuses.BURNING) { BurningComponent burning = spaceComponents.BurningComponents[player.Id]; statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Bad, string.Format(Messages.StatusMessages.Burning, burning.MinDamage, burning.MaxDamage, burning.TurnsLeft))); } if ((statuses & Statuses.UNDERWATER) == Statuses.UNDERWATER) { statsToPrint.Add(new Tuple <Color, string>(Colors.Caves.WaterInRange, Messages.StatusMessages.Underwater)); } if ((statuses & Statuses.HEALTHREGEN) == Statuses.HEALTHREGEN) { HealthRegenerationComponent healthRegen = spaceComponents.HealthRegenerationComponents[player.Id]; statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Good, string.Format(Messages.StatusMessages.HealthRegen, healthRegen.HealthRegain, healthRegen.RegenerateTurnRate))); } statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); } statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Special, string.Format(Messages.InventoryArtifacts + " ({0}/{1})", inventory.Artifacts.Count, inventory.MaxArtifacts))); foreach (Guid id in inventory.Artifacts) { NameComponent name = spaceComponents.NameComponents[id]; ArtifactStatsComponent artifactStats = spaceComponents.ArtifactStatsComponents[id]; statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.LootPickup, string.Format("{0} Lv{1}", name.Name, artifactStats.UpgradeLevel))); } statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Special, string.Format(Messages.InventoryConsumables + " ({0}/{1})", inventory.Consumables.Count, inventory.MaxConsumables))); if (inventory.Consumables.Count > 0) { statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); NameComponent name = spaceComponents.NameComponents[inventory.Consumables[0]]; ItemFunctionsComponent funcs = spaceComponents.ItemFunctionsComponents[inventory.Consumables[0]]; statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.LootPickup, string.Format("{0}({1})", name.Name, funcs.Uses))); statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, "Q - Use")); statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, "X - Throw")); statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, System.Environment.NewLine)); if (inventory.Consumables.Count > 1) { name = spaceComponents.NameComponents[inventory.Consumables[1]]; funcs = spaceComponents.ItemFunctionsComponents[inventory.Consumables[1]]; statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.LootPickup, string.Format("{0}({1})", name.Name, funcs.Uses))); statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, "E - Use")); statsToPrint.Add(new Tuple <Color, string>(Colors.Messages.Normal, "C - Throw")); } } } if (font != null) { foreach (Tuple <Color, string> stat in statsToPrint) { string text = MessageDisplaySystem.WordWrap(font, stat.Item2, camera.DungeonUIViewportLeft.Width - messageSpacing); Vector2 messageSize = font.MeasureString(stat.Item2); spriteBatch.DrawString(font, text, new Vector2(camera.DungeonUIViewportLeft.X + 10, 10 + (messageSpacing * messageNumber)), stat.Item1); messageNumber += 1; messageNumber += Regex.Matches(text, System.Environment.NewLine).Count; } } }