/// <summary> /// Sends attack message with added target for computation, then delivers results /// as messages to the player. /// </summary> /// <param name="target">The target of the attack (in this case, the hero)</param> public void Attack(ICombatant target) { var attackPacket = AttackDeliveryPacket; attackPacket.Target = target; var attackResult = CombatManager.DeliverAttack(attackPacket); if (attackResult.Critical) { DungeonGameEngine.ProcessMessageQueue(false, "The " + EntityName + " got a lucky shot inflicting extra damage."); } else if (attackResult.Fumble) { DungeonGameEngine.ProcessMessageQueue(false, "You are slightly amused to see the " + EntityName + " strike at your shadow."); } else if (attackResult.Hit) { DungeonGameEngine.ProcessMessageQueue(false, "The " + EntityName + " hit you."); } else { DungeonGameEngine.ProcessMessageQueue(false, "The " + EntityName + " missed you."); } }
internal static void IdentifyItem(bool selected = false) { if (!selected) { DungeonGameEngine.ProcessMessageQueue(false, "What do you want to identify?"); currentSelectionAction = SelectionActions.Identify; } else { DungeonGameEngine.ProcessMessageQueue(true); // Acknowledge the "What do you want to identify" prompt // Get old text before item gets renamed var listKey = currentItem.SortingValue; // Retrieving this property should cause the item to be identified as well DungeonGameEngine.ProcessMessageQueue(false, currentItem.IdentifyText); currentSelectionAction = SelectionActions.None; // Update inventory list text GameText textItem = inventoryList[listKey]; textItem.Text = currentItem.InventoryTitle; inventoryList.Remove(listKey); inventoryList.Add(currentItem.SortingValue, textItem); closingWindow = true; } }
static internal void PlayDeathMessages() { foreach (var msg in deathMessages) { DungeonGameEngine.ProcessMessageQueue(false, msg); } deathMessages.Clear(); }
internal static void KnockHeroUnconcious() { if (heroCurrentEffects[GameConstants.TemporaryEffects.Fainted] == 0) { DungeonGameEngine.ProcessMessageQueue(false, "You knocked yourself out"); heroCurrentEffects[GameConstants.TemporaryEffects.Fainted] = rand.Next(GameConstants.FAINT_TIME_MIN, GameConstants.FAINT_TIME_MAX + 1); } }
/// <summary> /// Triggers the discovery and effect of the scroll. Does not reduce qty because when qty /// reaches 1 before consumption, the Inventory will delete it from the list. /// </summary> /// <returns></returns> public string Consume() // IConsumable { if (!discoveredEffect) { NameScroll(); DungeonGameEngine.ProcessMessageQueue(false, "It is " + titleOfOneScroll); discoveredEffect = true; } TriggerEffect(); return("The scroll turned to ash as you finished reading it."); }
internal bool AttemptPickupItem(InventoryItem item) { if (item.InventoryWeight < (EffectiveCarryWeight - Inventory.Weight)) { Inventory.Add(item); return(true); } else { DungeonGameEngine.ProcessMessageQueue(false, "You need to drop something first."); return(false); } }
internal static void Die(Monster deadMonster, ICombatant attacker) { // To prevent accidentally forgetting to place the call to EarnXP in each monster subclass // it was placed in this method with a requirement to pass the attacker. if (monsters.Remove(deadMonster)) { CombatManager.AppendDeathMessage("You have killed the " + deadMonster.EntityName + "."); deadMonster.DropLoot(); // Because loot is visible if the tile is revealed, this will explain why you can see it when the hero is blind. if (InventoryEffectManager.HeroBlind) { DungeonGameEngine.ProcessMessageQueue(false, "You hear the " + deadMonster.EntityName + " drop something."); } } else { throw new ArgumentOutOfRangeException("Dead monster was not in the monsters list."); } attacker.EarnXP(deadMonster._XP); }
private bool SurvivesEnergyChange() { if (fat && energy <= EnergyStorage + 1000) { fat = false; DungeonGameEngine.ProcessMessageQueue(false, "You are feeling much leaner and stronger again."); } else if (!fat && energy > EnergyStorage + 1000) { fat = true; DungeonGameEngine.ProcessMessageQueue(false, "You are beginning to feel fat (and not as strong)."); } else if (energy > GameConstants.ENERGY_FAINT_LEVEL * 2) { InventoryEffectManager.FeelsFaint = false; hungry = false; } else if (energy > GameConstants.ENERGY_FAINT_LEVEL) { InventoryEffectManager.FeelsFaint = false; if (!hungry) { DungeonGameEngine.ProcessMessageQueue(false, "You are beginning to feel hungry."); } hungry = true; } else if (energy > 0) { if (!InventoryEffectManager.FeelsFaint) { DungeonGameEngine.ProcessMessageQueue(false, "You feel faint from lack of food."); } InventoryEffectManager.FeelsFaint = true; } else { return(false); } return(true); }
/// <summary> /// Takes player keyboard input and either updates selection change or activates an action on /// the selected item. If the rename window is open, control is passed over and directed to /// that window. Handles timing for when player holds a key while using Inventory window. /// </summary> /// <param name="key"></param> /// <param name="gameTime"></param> /// <param name="dropped"></param> /// <param name="showRenameItemScreen"></param> /// <returns></returns> internal static bool ProcessPlayerInputs(Keys key, GameTime gameTime, out List <InventoryItem> dropped, out bool showRenameItemScreen) { dropped = nothingToDrop; // Prevents creating a new list with every loop showRenameItemScreen = usingRenameItemScreen; elapsedTime += gameTime.ElapsedGameTime.Milliseconds; if (firstLoop) { UpdateCurrentItem(); } if (firstLoop && key != Keys.None) { return(false); // Forces keys to be released upon entry of first loop } firstLoop = false; // If no key pressed, or input passes directly to the RenameScreen, there should be no more delay in this class if (key == Keys.None || key != lastKey || usingRenameItemScreen) { currentDelay = GameConstants.NO_DELAY; } #region Using Rename Item Screen if (usingRenameItemScreen) { Debug.Assert(currentItem != null); string reservedText = (GetItem(inventoryList.ElementAt(selectedIndex).Key) as INamable).ReservedTextForTitle; if (RenameItemScreen.ProcessPlayerInputs(key, gameTime, resetInputWindow, reservedText, out response)) { // Screen closed usingRenameItemScreen = false; firstLoop = true; } resetInputWindow = false; if (response != string.Empty) { Rename(currentItem, true); } lastKey = key; return(false); // The inventory window stays open } #endregion #region Key press for Inventory Screen else if (key != Keys.None && elapsedTime > currentDelay) { elapsedTime = 0; // When a key is first pressed, the initial delay should be set if (key != lastKey) { currentDelay = GameConstants.INITIAL_KEY_DELAY; } // Once the initial delay is over, if the key is still held down, then repeating is allowed else { currentDelay = GameConstants.HOLD_KEY_DELAY; } switch (key) { case Keys.Up: selectedIndex--; window.SelectPrev(); break; case Keys.Down: selectedIndex++; window.SelectNext(); break; case Keys.Enter: if (currentItem != null && currentSelectionAction == SelectionActions.None) { if (currentItem is IWearable && !(currentItem as IWearable).Equipped) { Equip(currentItem); } else if (currentItem is Weapon && !(currentItem as Weapon).Wielded) { Wield(currentItem); } else if (currentItem is IConsumable) { Consume(currentItem); } } else if (currentSelectionAction == SelectionActions.Identify) { IdentifyItem(true); } break; case Keys.Delete: if (currentItem != null && currentSelectionAction == SelectionActions.None) { if (currentItem is IWearable && (currentItem as IWearable).Equipped) { Unequip(currentItem); } else if (currentItem is Weapon && (currentItem as Weapon).Wielded) { Unwield(currentItem); } else { Drop(currentItem); } } break; case Keys.R: if (currentItem != null && currentSelectionAction == SelectionActions.None && currentItem is INamable) { Rename(currentItem); } break; case Keys.Escape: if (currentSelectionAction == SelectionActions.Identify) { DungeonGameEngine.ProcessMessageQueue(false, "It is your breath (and not a very good one at that)."); currentSelectionAction = SelectionActions.None; } closingWindow = true; break; } UpdateCurrentItem(); UpdateKeyboardInstructions(); } #endregion lastKey = key; if (closingWindow) { dropped = dropList.ToList(); dropList.Clear(); firstLoop = true; // Reset for next time window opens closingWindow = false; return(true); } else { return(false); // Does not allow inventory menu to exit yet } }
} // ICombatant public void TakeDamage(CombatManager.DamageResult results) { // If you're hit if (results.AttackResult.Critical || results.AttackResult.Hit) { int hitsTaken = 0; int poisonDamage = 0; bool energyDrained = false; // Sort out the damage types foreach (var damagePair in results.DamageDealt) { switch (damagePair.Key) { case CombatManager.DamageType.Slashing: case CombatManager.DamageType.Bludgeoning: case CombatManager.DamageType.Piercing: hitsTaken += damagePair.Value; break; case CombatManager.DamageType.Rust: // TODO: Implement damage to armor in Inventory class break; case CombatManager.DamageType.Poison: poisonDamage += damagePair.Value; // TODO: Research actual poison damage handling, but for now just set Poisoned // For now, TakePoisonDmg randomly causes HP damage while poisoned and healing is stopped. InventoryEffectManager.HeroPoisoned = true; break; case CombatManager.DamageType.Energy: energy -= damagePair.Value; energyDrained = true; break; default: break; } } // If you died from regular damage if (!TakeHit(hitsTaken)) { deathMessage = "The " + results.Attacker.EntityName + " has killed you."; DungeonGameEngine.ThisGame.GameOver("killed by a " + results.Attacker.EntityName); } // If your energy was drained... if (energyDrained) { // And you survived the drainage... if (SurvivesEnergyChange()) { DungeonGameEngine.ProcessMessageQueue(false, "You feel a sudden loss of energy."); } else { // or if you die from the drainage CombatManager.AppendDeathMessage( "You had all your remaining energy sucked right out of you."); DungeonGameEngine.ThisGame.GameOver("drained to death"); } } } } // ICombatant
public void Attack(ICombatant target) { // Construct attack message CombatManager.AttackDelivery attackMessage = new CombatManager.AttackDelivery(); var currentWeapon = Inventory.CurrentWeapon; if (currentWeapon != null) { attackMessage.CombatType = currentWeapon.CombatType; attackMessage.DamageDice = currentWeapon.DamageDice; } else { // http://www.dandwiki.com/wiki/SRD:Unarmed_Strike attackMessage.CombatType = CombatManager.CombatType.Melee; attackMessage.DamageDice = new KeyValuePair <CombatManager.DamageType, CombatManager.DieType>[] { new KeyValuePair <CombatManager.DamageType, CombatManager.DieType> (CombatManager.DamageType.Bludgeoning, CombatManager.DieType.D3) }; } attackMessage.CombatType = CombatManager.CombatType.Melee; attackMessage.Attacker = this; attackMessage.Target = target; attackMessage.ToHitModifier = 0; attackMessage.DamageModifiers = new Dictionary <CombatManager.DamageType, int>(0); // Set Capacity to 1 // Send the attack CombatManager.AttackResult attackResult = CombatManager.DeliverAttack(attackMessage); // Process the attack results if (attackResult.Critical) { DungeonGameEngine.ProcessMessageQueue(false, "You struck a Critical blow to the " + target.EntityName + "."); } else if (attackResult.Fumble) { // Not all fumbles have to cause trouble if (Utility.Rand.Next(4) == 0) { // But this one did, so what happened var fumbleAction = Utility.Rand.Next(100); if (fumbleAction < 70) { // Either you hit yourself DungeonGameEngine.ProcessMessageQueue(false, "You swing wildly and miss, hitting yourself in the head in the process."); if (Utility.Rand.Next(2) == 0) { InventoryEffectManager.HeroConfused = true; } else { InventoryEffectManager.KnockHeroUnconcious(); } } else { // Or you broke your weapon if (currentWeapon != null) { DungeonGameEngine.ProcessMessageQueue(false, currentWeapon.Break()); } } } } else if (attackResult.Hit) { DungeonGameEngine.ProcessMessageQueue(false, "You hit the " + target.EntityName + "."); } else { DungeonGameEngine.ProcessMessageQueue(false, "You missed the " + target.EntityName + "."); } } // ICombatant
private void VaporizeMonsters() { DungeonGameEngine.ProcessMessageQueue(false, "This scroll has not been implemented yet."); // requires list of visible or detected monsters }
private void CreateUpStairs() { DungeonGameEngine.ProcessMessageQueue(false, "This scroll has not been implemented yet."); }
/// <summary> /// Calls any actions required to put the scroll's effect into motion when consumed /// </summary> /// <returns>string message to user when effect occurs</returns> private void TriggerEffect() { if (effectType == typeof(GameConstants.TemporaryEffects)) { switch (tempEffect) { case GameConstants.TemporaryEffects.Hastened: InventoryEffectManager.HeroHastened = true; break; case GameConstants.TemporaryEffects.Slowed: InventoryEffectManager.HeroSlowed = true; break; case GameConstants.TemporaryEffects.Blind: InventoryEffectManager.HeroBlind = true; break; case GameConstants.TemporaryEffects.Confused: InventoryEffectManager.HeroConfused = true; break; case GameConstants.TemporaryEffects.ImprovedNightSight: InventoryEffectManager.HeroSeesInDark = true; break; case GameConstants.TemporaryEffects.SensesMonster: InventoryEffectManager.HeroDetectsMonsters = true; break; case GameConstants.TemporaryEffects.Stuck: InventoryEffectManager.HeroStuck = true; break; case GameConstants.TemporaryEffects.Observant: InventoryEffectManager.HeroObservant = true; break; } } else { switch (instantEffect) { case GameConstants.InstantEffects.RestoreStrength: DungeonGameEngine.Hero.RestoreStrength(); DungeonGameEngine.ProcessMessageQueue(false, "Your strength has been restored."); break; case GameConstants.InstantEffects.RemoveCurse: Inventory.RemoveCurseItem(); break; case GameConstants.InstantEffects.Identify: Inventory.IdentifyItem(); break; case GameConstants.InstantEffects.RevealMap: RevealMap(); DungeonGameEngine.ProcessMessageQueue(false, "You suddenly feel as if you have been here before."); break; case GameConstants.InstantEffects.AscendStairs: CreateUpStairs(); DungeonGameEngine.ProcessMessageQueue(false, "The scroll flies from your hands and transorms into stairs, going up."); break; case GameConstants.InstantEffects.LightRoom: LightSpaces(); DungeonGameEngine.ProcessMessageQueue(false, "The scroll burned so brightly the walls are still glowing"); break; case GameConstants.InstantEffects.VaporizeMonsters: VaporizeMonsters(); DungeonGameEngine.ProcessMessageQueue(false, "The scroll says it is safe now, but do you believe it?"); break; default: break; } } }