Defining characters and enemies

In the last chapter, we covered how to use Data Tables to import custom data. Before that, we decided on what stats would play into combat and how. Now we're going to combine those to define our game's characters, classes, and enemy encounters.

Classes

Remember that in Chapter 1, Getting Started with RPG Design in Unreal, we established that our characters have the following stats:

  • Health
  • Max health
  • Magic
  • Max magic
  • Attack power
  • Defense
  • Luck

Of these, we can discard health and magic because they vary during the game, while the other values are predefined based on the character class. The remaining stats are what we will define in the Data Table. As mentioned in Chapter 1, Getting Started with RPG Design in Unreal, we also need to store what the value should be at level 50 (the maximum level). Characters will also have some abilities they start out with, and some they learn as they level up.

We'll define these in the character class spreadsheet, along with the name of the class. So our character class schema will look something like the following:

  • Class name (string)
  • Starting max HP (integer)
  • Max HP at level 50 (integer)
  • Starting max MP (integer)
  • Max MP at level 50 (integer)
  • Starting attack (integer)
  • Attack at level 50 (integer)
  • Starting defense (integer)
  • Defense at level 50 (integer)
  • Starting luck (integer)
  • Luck at level 50 (integer)
  • Starting abilities (string array)
  • Learned abilities (string array)
  • Learned ability levels (integer array)

The ability string arrays will contain the ID of the ability (the value of the reserved name field in UE4). Additionally, there are two separate cells for learned abilities—one that contains the ability IDs, another that contains the levels at which those abilities are learned.

In a production game, one thing you might consider is writing a custom tool to help manage this data and reduce human error. However, writing such a tool is outside the scope of this book.

Now, instead of creating a spreadsheet for this, we're actually going to first create the class and then the Data Table inside Unreal. The reason for this is that at the time of writing, the proper syntax to specify arrays in a cell of a Data Table is not well documented. However, arrays can still be edited from inside the Unreal editor, so we'll simply create the table there and use Unreal's array editor.

Firstly, as usual, create a new class. The class will be used as an object that you can call from, so choose Object as the parent class. Name this class FCharacterClassInfo and, for organization purposes, path your new class to your Source/RPG/Data folder.

Open FCharacterClassInfo.h and replace the class definition with the following code:

USTRUCT( BlueprintType )
struct FCharacterClassInfo : public FTableRowBase
{
  GENERATED_USTRUCT_BODY()

  UPROPERTY( BlueprintReadWrite, EditAnywhere, Category = "ClassInfo" )
    FString Class_Name;

  UPROPERTY( BlueprintReadWrite, EditAnywhere, Category = "ClassInfo" )
    int32 StartMHP;

  UPROPERTY( BlueprintReadWrite, EditAnywhere, Category = "ClassInfo" )
    int32 StartMMP;

  UPROPERTY( BlueprintReadWrite, EditAnywhere, Category = "ClassInfo" )
    int32 StartATK;

  UPROPERTY( BlueprintReadWrite, EditAnywhere, Category = "ClassInfo" )
    int32 StartDEF;

  UPROPERTY( BlueprintReadWrite, EditAnywhere, Category = "ClassInfo" )
    int32 StartLuck;

  UPROPERTY( BlueprintReadWrite, EditAnywhere, Category = "ClassInfo" )
    int32 EndMHP;

  UPROPERTY( BlueprintReadWrite, EditAnywhere, Category = "ClassInfo" )
    int32 EndMMP;

  UPROPERTY( BlueprintReadWrite, EditAnywhere, Category = "ClassInfo" )
    int32 EndATK;

  UPROPERTY( BlueprintReadWrite, EditAnywhere, Category = "ClassInfo" )
    int32 EndDEF;

  UPROPERTY( BlueprintReadWrite, EditAnywhere, Category = "ClassInfo" )
    int32 EndLuck;

  UPROPERTY( BlueprintReadWrite, EditAnywhere, Category = "ClassInfo" )
    TArray<FString> StartingAbilities;

  UPROPERTY( BlueprintReadWrite, EditAnywhere, Category = "ClassInfo" )
    TArray<FString> LearnedAbilities;

  UPROPERTY( BlueprintReadWrite, EditAnywhere, Category = "ClassInfo" )
    TArray<int32> LearnedAbilityLevels;
};

Most of this code should be familiar to you already; however, you may not recognize the last three fields. These are all of the TArray type, which is a dynamic array type provided by Unreal. Essentially, a TArray can have elements dynamically added to it and removed from it, unlike a standard C++ array.

Upon compiling this code, create a new folder called Data within your Content folder so that you can stay organized by keeping Data Tables that you create within the Data folder. Navigate to Content | Data in the Content Browser and create a new Data Table by right-clicking on Content Browser and choosing Miscellaneous | Data Table. Then, select Character Class Info from the drop-down list. Name your Data Table CharacterClasses and then double-click to open it.

To add a new entry, hit the + button. Then, give a name to the new entry by entering something in the Row Name field and pressing Enter.

After an entry has been added, you can select the entry in the Data Table pane and edit its properties in the Row Editor pane.

Let's add a Soldier class to the list. We will it give the name S1 (which we'll use to refer to the character class from other Data Tables) and it will have the following properties:

  • Class Name: Soldier
  • Start MHP: 100
  • Start MMP: 100
  • Start ATK: 5
  • Start DEF: 0
  • Start Luck: 0
  • End MHP: 800
  • End MMP: 500
  • End ATK: 20
  • End DEF: 20
  • End Luck: 10
  • Starting Abilities: (leave empty for now)
  • Learned Abilities: (leave empty for now)
  • Learned Ability Levels: (leave empty for now)

When you are finished, your Data Table should look like this:

Classes

If you have more character classes that you would like to define, continue to add them to your Data Table.

Characters

With classes defined, let's take a look at characters. Since most of the important combat-related data is already defined as part of a character's class, the character itself is going to be quite a bit simpler. In fact, for now, our characters will be defined by just two things: the name of the character and the character's class.

Firstly, create a new C++ class called FCharacterInfo whose parent is Object, and path it to the Source/RPG/Data folder. Now, replace the class definition in FCharacterInfo.h with this:

USTRUCT(BlueprintType)
struct FCharacterInfo : public FTableRowBase
{
  GENERATED_USTRUCT_BODY()

  UPROPERTY( BlueprintReadWrite, EditAnywhere, Category = "CharacterInfo" )
  FString Character_Name;

  UPROPERTY( BlueprintReadOnly, EditAnywhere, Category = "CharacterInfo" )
  FString Class_ID;
};

As we did earlier, we're just defining the two fields for the character (character name and class ID).

After compiling, create a new Data Table in your Data folder that you created earlier from within the Content Browser and select CharacterInfo as the class; call it Characters. Add a new entry with the name S1. You can name this character whatever you like (we named our character soldier Kumo), but for class ID, enter S1 (as this is the name of the Soldier class we defined earlier).

Enemies

As for enemies, rather than defining a separate character and class information, we'll create a simplified combined table for these two pieces of information. An enemy generally does not have to deal with experience and leveling up, so we can omit any data related to this. Additionally, enemies do not consume MP as players do, so we can omit this data as well.

Therefore, our enemy data will have the following properties:

  • Enemy name (string array)
  • MHP (integer)
  • ATK (integer)
  • DEF (integer)
  • Luck (integer)
  • Abilities (string array)

Much like the previous Data Class creations, we create a new C++ class that derives from Object, but this time we will call it FEnemyInfo and place it with the rest of our data in the Source/RPG/Data directory.

At this point, you should have an understanding of how to construct the class for this data, but let's take a look at the struct header anyway. In FEnemyInfo.h, replace your class definition with the following:

USTRUCT( BlueprintType )
struct FEnemyInfo : public FTableRowBase
{
  GENERATED_USTRUCT_BODY()

  UPROPERTY( BlueprintReadWrite, EditAnywhere, Category = "EnemyInfo" )
    FString EnemyName;

  UPROPERTY( BlueprintReadOnly, EditAnywhere, Category = "EnemyInfo" )
    int32 MHP;

  UPROPERTY( BlueprintReadOnly, EditAnywhere, Category = "EnemyInfo" )
    int32 ATK;

  UPROPERTY( BlueprintReadOnly, EditAnywhere, Category = "EnemyInfo" )
    int32 DEF;

  UPROPERTY( BlueprintReadOnly, EditAnywhere, Category = "EnemyInfo" )
    int32 Luck;

  UPROPERTY( BlueprintReadOnly, EditAnywhere, Category = "EnemyInfo" )
    TArray<FString> Abilities;
};

After compiling, create a new Data Table, select EnemyInfo as the class, and call the Data Table Enemies. Add a new entry with the name S1 and the following properties:

  • Enemy Name: Goblin
  • MHP: 20
  • ATK: 5
  • DEF: 0
  • Luck: 0
  • Abilities: (leave empty for now)

At this point, we've got the data for a character, the character's class, and a single enemy for the character to fight. Next, let's start keeping track of which characters are in the active party and what their current stats are.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.101.109