/// <summary> /// Player /// </summary> /// <param name="aPlayerName"></param> /// <param name="aLocation"></param> public Player(string aPlayerName, Location3i aLocation) : base() { // Create the players key-chain KeyChain = new KeyChain(); // Create the players wallet. Wallet = new Currency(0); G = '@'; Name = aPlayerName; Location = aLocation; C = new Colour() { FG = ConsoleColor.Gray }; Stats = new Stats() { Agility = 2, Charisma = 4, Endurance = 7, Intelligence = 7, Luck = 4, Perception = 2, Strength = 7, }; Initialize(); }
public Armour(string aName, char aGlyph, Colour aColour, Location3i l, ArmourLocation aArmourLocation) : base(ItemType.Armour, aName, aGlyph, aColour, l) { ArmourLocation = aArmourLocation; Condition = 100; }
/// <summary> /// Creates a new instance of <see cref="Actor"/> with the specified glyph /// and colour. /// </summary> public Actor(string aName, char aGlyph, Colour aColor, Location3i aLocation) : this() { Location = aLocation; Name = aName; G = aGlyph; C = aColor; }
/// <summary> /// FireAnt /// </summary> /// <param name="aLocation"></param> public FireAnt(Location3i aLocation) : base("fire ant", 'f', Colour.DarkRed, aLocation) { // All fire-ants start out as passive agressive. Agression = Game.NPC.Agression.PassiveAgressive; this.Write<FireAnt>(@"c:\DNH\monsters.dat"); }
/// <summary> /// creates a new weapon /// </summary> /// <param name="aName">the name of the weapon</param> /// <param name="aGlyph">the weapon glyph</param> /// <param name="aColor">the weapon colour</param> /// <param name="l">the weapon location.</param> /// <param name="aWProps">weapon properties</param> /// <param name="aLoc">worn location</param> /// <param name="aSubType">weapon subtype</param> public Weapon(string aName, char aGlyph, Colour aColor, Location3i l, WeaponProperties aWProps, WeaponLocation aLoc, WeaponSubType aSubType) : base(ItemType.Weapon, aName, aGlyph, aColor, l) { WeaponProperties = aWProps; WeaponSubType = aSubType; WeaponLocation = aLoc; }
/// <summary> /// Creates a new instance of an Item /// </summary> /// <param name="aItemType">The type of item this is.</param> /// <param name="aName">The name of the item to create</param> /// <param name="aGlyph">The glyph used to represent the item on screen.</param> /// <param name="aColor">The color of the item.</param> /// <param name="aLocation">The location of the item</param> public Item(ItemType aItemType, string aName, char aGlyph, Colour aColor, Location3i aLocation) { ItemType = aItemType; // Set the item type of this item. Name = aName; // Set the name of the item G = aGlyph; // Set the glyph C = aColor; // Set the color Location = aLocation; // The the location }
/// <summary> /// UpdateSeenData /// </summary> /// <param name="aLocation">The location to update "seen" data with.</param> public void UpdateSeenData(Location3i aLocation, double aSightDistance) { SeenRadius(delegate(int x, int y) { // Compute the distance from the passed location to the // [x, y] in the iterator if (Location2i.GetNew(x,y).Distance(aLocation) <= aSightDistance) SeenData[x, y, aLocation.D] = true; }); }
public ShortswordOfTheBear(Location3i l) : base("Shortsword of the Bear", '(', Colour.Standard, l, new WeaponProperties() { BaseWeaponDamage = 5, WeaponMaterial = Material.Steel, RustAccumulator = 0, Condition = 100, MaxCondition = 100, }, WeaponLocation.MainHand, WeaponSubType.MainHand | WeaponSubType.Thrown | WeaponSubType.DualWield) { }
/// <summary> /// Determines if there is a monster at this location. /// </summary> /// <param name="l">The location.</param> /// <returns></returns> public NonPlayerControlled MonsterThere(Location3i l) { return NonPlayerControlled.Where(m => m.Location == l) .FirstOrDefault(); }
/// <summary> /// GetTile /// </summary> /// <param name="l"></param> /// <param name="d"></param> /// <returns></returns> public Tile GetTile(Location3i l) { return GetTile(l.X, l.Y, l.D); }
/// <summary> /// IsPassable /// This method is used for shared collision detection. /// </summary> /// <returns></returns> public bool IsPassable(Location3i l) { //if (GameEngine.Player.Location == l) //return false; Tile tmpTile = GetTile(l); if (MonsterThere(l) != null) return false; return !tmpTile.Impassable; }
/// <summary> /// Creates a new NPC with the provided parameters. /// </summary> /// <param name="aName">The name of this NPC</param> /// <param name="aGlyph"></param> /// <param name="aColour"></param> public NonPlayerControlled(string aName, char aGlyph, Colour aColour, Location3i l) : base(aName, aGlyph, aColour, l) { }
/// <summary> /// CheckBounds /// </summary> /// <param name="l"></param> /// <returns></returns> public bool CheckBounds(Location3i l) { Location3i lLowerRight = Location3i.GetNew(DungeonWidth, DungeonHeight, DungeonDepth); if (l < Location3i.Origin3i) return false; else if (l >= lLowerRight) return false; return true; }
/// <summary> /// Set tile /// <remarks>Makes things a bit cleaner.</remarks> /// </summary> /// <param name="t">type</param> /// <param name="g">glyph</param> /// <param name="c">colour = standard.</param> static void SetTile(TileType t, char g, Colour c, Location3i location = null) { var tmpSetTile = new Tile() { G = g, TileType = t, C = c ?? Colour.Standard, }; if (location == null) { location = CurrentLocation; } // Store the previous tile. CurrentMap.SetTile(location, tmpSetTile); PreviousTile = tmpSetTile; }
/// <summary> /// Run /// </summary> public void Run(EngineRunFlags aFlags) { // set engine run flags GameEngine.RunFlags = aFlags; // CursorVisible Console.CursorVisible = false; // set to true for exit. bool done = false; /// Load all monsters. try { MonsterStore = Persisted.Read<List<Monster>>(R.MonsterFile); } catch { UI.Graphics.MessageBox.Show("DotNetHack", "Monster file not found!"); } while (!done) { redo_input: Graphics.CursorToLocation(1, 1); // So as not to pile up blanks. ConsoleKeyInfo input = Console.ReadKey(); Location3i UnitMovement = new Location3i(0, 0, 0); Tile nPlayerTile = CurrentMap.GetTile(Player.Location); switch (input.Key) { default: continue; case ConsoleKey.LeftArrow: UnitMovement.X--; break; case ConsoleKey.RightArrow: UnitMovement.X++; break; case ConsoleKey.UpArrow: UnitMovement.Y--; break; case ConsoleKey.DownArrow: UnitMovement.Y++; break; case ConsoleKey.OemPeriod: if (nPlayerTile.TileType == TileType.StairsUp) UnitMovement.D--; break; case ConsoleKey.P: { // TODO: allow for dynamic selection of what to put on, // should be done via Func<IArmour, bool> for selecting // from the greater list. // // perhaps genericize the dropdown concept. var p = Player.Inventory.Armour.First<IArmour>(); Player.WornArmour.PutOn(p, true); break; } case ConsoleKey.W: { // TODO: allow for dynamic selection of what to put on, // should be done via Func<IWeapon, bool> for selecting. Player.WieldedWeapons.Wield( Dice.RandomChoice<IWeapon>( Player.Inventory.Weapons.ToArray())); break; } case ConsoleKey.OemComma: if (input.Modifiers == ConsoleModifiers.Shift) { if (nPlayerTile.TileType == TileType.StairsDown) UnitMovement.D++; break; } else { Tile nTileUnderPlayer = CurrentMap.GetTile(Player.Location); while (nTileUnderPlayer.HasItems) { IItem cItem = nTileUnderPlayer.Items.Pop(); // switch by item type switch (cItem.ItemType) { default: // TODO: Inventory needs events. Player.Inventory.Push(cItem); break; // Occurs when a player picks up a key. case ItemType.Key: Player.KeyChain.AddKey((Key)cItem); break; // Occurs when a player picks up currency. case ItemType.Currency: Player.Wallet += (Currency)cItem; break; } } CurrentMap.DungeonRenderer.ClearLocation(Player.Location); } break; // If the player has potions, then take one off the top shelf // and drink it. // TODO: Allow player to select exactly which potion they'd like to quaff. case ConsoleKey.Q: { // TODO: allow for dynamic selection of potions to quaff. var p = Player.Inventory.Potions.First<IPotion>(); Player.Inventory.Remove(p); p.Quaff(Player); break; } case ConsoleKey.O: { ConsoleKeyInfo tmpInput; Location3i tmpUnitLocation = new Location3i(0, 0, 0); switch (Input.Filter(x => x.Key == ConsoleKey.LeftArrow || x.Key == ConsoleKey.RightArrow || x.Key == ConsoleKey.UpArrow || x.Key == ConsoleKey.DownArrow, out tmpInput).Key) { case ConsoleKey.RightArrow: tmpUnitLocation.X++; break; case ConsoleKey.LeftArrow: tmpUnitLocation.X--; break; case ConsoleKey.UpArrow: tmpUnitLocation.Y--; break; case ConsoleKey.DownArrow: tmpUnitLocation.Y++; break; } if (!CurrentMap.CheckBounds( Player.Location + tmpUnitLocation)) goto redo_input; Tile nDoorTile = CurrentMap.GetTile(Player.Location + tmpUnitLocation); if (nDoorTile.TileFlags == TileFlags.Door) { Door tmpDoor = (Door)nDoorTile; if (!tmpDoor.IsLocked) { if (tmpDoor.IsOpen) tmpDoor.CloseDoor(); else tmpDoor.OpenDoor(); } else { if (Player.KeyChain.CanUnLock(tmpDoor)) { if (tmpDoor.IsOpen) tmpDoor.CloseDoor(); else tmpDoor.OpenDoor(); } } } break; } case ConsoleKey.Escape: done = true; break; } if (!CurrentMap.CheckBounds(Player.Location + UnitMovement)) goto redo_input; var tmpMonster = CurrentMap.MonsterThere(Player.Location + UnitMovement); if (tmpMonster != null) { new ActionMeleeAttack(Player, tmpMonster).Perform(); Time = Time.AddSeconds(3); } Tile nMoveToTile = CurrentMap.GetTile(Player.Location + UnitMovement); if (nMoveToTile.TileType == TileType.Wall) goto redo_input; else if (nMoveToTile.TileFlags == TileFlags.Trap) { var nTrapTile = (Trap)nMoveToTile; nTrapTile.OnTrapTriggeredEvent( new Trap.TrapEventArgs(Player)); } else if (nMoveToTile.TileFlags == TileFlags.Door) if (((Door)nMoveToTile).IsClosed) goto redo_input; if (nMoveToTile.HasItems) { if (nMoveToTile.Items.Count == 1) UI.Graphics.Display.ShowMessage(nMoveToTile.Items.First<IItem>().Name); else UI.Graphics.Display.ShowMessage("{0}, {1} here", nMoveToTile.Items.Count, Speech.Pluralize("item", nMoveToTile.Items.Count)); } // Apply the unit movement. if (CurrentMap.IsPassable(Player.Location + UnitMovement)) { Player.Location += UnitMovement; Time = Time.AddSeconds(6); } Update(); CurrentMap.Render(Player.Location); Player.Draw(); } }
/// <summary> /// Creates a new instance of an Item /// </summary> /// <param name="aName">The name of the item to create</param> /// <param name="aGlyph">The glyph used to represent the item on screen.</param> /// <param name="aColor">The color of the item.</param> /// <param name="aLocation">The location of the item</param> public Item(string aName, char aGlyph, Colour aColor, Location3i aLocation) : this(ItemType.Other, aName, aGlyph, aColor, aLocation) { }
/// <summary> /// Creates a new instance of the shop keeper. /// </summary> public GulDarTheShopKeeper(Location3i aLoc) : base("Gul'dar", aLoc) { }
/// <summary> /// HardRefresh /// </summary> /// <param name="l"></param> public void HardRefresh(Location3i l) { IterateXY(delegate(int x, int y) { UI.Graphics.CursorToLocation(x, y); RenderDungeon.MapData[x, y, l.D].C.Set(); Console.Write(RenderDungeon.MapData[x, y, l.D].G); RenderBuffer[x, y].G = RenderDungeon.MapData[x, y, l.D].G; UI.Graphics.CursorToLocation(x, y); }); }
/// <summary> /// Main /// </summary> /// <param name="args"></param> static void Main(string[] args) { // Parse incoming args for the runtime env. R.ParseArgs(args); // Load all monsters try { Monsters = Persisted.Read<List<Monster>>(R.MonsterFile); } catch { UI.Graphics.MessageBox.Show("DNH-Edit", "Monster file not found!"); } // Show welcome message. UI.Graphics.MessageBox.Show("DNH-Edit", "Welcome to DotNetHack-Editor!"); // Create a new map with a couple of floors CurrentMap = new Dungeon3(UI.Graphics.ScreenWidth, UI.Graphics.ScreenHeight, 3); Console.SetWindowSize(UI.Graphics.ScreenWidth, UI.Graphics.ScreenHeight); CurrentLocation = new Location3i(UI.Graphics.ScreenCenter); // The last unit movement is recorded. Location3i LastUnitMovement = Location3i.Origin3i; // The default is the "Layout" mode. CommandProcessor = ProcessLayoutModeCommands; // Set the game engine run flags GameEngine.RunFlags = GameEngine.EngineRunFlags.Debug | GameEngine.EngineRunFlags.Editor; #region Main Loop redo__main_input: try { var inkey = Console.ReadKey(); Location3i UnitMovement = new Location3i(0, 0, 0); switch (inkey.Key) { #region Directional Keys case ConsoleKey.LeftArrow: UnitMovement.X--; break; case ConsoleKey.RightArrow: UnitMovement.X++; break; case ConsoleKey.UpArrow: UnitMovement.Y--; break; case ConsoleKey.DownArrow: UnitMovement.Y++; break; case ConsoleKey.PageUp: UnitMovement.D--; break; case ConsoleKey.PageDown: UnitMovement.D++; break; #endregion #region Editor Control Commands case ConsoleKey.Escape: return; case ConsoleKey.F1: { // Show File Menu // (1) Save // (2) Load // (3) Exit break; } case ConsoleKey.F5: // Create a new instance of the game engine with the current location and map. GameEngine g = new GameEngine(new Player("Editor", CurrentLocation), Util.DeepCopy<Dungeon3>(CurrentMap)); // Run the full out game engine except with editor and debug run flags. g.Run(GameEngine.EngineRunFlags.Debug | GameEngine.EngineRunFlags.Editor); CurrentMap.DungeonRenderer.HardRefresh(CurrentLocation); break; // generate a new guid. case ConsoleKey.F4: UI.Graphics.CursorToLocation(1, 1); CurrentGuid = Guid.NewGuid(); UI.Graphics.MessageBox.Show("Generated New Guid", CurrentGuid.ToString()); UI.Graphics.Display.Refresh(CurrentMap, CurrentLocation); break; // Change editor mode to "Layout" case ConsoleKey.F9: EditorMode = DotNetHack.Editor.EditorMode.Layout; UI.Graphics.Display.ShowMessage("Changed to \"{0}\" mode.", EditorMode); break; // Change editor mode to "Items" case ConsoleKey.F10: EditorMode = DotNetHack.Editor.EditorMode.Items; UI.Graphics.CursorToLocation(1, 1); UI.Graphics.Display.ShowMessage("Changed to \"{0}\" mode.", EditorMode); break; case ConsoleKey.F11: EditorMode = DotNetHack.Editor.EditorMode.Monsters; UI.Graphics.Display.ShowMessage("Changed to \"{0}\" mode.", EditorMode); break; #endregion #region Map Load/Save Commands /** * Save */ case ConsoleKey.F2: if (ConsoleModifiers.Control == inkey.Modifiers) { if (CurrentMapFileName == null) { UI.Graphics.CursorToLocation(1, 1); Console.Write("Save As: "); CurrentMapFileName = Console.ReadLine(); } // save the map, but if this fails say so. CurrentMap.SaveAs(CurrentMapFileName); CurrentMap.DungeonRenderer.HardRefresh(CurrentLocation); } break; /** * Load */ case ConsoleKey.F3: if (ConsoleModifiers.Control == inkey.Modifiers) { UI.Graphics.CursorToLocation(1, 1); Console.Write("Load Dungeon: "); string strLoadFile = Console.ReadLine(); CurrentMap = Dungeon3.Load(strLoadFile); CurrentMapFileName = strLoadFile; CurrentMap.DungeonRenderer.HardRefresh(CurrentLocation); } break; #endregion } // Depending on the editor "mode" re-wire the command procesor // (kind of like a func pointer) switch (EditorMode) { case DotNetHack.Editor.EditorMode.Layout: CommandProcessor = ProcessLayoutModeCommands; break; case DotNetHack.Editor.EditorMode.Items: CommandProcessor = ProcessItemModeCommands; break; case DotNetHack.Editor.EditorMode.Monsters: CommandProcessor = ProcessMonsterModeCommands; break; } // Fire off command processor, be sure to see the switch above CommandProcessor(inkey); // Record what the last UnitMovement was. LastUnitMovement = UnitMovement; // Check the boundaries of the dungeon. if (!CurrentMap.CheckBounds(CurrentLocation + UnitMovement)) goto redo__main_input; // Add UnitMovement to the CurrentLocation. CurrentLocation += UnitMovement; // Render CurrentMap.Render(CurrentLocation); // Move cursor to current location UI.Graphics.CursorToLocation(CurrentLocation); // Show the editor "hand" Console.Write(EDITOR_GLYPH); // CursorToLocation UI.Graphics.CursorToLocation(0, UI.Graphics.ScreenHeight - 1); Console.Write(CurrentLocation); } catch (Exception ex) { UI.Graphics.MessageBox.Show("DNH-Edit Exception", ex); UI.Graphics.Display.Refresh(CurrentMap, CurrentLocation); } // jump back to main input goto redo__main_input; #endregion }
/// <summary> /// Render, renders the Dungeon that this DungeonRenderer is wired to. /// </summary> /// <param name="l">This location/point is refreshed, because we assume the player moved.</param> public void Render(Location3i l) { #if FOG_OF_WAR // TODO: This shit should be else where, and may even benefit from // being called as part of several methods in a multicast delegate that // run each time render is called on a location. RenderDungeon.FogOfWar.UpdateSeenData(l, 6); #endif IterateXY(delegate(int x, int y) { #if FOG_OF_WAR if (RenderDungeon.FogOfWar.Seen(x, y, l.D)) #endif if (RenderBuffer[x, y].G != RenderDungeon.MapData[x, y, l.D].G) { UI.Graphics.CursorToLocation(x, y); if (RenderDungeon.MapData[x, y, l.D].Items.Count <= 0) RenderDungeon.MapData[x, y, l.D].C.Set(); else RenderDungeon.MapData[x, y, l.D].Items.Peek().C.Set(); Console.Write(RenderDungeon.MapData[x, y, l.D].G); RenderBuffer[x, y].G = RenderDungeon.MapData[x, y, l.D].G; UI.Graphics.CursorToLocation(x, y); } }); // draw all non player controlled characters. foreach (var npc in RenderDungeon.NonPlayerControlled) { // clear the location. ClearLocation(npc.Location); // Draw the location. npc.Draw(); } ClearLocation(l); }
/// <summary> /// RefreshBufferedRegion, refreshes the buffer for a two dimensional region /// of the screen. The reason that <see cref="Location3i"/> is passed is that /// we need to know the dungeon level so that we draw the correct boundground data. /// </summary> /// <param name="l">The location (dungeon level to render with)</param> /// <param name="r">The buffered region to re-render/ refresh.</param> public void RefreshBufferedRegion(Location3i l, DisplayRegion r) { for (int x = r.P1.X; x < r.P2.X; ++x) for (int y = r.P1.Y; y <= r.P2.Y; ++y) { UI.Graphics.CursorToLocation(x, y); RenderDungeon.MapData[x, y, l.D].C.Set(); Console.Write(RenderDungeon.MapData[x, y, l.D].G); RenderBuffer[x, y].G = RenderDungeon.MapData[x, y, l.D].G; } }
public GauntletsOfWisdom(Location3i l) : base("Gauntlets of Wisdom", '{', Colour.Silver, l, Equipment.Armour.ArmourLocation.Arms) { }
public void Render(Location3i aLoc) { DungeonRenderer.Render(aLoc); }
/// <summary> /// Creates a new shopkeeper. /// </summary> /// <param name="aShopKeeperName"></param> public ShopKeeper(string aShopKeeperName, Location3i l) : base(aShopKeeperName, '@', Colour.White, l) { }
/// <summary> /// SetTile will set the passed tile at the passed location parameters. /// </summary> /// <param name="l">l3i to set</param> /// <param name="aTile">tile to set</param> public void SetTile(Location3i l, Tile aTile) { MapData[l.X, l.Y, l.D] = aTile; }
/// <summary> /// LockBox /// </summary> /// <param name="aIsLocked">Is this lockbox actually locked?</param> public LockBox(bool aIsLocked, Location3i aLocation) : base("lockbox") { IsLocked = aIsLocked; Location = aLocation; }
/// <summary> /// Clears the screen with specified tile /// </summary> static void clrScreen(TileType tileType, char symbol, Colour color) { Location3i tmpLocation = new Location3i(0, 0, CurrentLocation.D); // Fill entire map with tileType for (int i = 0; i < Console.WindowHeight; i++) { for (int j = 0; j < Console.WindowWidth; j++) { tmpLocation.X = j; tmpLocation.Y = i; SetTile(tileType, symbol, color, tmpLocation); } } }
public HauberkOfDefense(Location3i l) : base("Hauberk of Defense", '{', Colour.Silver, l, Equipment.Armour.ArmourLocation.Chest) { }