Last active
March 16, 2021 23:19
-
-
Save BanalityOfSeeking/e66a1e5265b0107411413ed336a0c19d to your computer and use it in GitHub Desktop.
SOSCSRPG Inspired Console App
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using Engine.Services; | |
| using Engine.ViewModels; | |
| using Konsole; | |
| using System.Drawing; | |
| using Engine.Models; | |
| namespace SOSCSRPG_Console | |
| { | |
| partial class Program | |
| { | |
| public static GameDetails gameDetails = GameDetailsService.ReadGameDetails(); | |
| private static GameSession GameSession { get; set; } | |
| private static readonly MessageBroker _messageBroker = MessageBroker.GetInstance(); | |
| private static IConsole LogWindow { get; set; } | |
| private static IConsole MainWindow { get; set; } | |
| private static IConsole PlayerWindow { get; set; } | |
| private static IConsole GameWindow { get; set; } | |
| private static IConsole MainGameWindow { get; set; } | |
| private static IConsole LogGameWindow { get; set; } | |
| private static IConsole BasicsWindow { get; set; } | |
| private static IConsole StatusWindow { get; set; } | |
| private static IConsole EquipWindow { get; set; } | |
| // MessageBroker EventHandler | |
| public static void Startup() | |
| { | |
| // Console Configuration | |
| Console.SetWindowSize(1, 1); | |
| Console.SetBufferSize(80, 80); | |
| //setup full size window | |
| Console.SetWindowSize(Console.LargestWindowWidth, Console.LargestWindowHeight); | |
| //position to top left (0,0) | |
| Console.SetWindowPosition(0, 0); | |
| // set messagebroker event handler | |
| _messageBroker.OnMessageRaised += MessageHandlers.OnMessageReceived; | |
| // Create player based on selections. | |
| Player player = new PlayerCreation(gameDetails).player; | |
| // Set Property changed handler to notify and update UI. | |
| player.PropertyChanged += MessageHandlers.OnPropertyChanged_TryMatchingUpdate; | |
| // Initialize GameSession with player. | |
| GameSession = new GameSession(gameDetails, player, 0, -1); | |
| // Game screen configuration | |
| MainWindow = new Window().Open(); | |
| var consoles = MainWindow.SplitColumns( | |
| new Split(50, "Player", LineThickNess.Single, ConsoleColor.White), | |
| new Split(Console.LargestWindowWidth - 53, "Game", LineThickNess.Single, ConsoleColor.White) | |
| ); | |
| // set main screen area's | |
| PlayerWindow = consoles[0]; | |
| GameWindow = consoles[1]; | |
| // divide GameWindow into display and log | |
| var GameConsoles = GameWindow.SplitRows | |
| ( | |
| new Split(50, "MainGameWindow"), | |
| new Split(0, "GameLog") | |
| ); | |
| // set display variables | |
| MainGameWindow = GameConsoles[0]; | |
| LogGameWindow = GameConsoles[1]; | |
| // divide playerWindow into display areas needed for game | |
| var playerConsoles = PlayerWindow.SplitRows | |
| ( | |
| new Split(8, "Basics"), | |
| new Split(12, "Status"), | |
| new Split(24, "Inventory"), | |
| new Split(0, "Log") | |
| ); | |
| BasicsWindow = playerConsoles[0]; | |
| StatusWindow = playerConsoles[1]; | |
| EquipWindow = playerConsoles[2]; | |
| LogWindow = playerConsoles[3]; | |
| // add messages handler output.. | |
| MessageHandlers.LogScreen = LogWindow; | |
| Updater<IConsole> konsoleUpdater = Updater<IConsole>.GetUpdater(); | |
| var outputSupport = new Dictionary<string, (int, int)>(); | |
| konsoleUpdater.AddOutputAction((IConsole console, string Title, Func<string> Value) => | |
| { | |
| if (!outputSupport.ContainsKey(Title)) | |
| { | |
| outputSupport.Add(Title, (console.CursorTop, console.CursorLeft)); | |
| } | |
| (int x, int y) = outputSupport[Title]; | |
| console.CursorTop = x; | |
| console.CursorLeft = y; | |
| console.WriteLine(Title + " : " + Value() + " "); | |
| }); | |
| var currentPlayer = GameSession.CurrentPlayer; | |
| konsoleUpdater.AddUpdate(BasicsWindow, "Name", () => $"{currentPlayer.Name}"); | |
| konsoleUpdater.AddUpdate(BasicsWindow, "CurrentHitPoints", () => $"{currentPlayer.CurrentHitPoints}"); | |
| konsoleUpdater.AddUpdate(BasicsWindow, "Level", () => $"{currentPlayer.Level}"); | |
| konsoleUpdater.AddUpdate(BasicsWindow, "ExperiencePoints", () => $"{currentPlayer.ExperiencePoints}"); | |
| (IConsole statWindow, IConsole miscWindow) = StatusWindow.SplitLeftRight(); | |
| konsoleUpdater.AddUpdates(statWindow,currentPlayer.Attributes, (x) => x.DisplayName, (y) => y.ModifiedValue.ToString()); | |
| konsoleUpdater.AddUpdate(miscWindow, "MaximumHitPoints", () => $"{currentPlayer.MaximumHitPoints}"); | |
| konsoleUpdater.AddUpdate(miscWindow, "Gold", () => $"{currentPlayer.Gold}"); | |
| konsoleUpdater.AddUpdate(EquipWindow, "CurrentWeapon", () => $"{currentPlayer?.CurrentWeapon?.Name}"); | |
| konsoleUpdater.AddUpdate(EquipWindow, "CurrentConsumable", () => $"{currentPlayer?.CurrentConsumable?.Name}"); | |
| konsoleUpdater.UpdateAll(); | |
| } | |
| static void Main(string[] args) | |
| { | |
| Startup(); | |
| //var playerInventory = player.SplitBottom("Inventory"); | |
| // input binding | |
| Dictionary<ConsoleKey, Action> _userInputActions = new Dictionary<ConsoleKey, Action> | |
| { | |
| { ConsoleKey.F, () => GameSession.AttackCurrentMonster() }, | |
| { ConsoleKey.C, () => GameSession.UseCurrentConsumable() }, | |
| { ConsoleKey.W, () =>GameSession.MoveNorth() }, | |
| { ConsoleKey.A, () =>GameSession.MoveWest() }, | |
| { ConsoleKey.S, () =>GameSession.MoveSouth() }, | |
| { ConsoleKey.D, () =>GameSession.MoveEast() } | |
| }; | |
| // equips best weapon (requires ID(s) start ascend up as they get better.) | |
| GameSession.CurrentPlayer.CurrentWeapon = GameSession.CurrentPlayer.Inventory.Weapons.OrderByDescending(x => x.ItemTypeID).First(); | |
| GameSession.CurrentPlayer.CurrentConsumable = GameSession.CurrentPlayer.Inventory.HasConsumable ? GameSession.CurrentPlayer.Inventory.Consumables[0].Clone() : null; | |
| bool End = false; | |
| while (!End) | |
| { | |
| if (GameSession?.CurrentMonster != null) | |
| { | |
| LogWindow.WriteLine(GameSession.HasMonster ? $"(F)ight {GameSession?.CurrentMonster?.Name}?" : ""); | |
| } | |
| LogWindow.WriteLine(GameSession.CurrentPlayer.Inventory.Consumables.Count > 0 ? "(C)onsume" : ""); | |
| LogWindow.Write("You can move to the: ("); | |
| if (GameSession.HasLocationToEast) | |
| { | |
| LogWindow.Write(" East : Key = D "); | |
| } | |
| if (GameSession.HasLocationToWest) | |
| { | |
| LogWindow.Write(" West : Key = A "); | |
| } | |
| if (GameSession.HasLocationToNorth) | |
| { | |
| LogWindow.Write(" North: Key = W "); | |
| } | |
| if (GameSession.HasLocationToSouth) | |
| { | |
| LogWindow.Write(" South: Key = S "); | |
| } | |
| LogWindow.WriteLine(")"); | |
| LogWindow.WriteLine("Please enter a Action Key"); | |
| var actionKey = Console.ReadKey(true).Key; | |
| if (_userInputActions.ContainsKey(actionKey)) | |
| { | |
| _userInputActions[actionKey](); | |
| } | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using Konsole; | |
| using Engine.Models; | |
| using Engine.EventArgs; | |
| using System.ComponentModel; | |
| namespace SOSCSRPG_Console | |
| { | |
| public static class MessageHandlers | |
| { | |
| public static IConsole LogScreen { get; set; } | |
| public static Updater<IConsole> Updater = Updater<IConsole>.GetUpdater(); | |
| internal static void OnMessageReceived(object sender, GameMessageEventArgs gameMessage) | |
| { | |
| LogScreen.WriteLine(gameMessage.Message); | |
| } | |
| // PropertyChangedEvent Handler | |
| internal static void OnPropertyChanged_TryMatchingUpdate(object sender, PropertyChangedEventArgs propertyChangedEventArgs) | |
| { | |
| if (sender is Player) | |
| { | |
| Updater.UpdateThis(propertyChangedEventArgs.PropertyName); | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using Engine.Factories; | |
| using Engine.Models; | |
| using System; | |
| using System.Linq; | |
| using System.Collections.Generic; | |
| namespace SOSCSRPG_Console | |
| { | |
| public class PlayerCreation | |
| { | |
| private Race _selectedRace; | |
| private GameDetails GameDetails { get; } | |
| private Race SelectedRace | |
| { | |
| get => _selectedRace; | |
| set | |
| { | |
| _selectedRace = value; | |
| } | |
| } | |
| private string Name { get; set; } | |
| private static List<PlayerAttribute> PlayerAttributes { get; set; } = | |
| new List<PlayerAttribute>(); | |
| private bool HasRaces => | |
| GameDetails.Races.Any(); | |
| private bool HasRaceAttributeModifiers => | |
| HasRaces && GameDetails.Races.Any(r => r.PlayerAttributeModifiers.Any()); | |
| public Player player { get; } | |
| public PlayerCreation(GameDetails gameDetails) | |
| { | |
| GameDetails = gameDetails; | |
| bool SetName = false; | |
| bool SetRace = false; | |
| bool SetPlayer = false; | |
| if (HasRaces) | |
| { | |
| while (SetRace == false) | |
| { | |
| var count = GameDetails.Races.Count(); | |
| for (int i = 0; i < count; i++) | |
| { | |
| Console.WriteLine($"{i} : " + GameDetails.Races[i].DisplayName); | |
| } | |
| Console.WriteLine("Choose race."); | |
| var input = Console.ReadKey(true).KeyChar; | |
| if (int.TryParse(input.ToString(), out int output)) | |
| { | |
| if(output < count) | |
| { | |
| SelectedRace = GameDetails.Races[output]; | |
| SetRace = true; | |
| } | |
| } | |
| } | |
| while (SetName == false) | |
| { | |
| Console.WriteLine("Enter your Name:"); | |
| Name = Console.ReadLine(); | |
| if (!string.IsNullOrWhiteSpace(Name)) | |
| { | |
| SetName = true; | |
| } | |
| } | |
| } | |
| RollNewCharacter(); | |
| while (SetPlayer == false) | |
| { | |
| Console.WriteLine(); | |
| Console.WriteLine("Use these attributes? (Y | N)"); | |
| var key = Console.ReadKey(true); | |
| switch (key.KeyChar.ToString().ToLower()) | |
| { | |
| case "n": | |
| RollNewCharacter(); | |
| break; | |
| case "y": | |
| SetPlayer = true; | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| player = new Player(Name, 0, 10, 10, PlayerAttributes, 10); | |
| // Give player default inventory items, weapons, recipes, etc. | |
| player.AddItemToInventory(ItemFactory.CreateGameItem(1001)); | |
| player.AddItemToInventory(ItemFactory.CreateGameItem(2001)); | |
| player.LearnRecipe(RecipeFactory.RecipeByID(1)); | |
| player.AddItemToInventory(ItemFactory.CreateGameItem(3001)); | |
| player.AddItemToInventory(ItemFactory.CreateGameItem(3002)); | |
| player.AddItemToInventory(ItemFactory.CreateGameItem(3003)); | |
| } | |
| private void RollNewCharacter() | |
| { | |
| PlayerAttributes.Clear(); | |
| foreach (PlayerAttribute playerAttribute in GameDetails.PlayerAttributes) | |
| { | |
| playerAttribute.ReRoll(); | |
| Console.WriteLine(playerAttribute.DisplayName + " : " + playerAttribute.BaseValue); | |
| PlayerAttributes.Add(playerAttribute); | |
| } | |
| ApplyAttributeModifiers(); | |
| } | |
| private void ApplyAttributeModifiers() | |
| { | |
| foreach (PlayerAttribute playerAttribute in PlayerAttributes) | |
| { | |
| var attributeRaceModifier = | |
| SelectedRace.PlayerAttributeModifiers | |
| .FirstOrDefault(pam => pam.AttributeKey.Equals(playerAttribute.Key)); | |
| playerAttribute.ModifiedValue = | |
| playerAttribute.BaseValue + (attributeRaceModifier?.Modifier ?? 0); | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| namespace SOSCSRPG_Console | |
| { | |
| public class Updater<U> | |
| { | |
| private static readonly Updater<U> internalUpdater = new Updater<U>(); | |
| public static Updater<U> GetUpdater() => internalUpdater; | |
| internal readonly Dictionary<U, Dictionary<string, Func<string>>> Updates | |
| = new Dictionary<U, Dictionary<string, Func<string>>>(); | |
| private Action<U, string, Func<string>> Output { get; set; } | |
| public void AddUpdate(U output, string key, Func<string> value) | |
| { | |
| if (!Updates.ContainsKey(output)) | |
| { | |
| Updates.Add(output, new Dictionary<string, Func<string>> ()); | |
| Updates[output].Add(key, value); | |
| } | |
| else | |
| { | |
| Updates[output].Add(key, value); | |
| } | |
| } | |
| // add updates from a enumerable source | |
| public void AddUpdates<T>(U output, IEnumerable<T> source, Func<T, string> getTitle, Func<T, string> getValue) | |
| { | |
| // remove any previous updates | |
| if (Updates.ContainsKey(output)) | |
| { | |
| Updates.Remove(output); | |
| } | |
| // add update handler for output. | |
| Updates.Add(output, new Dictionary<string, Func<string>>()); | |
| // iterate source and add updates. | |
| foreach (var data in source) | |
| { | |
| AddUpdate(output, getTitle(data), () => getValue(data)); | |
| } | |
| } | |
| public void AddOutputAction(Action<U, string, Func<string>> func) | |
| { | |
| Output = func; | |
| } | |
| public void UpdateAll() | |
| { | |
| foreach (U output in Updates.Keys) | |
| { | |
| foreach (var kvp in Updates[output]) | |
| { | |
| Output(output, kvp.Key, kvp.Value); | |
| } | |
| } | |
| } | |
| public void UpdateThis(string PropertyName) | |
| { | |
| bool found = false; | |
| foreach (U output in Updates.Keys) | |
| { | |
| foreach (var kvp in Updates[output]) | |
| { | |
| if (PropertyName == kvp.Key) | |
| { | |
| Output(output, kvp.Key, kvp.Value); | |
| found = true; | |
| break; | |
| } | |
| } | |
| if(found) | |
| { | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment