Yeah, you can’t put any of the reflection macros like UPROPERTY within a macro. Unreal Header Tool only parses the exact header files, not the version after macros are expanded.
I see a few potential options.
First is the boilerplate option where you do everything manually. Or at least all the parts that involve reflection.
Second would be fallback to relying on the AnyStatChanged callback.
Third would be to manage the callbacks at runtime instead of compile time. By that I mean you keep some sort of data structure like a TMap or TArray that can associate each stat with a delegate. You’d have to write custom functions for binding & unbinding, but at least you’d only have to write that once and it would support any stat.
I’ll say that in my experience, the third one is usually the solution. Not for any “best practice” reason but because the stats become data driven (through data assets or blueprints) so you can’t rely on a solution that requires compile time setup.