I think the point was that if you use structs, you can’t store them as pointers (for replication), so it’s not possible to have an array containing different subtypes.
You can just store identifiers for the item type, rather than instantiated items. If you need to have them instantiated with their own subtype-specific data, then what is wrong with having them spawned in the world? A few hidden, non-ticking actors is hardly going to be a performance problem, assuming inventory contents isn’t changing super fast.
You use standard C/C++ casts with pointers to structs. You can’t cast structs by value.
So you can do:
FItemWeapon* weapon = (FItemWeapon*)item;
assuming item is a pointer to FItemBase.
But as I said above, this won’t work for your inventory. TArray< FItemBase* > is no good since pointers to structs are not replicated (at least I’m pretty sure they’re not). If you just had a TArray< FItemBase > then this isn’t polymorphic - all the items have to be of FItemBase, you can’t put a derived type in that array.