Skip to content

Instantly share code, notes, and snippets.

@BanalityOfSeeking
Last active March 16, 2021 23:19
Show Gist options
  • Select an option

  • Save BanalityOfSeeking/e66a1e5265b0107411413ed336a0c19d to your computer and use it in GitHub Desktop.

Select an option

Save BanalityOfSeeking/e66a1e5265b0107411413ed336a0c19d to your computer and use it in GitHub Desktop.
SOSCSRPG Inspired Console App
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]();
}
}
}
}
}
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);
}
}
}
}
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);
}
}
}
}
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