Giter Club home page Giter Club logo

soscsrpg's Introduction

soscsrpg's People

Contributors

darthpedro avatar dependabot[bot] avatar fx999dev avatar scottlilly avatar soscsrpg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

soscsrpg's Issues

When cloning GameItems, also clone their Action objects

When cloning GameItems, we need to also clone their Action objects, to prevent problems with event subscriptions.

Change it to something like the below (adding in whatever is needed to handle different types of GameItems and Actions):
Weapon clonedWeapon = new Weapon(ItemID, Name, Price, MinimumDamage, MaximumDamage, DamageType, WeaponSpeed, MissRate);
clonedWeapon.Action = new AttackWithWeapon(clonedWeapon);

Replace random number generation

RNGCryptoServiceProvider is being deprecated. Replace with new technique:

public static int GetNumberBetween(int minimumValue, int maximumValue)
{
    // Need to add one to maximumValue, because otherwise,
    // this function will never generate a value that matches the maximumValue.
    // For example: to get a value from 1 to 10 (inclusive),
    // The code must (effectively) call: RandomNumberGenerator.GetInt32(1, 11);
    return RandomNumberGenerator.GetInt32(minimumValue, maximumValue + 1);
}

WPFUI Main Window ComboBox Improvement

Currently the ComboBox in MainWindow for the consumable items only show single items.
That makes for a huge list when there are lots of consumable items in the inventory.

Having multiple of the same consumable items only show once with a quantity concatenation would shorten the list of ComboBox items.

Quest chains

  • Must complete one quest before getting the next in the chain

"Z" key throws an exception if pressed at a location without a monster

The Z key will throw an exception if pressed in the absence of a monster, so I have slightly amended the code at line 250 – 253 of GameSession.cs to:

public void AttackCurrentMonster()
{
if (CurrentMonster == null || CurrentLocation.GetMonster() == null)
{
RaiseMessage(“No monsters to attack here!”);
return;
}

Improve combat

  • Fleeing gives the monster one last attack
  • Not always immediately spawn a new monster after winning a battle

Monster WPF Data File Builder

Made from a project note. it a very dirty solution, but it is a WIP

`

namespace MonsterCreator
{
    using System.Collections.Generic;
    using System.IO;
    using System.Xml;

    public static class BuilderExtensions
    {
        public static MonsterBuilder CreateMonster(this MonsterBuilder builder, string monsterName, int MaximumHitPoints, string WeaponId, int RewardXP, int Gold,
            string ImageName, int Dexterity, IEnumerable<(string ID, int Percentage)> lootBag)
        {
            builder.Monster = builder.XmlFile.CreateElement("Monster");
            builder.Monster.SetAttribute("ID", (builder.Monsters.ChildNodes.Count + 1).ToString());
            builder.Monster.SetAttribute("Name", monsterName);
            builder.Monster.SetAttribute(nameof(MaximumHitPoints), MaximumHitPoints.ToString());
            builder.Monster.SetAttribute(nameof(WeaponId), WeaponId);
            builder.Monster.SetAttribute(nameof(RewardXP), RewardXP.ToString());
            builder.Monster.SetAttribute(nameof(Gold), Gold.ToString());
            builder.Monster.SetAttribute(nameof(ImageName), ImageName);

            var dex = builder.XmlFile.CreateElement(nameof(Dexterity));
            dex.InnerText = Dexterity.ToString();
            builder.Monster.AppendChild(dex);

            var lootItems = builder.XmlFile.CreateElement("LootItems");
            foreach ((string ID, int Percentage) in lootBag)
            {
                var item = builder.XmlFile.CreateElement("LootItem");
                item.SetAttribute(nameof(ID), ID);
                item.SetAttribute(nameof(Percentage), Percentage.ToString());
                lootItems.AppendChild(item);
            }
            builder.Monster.AppendChild(lootItems);
            builder.Monsters.AppendChild(builder.Monster);
            builder.Monster = null;
            builder.XmlFile.Save(".\\GameData\\Monsters.xml");
            return builder;
        }
    }
    public class MonsterBuilder
    {
        private const string MONSTER_DATA_FILENAME = ".\\GameData\\Monsters.xml";
        private const string BaseNode = "/Monsters";
        internal readonly XmlDocument XmlFile = new XmlDocument();
        internal XmlElement Monsters { get; }
        internal XmlElement Monster { get; set; }
        public MonsterBuilder()
        {
            if (File.Exists(MONSTER_DATA_FILENAME))
            {
                XmlFile.Load(MONSTER_DATA_FILENAME);
                if (!string.IsNullOrEmpty(BaseNode))
                {
                    if (XmlFile.SelectSingleNode(BaseNode).NodeType == XmlNodeType.Element)
                    {
                        Monsters = (XmlElement)XmlFile.SelectSingleNode(BaseNode);
                    }
                }
            }
        }
    }
}

using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Engine.Models;

namespace MonsterCreator
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        //Range of Hit Points
        public ObservableCollection<int> HitPoints = new ObservableCollection<int>(Enumerable.Range(1, 25));

        // Complete collection of Monsters so far.
        public ObservableCollection<Monster> Monsters = new ObservableCollection<Monster>();
        public ObservableCollection<(string ItemName, int ID, int Percentage)> Loots = new ObservableCollection<(string, int, int)> 
        {
            ("Rusty Sword", 1002, 25),
            ("Snake fang", 1501, 35),
            ("Rat Claw", 1502, 35),
            ("Spider fang", 1503, 35),
            ("Granola bar", 2001, 50),
            ("Oats", 3001, 50),
            ("Honey", 3002, 50),
            ("Raisins", 3003, 50)
        };


        public MainWindow()
        {
            InitializeComponent();

            MonsterHP.ItemsSource = HitPoints;
            MonsterXP.ItemsSource = HitPoints;
            MonsterXP.SelectedIndex = 0;
            MonsterHP.SelectedIndex = 0;
            Weapons.ItemsSource = Loots.Where(x => x.ID > 1500 && x.ID < 1505).Select(x => x.ItemName);
            Weapons.SelectedIndex = 0;
            Gold1.ItemsSource = HitPoints;
            Gold1.SelectedIndex = 0;
        }


        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MonsterBuilder builder = new MonsterBuilder();

            textBox1.Text = (builder.Monsters.ChildNodes.Count + 1).ToString();
            builder.CreateMonster(
                MonsterName.Content.ToString(),
                MonsterHP.SelectedIndex + 1, 
                Loots.FirstOrDefault(x => x.ItemName == Weapons.Text).ID.ToString(),
                MonsterXP.SelectedIndex + 1,
                int.Parse(Gold1.Text),
                "",
                10,
                Loots.Select(x => (x.ID.ToString(), x.Percentage))
                );
        }
    }
}

`

XAML

`

    <Window
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:MonsterCreator"
            xmlns:System="clr-namespace:System;assembly=System.Runtime" x:Class="MonsterCreator.MainWindow"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800">
        <Grid Margin="0,0,-3,0" HorizontalAlignment="Right" Width="800">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="16*"/>
                <RowDefinition Height="0*"/>
                <RowDefinition Height="5*"/>
                <RowDefinition Height="10*"/>
            </Grid.RowDefinitions>
            <Label x:Name="Monster_Creator" Content="SOSCSRPG Monster Creator 0.1a" HorizontalAlignment="Left" Height="24" Margin="308,10,0,0" VerticalAlignment="Top" Width="184" Grid.ColumnSpan="2"/>
            <Grid HorizontalAlignment="Center" Height="384" Margin="0,34,0,0" VerticalAlignment="Top" Width="380" Grid.RowSpan="4">
                <TextBox x:Name="textBox" HorizontalAlignment="Left" Margin="7,29,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="106" Height="25"/>
                <ComboBox x:Name="MonsterHP" HorizontalAlignment="Left" Height="25" Margin="7,87,0,0" VerticalAlignment="Top" Width="106" />
                <Label x:Name="MonsterName" Content="Name" HorizontalAlignment="Left" Height="24" VerticalAlignment="Top" Width="86" Margin="8,0,0,0"/>
                <Label x:Name="MonsterHitPoints" Content="Hit Points" HorizontalAlignment="Left" Height="24" Margin="8,60,0,0" VerticalAlignment="Top" Width="86"/>
                <Label x:Name="MonsterId" Content="ID" HorizontalAlignment="Left" Height="23" Margin="127,1,0,0" VerticalAlignment="Top" Width="85"/>
                <TextBox x:Name="textBox1" HorizontalAlignment="Left" Height="25" Margin="127,29,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="105" IsEnabled="False"/>
                <Label x:Name="Expierence" Content="Expierence" HorizontalAlignment="Left" Height="25" Margin="127,59,0,0" VerticalAlignment="Top" Width="85"/>
                <ComboBox x:Name="MonsterXP" HorizontalAlignment="Left" Height="25" Margin="127,86,0,0" VerticalAlignment="Top" Width="106" />
                <Label x:Name="Weapon" Content="Weapon" HorizontalAlignment="Left" Margin="10,115,0,0" VerticalAlignment="Top" Width="84"/>
                <ComboBox x:Name="Weapons" HorizontalAlignment="Left" Margin="7,141,0,0" VerticalAlignment="Top" Width="106"/>
                <Label x:Name="Gold" Content="Gold" HorizontalAlignment="Left" Margin="127,114,0,0" VerticalAlignment="Top" Width="75"/>
                <ComboBox x:Name="Gold1" HorizontalAlignment="Left" Margin="127,141,0,0" VerticalAlignment="Top" Width="105"/>
                <Button x:Name="button" Content="Create Monster" HorizontalAlignment="Left" Height="30" Margin="7,240,0,0" VerticalAlignment="Top" Width="106" Click="Button_Click"/>
            </Grid>
        </Grid>
    </Window>

`

Example appended to file

<Monster ID="4" Name="Name" MaximumHitPoints="8" WeaponId="1502" RewardXP="8" Gold="4" ImageName=""> <Dexterity>10</Dexterity> <LootItems> <LootItem ID="1002" Percentage="25" /> <LootItem ID="1501" Percentage="35" /> <LootItem ID="1502" Percentage="35" /> <LootItem ID="1503" Percentage="35" /> <LootItem ID="2001" Percentage="50" /> <LootItem ID="3001" Percentage="50" /> <LootItem ID="3002" Percentage="50" /> <LootItem ID="3003" Percentage="50" /> </LootItems> </Monster>

This is very rough draft, so improvements and eventual push will come

Fix MessageBroker when loading a new game

When loading a new game, the MessageBroker does not remove subscriptions from the previous GameSession object.

Fix this, so we don't have this type of error coming up again.

Intermittent NullReferenceException on player killed

This happens when the player is killed and sent back to the Home location where normally the CurrentMonster in GameSession would be set to null. I believe we have a race condition where sometimes the currentBattle object somehow becomes null before the currentMonster object does and so when we go through the CurrentMonster setter, we hit a NullReferenceException.

Steps to reproduce the behavior:
(very intermittent)

  1. Start the game.
  2. Go to a battle location (found fighting snakes and verified fighting spiders).
  3. Keep fighting and returning to the battles after being killed.
  4. Eventually you may get the error - stack trace below:

System.NullReferenceException
HResult=0x80004003
Message=Object reference not set to an instance of an object.
Source=GameEngine
StackTrace:
at GameEngine.ViewModels.GameSession.set_CurrentMonster(Monster value) in \Engine\ViewModels\GameSession.cs:line 55

image

Lesson 18.4 Step 6 typo

Describe the bug
Typo:
Change the hard-coded “18” value we were passing into the base constructor for the dexterity to “new LiChange the hard-coded “18” value we were passing into the base constructor for the dexterity to “new List()”.

To Reproduce
Steps to reproduce the behavior:

  1. Go to https://soscsrpg.com/build-a-c-wpf-rpg/lesson-18-4-adding-player-attributes-to-living-entities/
  2. Scroll down to Step 6
  3. See typo

Expected behavior
Should be:
Change the hard-coded “18” value we were passing into the base constructor for the dexterity to “new List()”.

Create Contributing.md for contribution guidelines

Most OSS projects have a CONTRIBUTING.md file to describe the process and guidelines for making contributions to the project.

Describe the solution you'd like
We should have a CONTRIBUTING.md for this project.

UI to build data files

  • Separate WPF project to easily create data files for game items, monsters, locations, quests, recipes, etc.
  • Read existing data files
  • Validate existing game data files
  • Write new/modified game data files

Lock down locations

  • Need to be certain level
  • Need to have certain item
  • Need to complete certain quest
  • Need to have certain faction level with group

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.