Hi Douglas,
I’ve posted a workable solution(for my project) to this inheritance issue below.
Have a look, it may helps you.
i think in the Merlin/Gandalf example, you should probably combine your spells into a single data table that every character uses. accessing data tables is less high maintenance when data tables are used on categories of things, rather than instances. so its fine to have a datatable of character stats, but you shouldn’t have a specific data table for each character.
so if you have more than one data table that use the same struct, they should probably be combined into the same data table. Merlin can be given an array of names that represents his spell collection, and his spell data can be looked up in the same spell table everyone uses for all spells.
data tables are data oriented, rather than object oriented, so you should not think of data belonging to a specific object, like Merlin, but instead, think of data as belonging to a general functionality, like spell casting.
using data tables this way, allows you to quickly create new characters that combine the spells of Merlin and Gandalf, so you can make a shape shifter like Shang Tsung from Mortal Kombat or Mokujin from Tekken, who can use any move in the game, and you can make custom character editors in your game, which allows you to choose moves from a global list, like the create a skater from tony hawk games.
when you separate data from specific class hierarchies, it gives you alot of freedom and modularity, where any character can perform any move, and any weapon can fire any projectile. if you take it a step further, and stick with data oriented design, Merlin and Gandalf should not even be specific actors or objects, they should just be rows in a character Data Table.
so instead of spawning a Merlin Actor that looks up Merlin_Spells, you should spawn a generic character, and pass it a character name, like Merlin, so on begin play, it can look up a list of available spell names from a CharacterSpells data table, then combine that list with collected spells, by loading a SaveGame.
I see what you mean. Use them more like you would with a real database. A table stores one type of entity and the “hierarchization” of this data comes from the API on top. Following your way, my Spell structure should probably have a Magician key that can be set to Gandalf or Merlin. That would work nicely.
your spell structure should probably only contain data related to each spell, and not contain anything about whether a specific character is allowed to use the spell, because that would be high maintenance, and lower the potential for modularity. to control which spells a character can use, you should use an array of spell names in your base character, which can be loaded from a separate data table.
so a generic character is given the name Merlin. using that name, it looks up a data table called CharacterSpellsTable, where each row has an array of names, and it copies this array into the character’s AvailableSpells. when you use a spell, you get a name from the AvailableSpells, and use it to look up spell data in a separate SpellsTable.
spell data only describes the statistics of a spell.
“who owns which spells” is a separate concept, which is not part of spell data, but instead part of character data or inventory data.
ideally, ownership should be editable at runtime, so designers can add any spell to any character, in game.
if you want to create a new character, which uses only existing spells, it should not require editing the spells data table. if you want to create a new spell, it should not require knowing which characters can exist.
the idea is, that programmers should give designers as much freedom as possible for mixing and matching any character with any spell, and the designers should be the ones who limit the player with rules. if you hard coded which characters are allowed to have which set of spells, you would run into trouble if a designer wanted to make a game mode where everyone gets the same set of spells, or the set of spells changes throughout the game, like Gun Game in Call of Duty.
so programmers should make things generic and flexible, while designers make things specific and challenging. programmers create as many new possibilities as they can, while designers limit these possibilities to create challenges and improve balance.
GetDataTableRow outputs a specific type of struct, so changing the type of DataTable with a variable at runtime, would also change the type of struct it outputs, which would break its connection to the BreakStruct node.
it would be nice if GetDataTableRow just output a blob of Bytes in binary, and we could cast that blob to a specific struct, but structs don’t allow casting or inheritance to make them as light weight as possible.
since UE4 doesn’t have struct inheritance and struct casting, you should design data tables to hold data for categories of generic functionality, rather than specific objects. so you can have a weapons data table, but you shouldn’t have a shotgun data table, shotgun should be just a row, not a table. each type of enemy should not have its own data table, they should each be a row in an Enemies data table.
I actually tried to fix that by branching the engine but the variable output pin was a problem. And like you said you cannot cast structs. Only solution I can see is some more advance logic when processing the input table. A new argument could be used to set the type of struct that that the node will support.
I understand what you mean, but I think that might depends on the actual game needs to. For instance I think in the game I am trying to design, it would actually be more maintenance if I had to manage a list of spells per character. Whereas by having a Magician class key on each Spell, I can set it to be available for Magician, Merlin or Gandalf. In other words, shared by all magicians or specific to one.
“By design” seems like a poor decision on this one. I am using data tables to define dozens of settings for various weapons, and based on player purchase choices, I need to select the correct table. This info now needs to be replicated for every weapon because I can’t promote the get data table input to a variable.
+1
Same thing for me: stuck “by design”! Have to found another way.
why not put every weapon in your game in the same data table?
Nothing is stopping me doing that - but that would mean a data table with well over 200 rows in my case. It’s much easier to split into smaller data sets, not just in BP, but also for the designers working with the data tables.
Being able to specify the data table through through a variable rather than a static value would make the entire process easier for all departments.
I tried to change the source code to remove the literal only restriction. Sadly, I quickly realized why they took that route. Indeed, any other way results in unpredictable output types. Adding the fact that you cannot cast structs, it becomes apparent that they will not be able to address this concern easily.
is it possible to make the struct for this variable? would be nice since i am trying to write a function for datatables that use different structs
One relevant note: If you know which underlying type of data you are going to use for the table, one trick is to drag from “Out Row” and directly break it down using the corresponding type, and the Get Datatable Row would work as expected.
Here “Current Pattern” is a variable holding potentially unknown data table reference, but I am breaking it as SemanticsTable type, and it will compile and work.
Let us just say you are a life saver…
[=“anonymous_user_eacb5f40, post:13, topic:306729”]
UE-11952 has been closed as by design. The reason this is required is that, when reading data table entries, a literal value is required to determine what rows are available to get. Without the literal, this information cannot be determined.
[/]
I know I’m like… 7 years late to this party…
But did you guys not think of slapping on a struct input pin to define the structure of the dynamically assigned datatable and call it a day?.. if they match the struct perfectly then all is good, if not… let them crash and fate sort them out sounds like a very easy solution to a very annoying problem
Gold.
Simply; there is no way to use data table inside data table. For example; Datatables of NPC talks, then choose John’s talk DataTable. There is no way with blueprint.