1
\$\begingroup\$

I'm currently learning C# in hopes of making games on my own using Unity. I'm using the Udemy class by Denis Panjuta and followed 8 sections before making my first app by myself.

The 8 sections include Datatypes and Variables, Functions and Methods, Making decisions, Loops, OOP, Arrays and List, and Debugging. I know how important it is to maintain best practices in code, but being new this gets... overwhelming pretty fast.

I'm looking for good practices considering what I know, as I will be able to go further once I acquire more knowledge, of course.

In this game, you play a character who has to work on a school project and need to chose what to do everyday in order to increase specific stats. He has 50 days to finish his project and must defeat 4 bosses, one of which has 3 phases.

I'm using 5 classes; the first is BattleSystem which handles battles:

using System;

namespace My_first_game
{
    // This class handles battles.
    class BattleSystem
    {
        private static bool isOver = false;

        // The battle handles everything needed to have an encounter.
        public static void Battle(Character player)
        {
            bool playerTurn = true; // needs to be true in order for first turn to be the players
            string playerInput; // will hold what the player types in
            bool correctInput; // will check if the input is correct
            int healAmount;
            int damageAmount;
            int phase;
            Enemy boss = GetEnemy(Story.chapter);
            bool alreadyDone = false;
            int numberOfHeals = player.insight / 3;
            string bossLine = "";


            while (!isOver) // while the battle is not over
            {
                phase = DeterminePhase(boss.bossHp, boss.bossTotalHp);
                
                if (playerTurn) // should start here and then alternate
                {
                    Console.WriteLine("\n" + boss.lines[phase][0]);
                    bossLine = AlternateDialogue(phase, boss); // To avoid the boss saying a line that doesn't match with the phase starter.
                    Console.WriteLine("Do you want to (W)ork or take a (B)reak?");
                    do // here we read the line as long as the player does an incorrect input
                    {
                        playerInput = Console.ReadLine();
                        if (playerInput == "W" || playerInput == "w") // to deal damage
                        {
                            damageAmount = Character.DealDamage(player);
                            boss.bossHp -= damageAmount;
                            Console.WriteLine("The boss has {0} hp remaining", boss.bossHp);
                            if (boss.bossHp <= 0)
                                isOver = true;
                            correctInput = true;
                        }
                        else if (playerInput == "B" || playerInput == "b") // to heal
                        {
                            if (numberOfHeals > 0)
                            {
                                healAmount = Program.DiceRoll() * (player.knowledge / 2);
                                Character.Heal(healAmount, player);
                                numberOfHeals--;
                                Console.WriteLine("You have {0} heals left.", numberOfHeals);
                                correctInput = true;
                            }
                            else
                            {
                                Console.WriteLine("You don't have any heals left");
                                correctInput = false;
                            }
                            
                        }
                        else // if input is anything but w, W, b or B
                        {
                            Console.WriteLine("Please enter (w) to heal or (b) to attack.");
                            correctInput = false;
                        }
                    } while (!correctInput);

                    if (((float)boss.bossHp / (float)boss.bossTotalHp * 100) <= boss.insightTrigger && !alreadyDone)
                        alreadyDone = Enemy.InsightCheck(Story.chapter, player, boss);

                    playerTurn = false;
                }
                else // if it's not the players turn, do the enemy turn
                {
                    Console.WriteLine(bossLine);
                    Character.TakeDamage(boss.attackDamage, player);

                    playerTurn = true;
                }
            }

            Console.WriteLine("You won the battle! Press enter to continue!");
            Console.ReadLine();
        }
        // This section will alternate what the boss will say.
        private static string AlternateDialogue(int phase, Enemy boss)
        {
            int rng = new Random().Next(1, 5);
            string line = boss.lines[phase][rng];
            return line;
        }
        
        // Determines which phase the boss is at by fourths of hp left
        public static int DeterminePhase(int currentHp, int totalHp)
        {
            int phase = 0;
            float lifePercent = ((float)currentHp / (float)totalHp) * 100;

            if (lifePercent > 75f)
                phase = 0;
            else if (lifePercent > 50f)
                phase = 1;
            else if (lifePercent > 25f)
                phase = 2;
            else
                phase = 3;

            return phase;
        }
        
        // This takes in the chapter the player is at and figures out which boss to output.
        public static Enemy GetEnemy(int chapter)
        {
            Enemy enemie = new Enemy();
            switch (chapter)
            {
                case 1:
                    enemie = Enemy.Boss1();
                    break;
                case 2:
                    enemie = Enemy.Boss2();
                    break;
                case 3:
                    enemie = Enemy.Boss31();
                    break;
                case 4:
                    enemie = Enemy.Boss32();
                    break;
                case 5:
                    enemie = Enemy.Boss33();
                    break;
                case 6:
                    enemie = Enemy.Boss4();
                    break;
            }
            return enemie;
        }
    }
}

The second one is Enemy for my boss designs:

using System;

namespace My_first_game
{
    // This class handles the boss creation process
    class Enemy
    {
        public int bossHp;
        public int bossTotalHp;
        public int attackDamage;
        // the first line of every subarray is the step the character is at, the rest is dialogue
        public string[][] lines;
        // For insight boosts
        public float insightTrigger; // At what point in the boss health does the effect triggers
        public int insightThreshold; // how much insight the player needs

        // constructor
        public Enemy(int hp, int ad, string[][] text, float itr, int ith)
        {
            bossTotalHp = hp;
            bossHp = bossTotalHp;
            attackDamage = ad;
            lines = text;
            insightTrigger = itr;
            insightThreshold = ith;
    }
        // temp constructor empty
        public Enemy()
        {
        }
        // The bosses should all increase in difficulty the further you go down
        // The patern is variables for balance, insight stuff, Strings for phases 1 to 4, then creating the array, then creating it with the arrays
        // Boss 1 is choosing the subject
        public static Enemy Boss1()
        {
            int hp = 300;
            int ad = new Random().Next(1, 5);

            float itr = 0f;
            int ith = 10;
            
            string t1 = "The first step is finding something original.";
            string t11 = "Trying to find something original?";
            string t12 = "Everything has already been done.";
            string t13 = "Do you really think nobody thought of that?";
            string t14 = "Wow, I'm sure noooobody ever worked on that subject...";

            string t2 = "Now, you need to find the subject interesting yourself.";
            string t21 = "That subject looks booooooring.";
            string t22 = "Do you really find this interesting?";
            string t23 = "Imagine just talking about this to your friends... See their long faces?";
            string t24 = "You will never finish if you chose this subject.";

            string t3 = "Your subject needs to find the perfect balance between vagueness and preciseness.";
            string t31 = "That subject is too vague...";
            string t32 = "That's way too precise, you won't have enough data.";
            string t33 = "Are you planing on doing 500 pages?";
            string t34 = "You know you need at least 80 pages worth of content, right?";

            string t4 = "Finally, make sure your subject is doable.";
            string t41 = "You won't be able to find any data on this subject.";
            string t42 = "You really think you're going to find people to interview over there? Keep dreaming.";
            string t43 = "There's just not enough scientific sources around to chose that subject.";
            string t44 = "Where are you going to find the funds to make that project?";

            string[][] lines = new string[][]
            {
                new string[] { t1, t11, t12, t13, t14 },
                new string[] { t2, t21, t22, t23, t24 },
                new string[] { t3, t31, t32, t33, t34 },
                new string[] { t4, t41, t42, t43, t44 }
            };
            Enemy boss1 = new Enemy(hp, ad, lines, itr, ith);
            return boss1;
        }

        // Boss 2 is the directed reading seminary.
        public static Enemy Boss2()
        {
            int hp = 425;
            int ad = new Random().Next(1, 6);

            float itr = 50f;
            int ith = 12;
            
            string t1 = "You need to make time to read.";
            string t11 = "You don't have the time to work on that.";
            string t12 = "You've got bills to pay, just work instead of reading.";
            string t13 = "Your appartment is a mess... Maybe you should clean it up?";
            string t14 = "When's the last time you took time off?";

            string t2 = "Make sure you are motivated!";
            string t21 = "You'd rather be playing video games right now...";
            string t22 = "You know who you haven't seen in a while? Remember that highschool friend?";
            string t23 = "Finish up quickly here, there's a party at 8.";
            string t24 = "Why are these texts so uninteresting? Hey, author, can you spice things up a little?";

            string t3 = "Taking good notes while you read is crucial! It will help down the line.";
            string t31 = "Reading with a pen in hand is so much slower.";
            string t32 = "It really feels like your not making any progress with all these scribbles.";
            string t33 = "Are these notes even worthwhile?";
            string t34 = "You are never going to read these.";

            string t4 = "Guess what, you have a paper to produce on your readings...";
            string t41 = "Oh no... a blank page appears!";
            string t42 = "You're only repeating what those authors said. YOU're not saying anything original here.";
            string t43 = "Are you seriously going to write that?";
            string t44 = "You thought this would be over in an hour didn't you?";

            string[][] lines = new string[][]
            {
                new string[] { t1, t11, t12, t13, t14 },
                new string[] { t2, t21, t22, t23, t24 },
                new string[] { t3, t31, t32, t33, t34 },
                new string[] { t4, t41, t42, t43, t44 }
            };
            Enemy boss2 = new Enemy(hp, ad, lines, itr, ith);
            return boss2;
        }
        
        // Boss 3 is subdivised in 3 sub bosses which follow the difficulty curve as if they were 3 seperate bosses.
        // Boss 3-1 is argument 1
        public static Enemy Boss31()
        {
            int hp = 525;
            int ad = new Random().Next(2, 7);

            float itr = 100f;
            int ith = 14;

            string t1 = "Let's start right away with your first argument. You'll do the intro later.";
            string t11 = "The first page of project, what are you going to write?";
            string t12 = "How do you even start an argument?";
            string t13 = "You've done this all your bachelors degree, and now, you just can't...";
            string t14 = "You've read on this a ton, don't you have anything to say?";

            string t2 = "Still on this first argument, but now you've got it going.";
            string t21 = "Look at you typing now! Are you sure this is all good?";
            string t22 = "Oh, I wouldn't phrase it like this...";
            string t23 = "Have you eaten? ooh, grab a bite!";
            string t24 = "That's a load of bullshit you're writing there. You should start this part again.";

            string t3 = "All is said and done. You should do a mini-conclusion here.";
            string t31 = "It's just a single paragraph... What, are you too tired?";
            string t32 = "Is this really what you said?";
            string t33 = "It feels like you could've read a bit more before writing.";
            string t34 = "Time to fact check this info real quick, just in case...";

            string t4 = "Time to finish up. Correct these typos.";
            string t41 = "You're, your, yuor...";
            string t42 = "That sentence... really makes no sense.";
            string t43 = "Are you even a masters degree student? What's with this language?";
            string t44 = "[insert corrector app] has crashed! Send an error report?";

            string[][] lines = new string[][]
            {
                new string[] { t1, t11, t12, t13, t14 },
                new string[] { t2, t21, t22, t23, t24 },
                new string[] { t3, t31, t32, t33, t34 },
                new string[] { t4, t41, t42, t43, t44 }
            };
            Enemy boss31 = new Enemy(hp, ad, lines, itr, ith);
            return boss31;
        }
        // Boss 3-2 is argument 2
        public static Enemy Boss32()
        {
            int hp = 650;
            int ad = new Random().Next(2, 8);

            float itr = 100f;
            int ith = 16;

            string t1 = "Chapter 2 now! This should be your last argument.";
            string t11 = "Your worst enemy once again appears: the blank page!";
            string t12 = "Maybe you should just write something and come back to it later.";
            string t13 = "Why must you go though this all the time?";
            string t14 = "You'd think you'd be better at writing words as time goes by...";

            string t2 = "Now you're all setup. The rest *should* be a breeze!";
            string t21 = "Shouldn't this go in the first argument? It feels like it should...";
            string t22 = "That whole section needs more precision. It feels like you havn't read enough.";
            string t23 = "Something feels off... Start over?";
            string t24 = "You feel like you really shouldn't have gone for a masters degree...";

            string t3 = "Time to conclude the second part.";
            string t31 = "Get your thoughts together, this should be easy.";
            string t32 = "Is this section really different than the first one?";
            string t33 = "It feels like this whole section is pointless.";
            string t34 = "Maybe take a break? I don't know.";

            string t4 = "Revision, revision, revision...";
            string t41 = "Look how many mistakes you've made.";
            string t42 = "This should be something you should've mastered in fifth grade.";
            string t43 = "Corrector shows 30 errors... in 6 pages...";
            string t44 = "This sentence is missing words, again!";

            string[][] lines = new string[][]
            {
                new string[] { t1, t11, t12, t13, t14 },
                new string[] { t2, t21, t22, t23, t24 },
                new string[] { t3, t31, t32, t33, t34 },
                new string[] { t4, t41, t42, t43, t44 }
            };
            Enemy boss32 = new Enemy(hp, ad, lines, itr, ith);
            return boss32;
        }
        // Boss 3-3 is intro, conclu and finishing up
        public static Enemy Boss33()
        {
            int hp = 750;
            int ad = new Random().Next(2, 9);

            float itr = 100f;
            int ith = 18;

            string t1 = "On to the introduction of your project!";
            string t11 = "How do you back to the introduction now?";
            string t12 = "It feels like I should've started here.";
            string t13 = "That thesis is all wrong.";
            string t14 = "What even is a problem statement...";

            string t2 = "Now for the conclusion. The end is near.";
            string t21 = "This should be the easiest part. Just type it.";
            string t22 = "I almost don't want this to be done.";
            string t23 = "What am I really bringing to the table here?";
            string t24 = "I should just rush this part... No one will notice.";

            string t3 = "Spell checking. Let's check the whole document, just to make sure everything is in order.";
            string t31 = "Spell checking again...";
            string t32 = "Mistakes in the sections I've already corrected? How do new ones keep poping up?";
            string t33 = "All these sentences are starting to blend in together.";
            string t34 = "You've used the same words how many time in the past 4 lines? 5?";

            string t4 = "Time to put the layout in place.";
            string t41 = "Just going to change the font aaaand... everything is out of place.";
            string t42 = "Why did you type in 3 different font sizes?";
            string t43 = "Those footnotes are horrible. One is completely missing.";
            string t44 = "What name are you going to give to this paper? It should be obvious but...";

            string[][] lines = new string[][]
            {
                new string[] { t1, t11, t12, t13, t14 },
                new string[] { t2, t21, t22, t23, t24 },
                new string[] { t3, t31, t32, t33, t34 },
                new string[] { t4, t41, t42, t43, t44 }
            };
            Enemy boss33 = new Enemy(hp, ad, lines, itr, ith);
            return boss33;
        }

        // Boss 4 is the defense of project
        public static Enemy Boss4()
        {
            int hp = 900;
            int ad = new Random().Next(4, 9);

            float itr = 100f;
            int ith = 20;

            string t1 = "This is really the last stretch. You've got this!";
            string t11 = "How do you even prepare for this?";
            string t12 = "Should you dress in something... I don't know... official?";
            string t13 = "What are they going to say? This is stressful";
            string t14 = "So they can have you start over again? You really don't want to go through this again.";

            string t2 = "This is far from perfect, but what did you expect? Everything right the first try? You'll get it right in the actual thesis!";
            string t21 = "Lot's and lot's of criticism. Did they even like it?";
            string t22 = "You're going to fail aren't you?";
            string t23 = "This is going horribly.";
            string t24 = "They can't even agree on their criticism.";

            string t3 = "You won't be able to reuse this unless you work on it a bit more.";
            string t31 = "How many comments are on this paper? Did they really hate it that much?";
            string t32 = "Will you be able to reuse any of this?";
            string t33 = "I am not starting this over again.";
            string t34 = "This comment doesn't feel fair at all... Is the professor projecting or something?";

            string t4 = "You've put something out in the world. Criticism is part of the experience.";
            string t41 = "They say you defend it, but you're really just sitting there, taking the criticism in.";
            string t42 = "Can't they just tell if they liked it or not? Why keep the suspense going?";
            string t43 = "Almost... there...";
            string t44 = "It feels like they want you to do their thing.";

            string[][] lines = new string[][]
            {
                new string[] { t1, t11, t12, t13, t14 },
                new string[] { t2, t21, t22, t23, t24 },
                new string[] { t3, t31, t32, t33, t34 },
                new string[] { t4, t41, t42, t43, t44 }
            };
            Enemy boss4 = new Enemy(hp, ad, lines, itr, ith);
            return boss4;
        }
        
        public static void InsightEffect(int chap, Character c, Enemy e)
        {
            switch (chap)
            {
                case 1: // Increases insight by 50%
                    Console.WriteLine("With your subject in mind, your insight has increased");
                    c.insight += (c.insight / 2);
                    break;

                case 2: // Restores WP by 20%
                    Console.WriteLine("Now that you made time and are motivated, you gain a boost in will");
                    c.currentWP += (c.totalWP / 5);
                    if (c.currentWP > c.totalWP)
                        c.currentWP = c.totalWP;
                    break;

                case 3: // Skip first phase of the boss fight (25% health damage at the start of battle)
                    Console.WriteLine("You are insightful enough to start writing right away");
                    e.bossHp -= (e.bossTotalHp / 4);
                    break;

                case 4: // Skip first phase of the boss fight (25% health damage at the start of battle)
                    Console.WriteLine("You are insightful enough to start writing right away");
                    e.bossHp -= (e.bossTotalHp / 4);
                    break;

                case 5: // Skip first phase of the boss fight (25% health damage at the start of battle)
                    Console.WriteLine("You are insightful enough to start writing right away");
                    e.bossHp -= (e.bossTotalHp / 4);
                    break;

                case 6: // Increases knowledge by 20%
                    Console.WriteLine("Your insight garantees you'll have all the right answers. Your knowledge is increased.");
                    c.knowledge += (c.knowledge / 5);
                    break;
            }
            
        }

        public static bool InsightCheck(int chap, Character c, Enemy e)
        {
            bool success = false;
            if (c.insight >= e.insightThreshold)
            {
                InsightEffect(chap, c, e);
                success = true;
            }
            return success;
        }
        
    }
}

Then I have Story for my story elements:

using System;

namespace My_first_game
{
    // This class contains all the story bits
    class Story
    {
        public static int chapter = 1;

        // the first thing you see, not a part of the actual game
        public static void Intro()
        {
            Console.WriteLine("Welcome to this game.");
            Console.WriteLine("You will play a character trying to complete his thesis draft.");
            Console.WriteLine("Let's start by creating your character.");
            Console.WriteLine(Program.line + "\n");
        }
        // reminds the player what story beats he needs to do
        public static void Reminder()
        {
            switch (chapter)
            {
                case 1:
                    Console.WriteLine("You still need to chose your subject before anything else. Maybe get on that?");
                    break;
                case 2:
                    Console.WriteLine("Between 2 500 and 3 000 pages to read? Better be ready for it!");
                    break;
                case 3:
                    Console.WriteLine("This is it! You know your stuff, you just need to write it down.");
                    break;
                case 4:
                    Console.WriteLine("You've written a lot, but there is still more to go.");
                    break;
                case 5:
                    Console.WriteLine("Almost finished. This is the last stretch!");
                    break;
                case 6:
                    Console.WriteLine("WHAT? You need to defend this thing? Okay, better be prepared.");
                    break;
            }
        }

        public static void NoShow(Character p, int willHit)
        {
            Console.WriteLine("You decided not to go, but you regret it.");
            Console.WriteLine("The hit on your will was pretty big.");
            Character.TakeDamage((willHit), p);
            Program.StartNewDay();
        }

        public static void Work(Character p)
        {
            int willHit = 10;
            int insIncrease = 1;
            Console.WriteLine("It is wednesday my dudes.");
            Console.WriteLine("Time to go to work.");
            Console.WriteLine("Once you come back, you are too exhausted to get back to your project.");
            Console.WriteLine("At least, you've made enough money to survive another week.");
            Console.WriteLine("(Who said this game was realistic?)");
            Console.WriteLine("Your will has taken a hit, but your determination has increased");

            Character.TakeDamage(willHit, p);
            p.insight += insIncrease;
        }

        public static void PartyInvite(Character p)
        {
            bool isValid;
            int detIncrease = 3;
            int willHit = 5;

            Console.WriteLine("Today, your friends invited you over for a party.");
            Console.WriteLine("This might be a great way to unwind.");
            
            do // as long as the player doesn't input a valid string
            {
                Console.WriteLine("Would you like to go? (Y)es or (N)o?");
                string choice = Console.ReadLine();

                if (choice == "Y" || choice == "y")
                {
                    Console.WriteLine("You had a great time in the party!");
                    Console.WriteLine("Unfortunately, you weren't able to put in meaningful work.");
                    Console.WriteLine("Your determination has increased!");
                    Console.WriteLine("... but your will has taken a hit");

                    p.determination += detIncrease;
                    Character.TakeDamage(willHit, p);

                    Console.WriteLine("Press enter to continue.");
                    Console.ReadLine();
                    isValid = true;
                }
                else if (choice == "N" || choice == "n")
                {
                    NoShow(p, (willHit * 2));
                    isValid = true;
                }
                else
                {
                    Console.WriteLine("Your answer did not register.");
                    isValid = false;
                }
            } while (!isValid);
        }
        public static void DineAtParents(Character p)
        {
            bool isValid;
            int detDecrease = 1;
            int insIncrease = 1;
            int knowIncrease = 1;
            int willHit = 5;

            Console.WriteLine("Your parents invited you to your weekly diner.");
            Console.WriteLine("They'll want to know how you're progressing.");

            do // as long as the player doesn't input a valid string
            {
                Console.WriteLine("Would you like to go? (Y)es or (N)o?");
                string choice = Console.ReadLine();

                if (choice == "Y" || choice == "y")
                {
                    Console.WriteLine("The food was good (and free) but the questions were hard.");
                    Console.WriteLine("It feels like you haven't made discernable progress in your project.");
                    Console.WriteLine("Maybe you don't have anything to report...");
                    Console.WriteLine("Your will was replenished, your insight increased, as did your knowledge. But your determination has decreased.");

                    p.determination -= detDecrease;
                    p.totalWP = Character.CalculateTotalWP(p.determination);
                    p.currentWP = p.totalWP;
                    p.insight += insIncrease;
                    p.knowledge += knowIncrease;

                    Console.WriteLine("Press enter to continue.");
                    Console.ReadLine();
                    isValid = true;
                }
                else if (choice == "N" || choice == "n")
                {
                    NoShow(p, (willHit * 2));
                    isValid = true;
                }
                else
                {
                    Console.WriteLine("Your answer did not register.");
                    isValid = false;
                }
            } while (!isValid);
        }

        public static int Trip(Character p)
        {
            bool isValid;
            int daysLost = 3;
            int detIncrease = 2;
            int insIncrease = 2;
            int knowIncrease = 2;
            int willHit = 15;

            Console.WriteLine("Your friends invite you over for a road trip, lasting {0} days.", daysLost);
            Console.WriteLine("You really could use those days off...");
            
            do // as long as the player doesn't input a valid string
            {
                Console.WriteLine("Would you like to go? (Y)es or (N)o?");
                string choice = Console.ReadLine();

                if (choice == "Y" || choice == "y")
                {
                    Console.WriteLine("You had a great time with your friends!");
                    Console.WriteLine("You had time to discuss about various subjects, some of wich might pertain to your project.");
                    Console.WriteLine("Not only did you learn a lot in your trip, but you feel refreshed");

                    p.determination += detIncrease;
                    p.insight += insIncrease;
                    p.knowledge += knowIncrease;
                    p.currentWP = Character.CalculateTotalWP(p.determination);

                    Console.WriteLine("Press enter to continue.");
                    Console.ReadLine();
                    isValid = true;
                }
                else if (choice == "N" || choice == "n")
                {
                    NoShow(p, willHit);
                    Console.WriteLine("Seriously, you should've gone.");
                    daysLost = 1;
                    isValid = true;
                }
                else
                {
                    Console.WriteLine("Your answer did not register.");
                    isValid = false;
                }
            } while (!isValid);
            return daysLost;
        }

        // lose state, will exit the game.
        // Considering not ending the game and putting back player in day to day with 1 WP. It would be more modern game design
        public static void GameOver(Character c)
        {
            Console.WriteLine("\n\n{0} has lost his will to complete his draft. Try again!", c.name);
            Console.WriteLine("Press enter to close the game!");
            Console.ReadKey();
            Environment.Exit(0);
        }
        // win state will exit the game
        public static void Win(Character c)
        {
            Console.WriteLine("{0} has officialy finished his project!", c.name);
            Console.WriteLine("Congratulations on finishing this simple game. I hope you enjoyed it.");
            Console.WriteLine("A sequel should be coming quote-unquote soon!");
            Console.WriteLine("Press enter to close the game!");
            Console.ReadKey();
            Environment.Exit(0);
        }
    }
    
}

Next comes Character for handling the player character:

using System;

namespace My_first_game
{
    // This class handles creating and managing the character.
    class Character
    {
        public string name;
        public int determination; // same as vitality
        public int knowledge; // same as strength
        public int insight; // same as intelligence
        public int currentWP; // WP is like HP
        public int totalWP;
        private static int baseStats = 5; // For balancing stats applies to all of them

        // constructor
        public Character(string nam, int det, int know, int ins)
        {
            name = nam;
            determination = det;
            knowledge = know;
            insight = ins;
            totalWP = CalculateTotalWP(determination);
            currentWP = totalWP;
        }

        // puts the user in charge of creating the character using dicerolls
        public static Character GenerateCharacter()
        {
            Console.WriteLine("To create a character, enter a name:");
            string name = Console.ReadLine();

            Console.WriteLine("\nNow, let's take care of the stats.\n");

            Console.WriteLine("The first stat we need to check is determination.");
            Console.WriteLine("This will determine how much will {0} has (think of it like HP).", name);
            Console.WriteLine("Roll the dice 2 times:");
            int det = Program.DiceRoll() + Program.DiceRoll() + baseStats; // between 7 and 17
            Console.WriteLine("{0}s determination is {1}\n", name, det);

            Console.WriteLine("Next, let's see how knowledgeable your character is.");
            Console.WriteLine("{0}s knowledge will determine how hard the problems will be tackled.", name);
            Console.WriteLine("Roll the dice once");
            int know = Program.DiceRoll() + baseStats; // between 6 and 11
            Console.WriteLine("{0}s knowledge is {1}\n", name, know);


            Console.WriteLine("Finally, we need to determine how insightful your character is.");
            Console.WriteLine("{0}s insight will give bonuses during fights and determine the number of times you can heal in a fight.", name);
            Console.WriteLine("Roll the dice once:");
            int ins = Program.DiceRoll() + baseStats; // between 6 and 11
            Console.WriteLine("{0}s insight is {1}\n", name, ins);

            Character player = new Character(name, det, know, ins);
            ShowStats(player);
            Console.WriteLine("\nPress enter to continue");
            Console.ReadLine();
            return player;
        }

        // Handles the calculations to dertermine the total WP, needs to be updatable
        public static int CalculateTotalWP(int det)
        {
            int minimumWP = 10;
            int result = minimumWP + (det*2); // so initial total wp is from 24 to 44
            return result;
        }

        // Handles the balance for the number of heals the player gets
        public static int CalculateNumberOfHeals(int ins)
        {
            int numHeals = ins / 3;
            return numHeals;
        }

        // Is in charge of showing the players stats
        public static void ShowStats(Character c)
        {
            c.totalWP = CalculateTotalWP(c.determination);
            Console.WriteLine(" ".PadRight(Console.BufferWidth - 2) + "\n" + Program.line);
            Console.WriteLine("Name: {0}", c.name);
            Console.WriteLine("Determination: {0}", c.determination);
            Console.WriteLine("Knowledge: {0}", c.knowledge);
            Console.WriteLine("Insight: {0}", c.insight);
            Console.WriteLine("WP: {0}/{1}", c.currentWP, c.totalWP);
            Console.WriteLine(Program.line);
        }

        // Handles when the character is hurt, either by boss or story beats
        public static void TakeDamage(int amount, Character c)
        {
            if (amount >= c.currentWP) // check to see if he dies
            {
                Console.WriteLine("\n{0} took {1} damage to will.", c.name, amount);
                c.currentWP = 0;
                Story.GameOver(c);
            }
            else
            {
                c.currentWP -= amount;
                Console.WriteLine("\n{0} took {1} damage to will.", c.name, amount);
                Console.WriteLine("{0} has {1} will point remaining", c.name, c.currentWP);
            }
        }
        // The amount that is healed in battle is calculated in BattleSystem
        public static void Heal(int amount, Character c)
        {
            if (amount >= (c.totalWP - c.currentWP))
            {
                Console.WriteLine("{0} healed by {1}.", c.name, (c.totalWP - c.currentWP));
                c.currentWP = c.totalWP;
            }
            else
            {
                c.currentWP += amount;
                Console.WriteLine("{0} healed by {1}.", c.name, amount);
            }
            
            Console.WriteLine("{0} currently has {1} out of {2} will points", c.name, c.currentWP, c.totalWP);
        }

        //When the character attacks
        public static int DealDamage(Character c)
        {
            int roll = Program.DiceRoll();
            float damageModifier = 1.5f;
            int damage = Convert.ToInt32((c.knowledge + roll) * damageModifier);
            Console.WriteLine("{0} hit for {1}", c.name, damage);
            return damage;
        }

        // The next methods handle the day to day activities. They help boost the characters stats
        public static void HangoutFriends(Character c)
        {
            Console.WriteLine(" ".PadRight(Console.BufferWidth - 2) + "\n{0} chose to hangout with some friends.", c.name);
            Console.WriteLine("{0} is having a wonderful time.", c.name);
            Console.WriteLine("{0} even picked up on something while discussing the subject with them.", c.name);
            Console.WriteLine("{0}s insight has improved, things might get a bit easier.", c.name);
            Console.WriteLine("{0} is reminded that although you wish it could always be that simple, life isn't like this.", c.name);
            c.insight += 1;
            TakeDamage(5, c);
            Console.WriteLine("\nPress enter to continue");
            Console.ReadLine();
        }
        public static void Study(Character c)
        {
            Console.WriteLine(" ".PadRight(Console.BufferWidth - 2) + "\n{0} chose to stay in and study.".PadRight(Console.BufferWidth - 2), c.name);
            Console.WriteLine("{0} reads interesting material on the subject.", c.name);
            Console.WriteLine("{0}s knowledge has improved, {0} will fare better in the coming steps.", c.name);
            c.knowledge += 1;
            Console.WriteLine("\nPress enter to continue");
            Console.ReadLine();
        }
        public static void PlayGames(Character c)
        {
            Console.WriteLine(" ".PadRight(Console.BufferWidth - 2) + "\n{0} spent the day playing video games.".PadRight(Console.BufferWidth - 2), c.name);
            Console.WriteLine("{0} feels pretty bad about it, but it did make for some relaxing time.", c.name);
            Console.WriteLine("{0} feels revitalised, {0}s will was restored", c.name);
            c.currentWP = c.totalWP;
            Console.WriteLine("\nPress enter to continue");
            Console.ReadLine();
        }
            
    }
}

And finally, my Program:

using System;

namespace My_first_game
{
    class Program
    {
        static Character playerChar;
        public static string line = "---------------------------";

        static void Main(string[] args)
        {
            Story.Intro();
            playerChar = Character.GenerateCharacter();

            int i = 1;
            do
            {
                switch (i) // isn't sexy, but it helps in case I want to add story beats to specific days
                {
                    case 1:
                        DawnOfDay(playerChar, 0, i);
                        StartNewDay();
                        i++;
                        break;
                    case 2:
                        DawnOfDay(playerChar, 0, i);
                        StartNewDay();
                        i++;
                        break;
                    case 3:
                        DawnOfDay(playerChar, 0, i);
                        Story.Work(playerChar);
                        i++;
                        break;
                    case 4:
                        DawnOfDay(playerChar, 0, i);
                        Story.PartyInvite(playerChar);
                        i++;
                        break;
                    case 5:
                        DawnOfDay(playerChar, 0, i);
                        StartNewDay();
                        i++;
                        break;
                    case 6:
                        DawnOfDay(playerChar, 0, i);
                        StartNewDay();
                        i++;
                        break;
                    case 7:
                        DawnOfDay(playerChar, 0, i);
                        Story.DineAtParents(playerChar);
                        i++;
                        break;
                    case 8:
                        DawnOfDay(playerChar, 0, i);
                        StartNewDay();
                        i++;
                        break;
                    case 9:
                        DawnOfDay(playerChar, 1, i);
                        Story.PartyInvite(playerChar);
                        i++;
                        break;
                    case 10:
                        DawnOfDay(playerChar, 1, i);
                        Story.Work(playerChar);
                        i++;
                        break;
                    case 11:
                        DawnOfDay(playerChar, 1, i);
                        StartNewDay();
                        i++;
                        break;
                    case 12:
                        DawnOfDay(playerChar, 1, i);
                        StartNewDay();
                        i++;
                        break;
                    case 13:
                        DawnOfDay(playerChar, 1, i);
                        Story.PartyInvite(playerChar);
                        i++;
                        break;
                    case 14:
                        DawnOfDay(playerChar, 1, i);
                        Story.DineAtParents(playerChar);
                        i++;
                        break;
                    case 15:
                        DawnOfDay(playerChar, 1, i);
                        StartNewDay();
                        i++;
                        break;
                    case 16:
                        DawnOfDay(playerChar, 1, i);
                        StartNewDay();
                        i++;
                        break;
                    case 17:
                        DawnOfDay(playerChar, 2, i);
                        Story.Work(playerChar);
                        i++;
                        break;
                    case 18:
                        DawnOfDay(playerChar, 2, i);
                        StartNewDay();
                        i++;
                        break;
                    case 19:
                        DawnOfDay(playerChar, 2, i);
                        StartNewDay();
                        i++;
                        break;
                    case 20:
                        DawnOfDay(playerChar, 2, i);
                        StartNewDay();
                        i++;
                        break;
                    case 21:
                        DawnOfDay(playerChar, 2, i);
                        Story.DineAtParents(playerChar);
                        i++;
                        break;
                    case 22:
                        DawnOfDay(playerChar, 2, i);
                        StartNewDay();
                        i++;
                        break;
                    case 23:
                        DawnOfDay(playerChar, 2, i);
                        StartNewDay();
                        i++;
                        break;
                    case 24:
                        DawnOfDay(playerChar, 2, i);
                        Story.Work(playerChar);
                        i++;
                        break;
                    case 25:
                        DawnOfDay(playerChar, 3, i);
                        i += Story.Trip(playerChar);
                        break;
                    case 26:
                        DawnOfDay(playerChar, 3, i);
                        Story.PartyInvite(playerChar);
                        i++;
                        break;
                    case 27:
                        DawnOfDay(playerChar, 3, i);
                        StartNewDay();
                        i++;
                        break;
                    case 28:
                        DawnOfDay(playerChar, 3, i);
                        Story.DineAtParents(playerChar);
                        i++;
                        break;
                    case 29:
                        DawnOfDay(playerChar, 3, i);
                        StartNewDay();
                        i++;
                        break;
                    case 30:
                        DawnOfDay(playerChar, 3, i);
                        StartNewDay();
                        i++;
                        break;
                    case 31:
                        DawnOfDay(playerChar, 3, i);
                        Story.Work(playerChar);
                        i++;
                        break;
                    case 32:
                        DawnOfDay(playerChar, 3, i);
                        StartNewDay();
                        i++;
                        break;
                    case 33:
                        DawnOfDay(playerChar, 4, i);
                        StartNewDay();
                        i++;
                        break;
                    case 34:
                        DawnOfDay(playerChar, 4, i);
                        StartNewDay();
                        i++;
                        break;
                    case 35:
                        DawnOfDay(playerChar, 4, i);
                        Story.DineAtParents(playerChar);
                        i++;
                        break;
                    case 36:
                        DawnOfDay(playerChar, 4, i);
                        Story.PartyInvite(playerChar);
                        i++;
                        break;
                    case 37:
                        DawnOfDay(playerChar, 4, i);
                        StartNewDay();
                        i++;
                        break;
                    case 38:
                        DawnOfDay(playerChar, 4, i);
                        Story.Work(playerChar);
                        i++;
                        break;
                    case 39:
                        DawnOfDay(playerChar, 4, i);
                        StartNewDay();
                        i++;
                        break;
                    case 40:
                        DawnOfDay(playerChar, 4, i);
                        StartNewDay();
                        i++;
                        break;
                    case 41:
                        DawnOfDay(playerChar, 5, i);
                        Story.PartyInvite(playerChar);
                        i++;
                        break;
                    case 42:
                        DawnOfDay(playerChar, 5, i);
                        Story.DineAtParents(playerChar);
                        i++;
                        break;
                    case 43:
                        DawnOfDay(playerChar, 5, i);
                        StartNewDay();
                        i++;
                        break;
                    case 44:
                        DawnOfDay(playerChar, 5, i);
                        StartNewDay();
                        i++;
                        break;
                    case 45:
                        DawnOfDay(playerChar, 5, i);
                        Story.Work(playerChar);
                        i++;
                        break;
                    case 46:
                        DawnOfDay(playerChar, 5, i);
                        Story.PartyInvite(playerChar);
                        i++;
                        break;
                    case 47:
                        DawnOfDay(playerChar, 5, i);
                        StartNewDay();
                        i++;
                        break;
                    case 48:
                        DawnOfDay(playerChar, 5, i);
                        StartNewDay();
                        i++;
                        break;
                    case 49:
                        DawnOfDay(playerChar, 5, i);
                        Story.DineAtParents(playerChar);
                        i++;
                        break;
                    case 50:
                        DawnOfDay(playerChar, 5, i);
                        StartNewDay();
                        i++;
                        break;
                }
            } while (i < 51);

            // To stop the app from closing
            Console.ReadKey();
        }            
        
        // decides a number for RNG
        public static int DiceRoll()
        {
            Console.WriteLine("Press enter to roll the dice");
            Console.ReadLine();
            int result = new Random().Next(1, 7);
            Console.SetCursorPosition(0, Console.CursorTop - 1);
            Console.WriteLine("You rolled a {0}", result);
            return result;
        }

        public static void DawnOfDay(Character p, int expectedChapter, int day)
        {
            Console.Clear();
            Console.WriteLine("{0}\nDawn of a new day.", line);
            Console.WriteLine("You are at day {0} out of 50.", day);
            ProgressionCheck(p, expectedChapter);
        }

        // Default day
        public static void StartNewDay()
        {
            bool isValid;
            int choice;
            Story.Reminder();

            Console.WriteLine("Chose your next move carefully");
            Console.WriteLine("You have four choices:");

            Console.WriteLine("1. Hangout with friends (improves insight but lowers will)");
            Console.WriteLine("2. Study, study, study... (improves knowledge)");
            Console.WriteLine("3. Play video games (restores will)");
            Console.WriteLine("4. Work on your project (advances the story and improves determination)");

            do // as long as the player doesn't input a valid string
            {
                Console.WriteLine("Enter the corresponding number and press enter (or press s to see your stats)");

                string input = Console.ReadLine();
                bool isInt = int.TryParse(input, out choice);
                Console.SetCursorPosition(0, (Console.CursorTop - 1));

                if (input == "s")
                {
                    Character.ShowStats(playerChar);
                    isValid = false;
                }
                else if (!isInt || choice < 1 || choice > 4)
                {
                    isValid = false;
                    Console.WriteLine("Your input is incorrect, try again.");
                    Console.SetCursorPosition(0, (Console.CursorTop - 2));
                }
                else
                {
                    isValid = true;
                }
            } while (!isValid);

            switch (choice)
            {
                case 1:
                    Character.HangoutFriends(playerChar);
                    break;
                case 2:
                    Character.Study(playerChar);
                    break;
                case 3:
                    Character.PlayGames(playerChar);
                    break;
                case 4:
                    Console.WriteLine("Let's see if you're ready!");
                    playerChar.determination += 1;
                    playerChar.totalWP = Character.CalculateTotalWP(playerChar.determination);
                    Console.WriteLine("\nPress enter to continue");
                    Console.ReadLine();
                    BattleSystem.Battle(playerChar);
                    break;
            }
            
        }

        public static void ProgressionCheck (Character p, int expectedChapter)
        {
            int willHit = 2;
            if (Story.chapter < expectedChapter)
            {
                Console.WriteLine("You feel like you've not made significant progress in a while.");
                Console.WriteLine("Your will is slowly waning.");

                p.currentWP -= willHit;
            }
        }
    } 
}
```
\$\endgroup\$
1
  • \$\begingroup\$ Tip: public static readonly string line = new string('-', 27); \$\endgroup\$
    – aepot
    Dec 29, 2020 at 20:35

1 Answer 1

2
\$\begingroup\$

Hey here a few little things I saw. I hope this helps a bit.

  1. Overall comments

A good coding practice is to use Access modfiers class BattleSystem should maybe become public class BattleSystem depends on how you layer your projects what access modifier to use https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers.

A code convention is to start your property with a capital letter if it's public in your class enemy for example you have public int bossHp; this should be public int BossHp;

  1. class Program

in your main method you do i++ in every switch case, you would be able to put this i++ behind your switch because only one case at a time can be accessed and you want to increment i everytime it seems like.

  1. enemy class
                case 3: // Skip first phase of the boss fight (25% health damage at the start of battle)
                    Console.WriteLine("You are insightful enough to start writing right away");
                    e.bossHp -= (e.bossTotalHp / 4);
                    break;

                case 4: // Skip first phase of the boss fight (25% health damage at the start of battle)
                    Console.WriteLine("You are insightful enough to start writing right away");
                    e.bossHp -= (e.bossTotalHp / 4);
                    break;

                case 5: // Skip first phase of the boss fight (25% health damage at the start of battle)
                    Console.WriteLine("You are insightful enough to start writing right away");
                    e.bossHp -= (e.bossTotalHp / 4);
                    break;

A quick tip when writing code and you see yourself writing 2 times the same exact thing there is probably a better way to write it.

The only thing different above here is the case statements, so you'll have to look for something you can reuse for example you save what you copied pasted in Console.WriteLine() in a string variable above the switch case statment, or you make a method where you print that line and return the boss hp/4. (Just an idea)

I love this site I still use it to this day and I think it will surely help you to write better code: https://refactoring.guru/refactoring

EDIT

Typo I wrote BoosHP should have been BossHP

Styling after 2. the whole text was pasted behind it but there should have been an enter

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.