Data organization approach

Not sure where else to post this, and it’s not a specific problem per se, but I’ve been struggling with how to organize my game’s data. It’s an open world game with a C++ class to generate the terrain, but everything else is handled in blueprints (with the intent of optimizing into C++ once the dust has settled).

At the moment there are 3 main classes in the game: Items, Environment, and Mobs. Each follows the same general pattern of every item inheriting from the base class with the defaults updated for each variation. From there Actors were largely referred to by their class rather than an actual object reference (I.E. the inventory slot struct says we have 10 sword classes in slot 1, but an actor would only be spawned when the sword is actually equipped) This was working fine for the most part, but the constant changes to underlying structs and variables would inevitably wipe out the updated defaults for every child class and I’d have to go re-enter them, which is only going to get more time consuming as more items are added.

My solution to the instability of structs led me to creating a data table for all of the key information for each item and I created an actor component for each dataset to define the various queries against it, so that now the individual classes are largely empty and only used to differentiate a sword from an axe and all of the actual parameters are pulled from a data table. Again, no issues there, except I’m not sure where to reliably reference this info. I considered referencing the table in each item, but my gut feel at the time was that having all of those individual references would needlessly eat up resources. Instead I decided to add these data components to the Gamestate class, and have each actor send a call there when it needs to know how much damage a sword does, for example. The problem now is that somewhere along the line the references to the data table are occasionally replaced with PLACEHOLDER (I’m fairly positive this is because I’ve been pretty sloppy with validity checks) but I also have the feeling that I’m doing something terribly wrong. The general flow ends up being: Player clicks on UI, UMG sends a call to say button A was clicked to the Player class, Player class decides what action that button denotes (“Use”, let’s say), and then sends a call to the Gamestate class which in turn checks with the data table component to see what happens when we “Use” this particular class. Player takes that information and acts on it. It works when I’m not plagued with PLACEHOLDER, but it feels like a house of cards.

I guess the question is how are others managing a large number of items that aren’t specifically added to the level? I’m managing the loot tables, inventories, and spawns with arrays at the class level rather than the actor level…is this the right approach? Is there a better way?