ue-mcp 0.4.0-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +89 -0
  3. package/dist/bridge.d.ts +25 -0
  4. package/dist/bridge.js +124 -0
  5. package/dist/bridge.js.map +1 -0
  6. package/dist/deployer.d.ts +18 -0
  7. package/dist/deployer.js +175 -0
  8. package/dist/deployer.js.map +1 -0
  9. package/dist/editor-control.d.ts +15 -0
  10. package/dist/editor-control.js +181 -0
  11. package/dist/editor-control.js.map +1 -0
  12. package/dist/github-app.d.ts +4 -0
  13. package/dist/github-app.js +94 -0
  14. package/dist/github-app.js.map +1 -0
  15. package/dist/index.d.ts +2 -0
  16. package/dist/index.js +125 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/init.d.ts +2 -0
  19. package/dist/init.js +290 -0
  20. package/dist/init.js.map +1 -0
  21. package/dist/instructions.d.ts +1 -0
  22. package/dist/instructions.js +150 -0
  23. package/dist/instructions.js.map +1 -0
  24. package/dist/project.d.ts +32 -0
  25. package/dist/project.js +175 -0
  26. package/dist/project.js.map +1 -0
  27. package/dist/tools/animation.d.ts +2 -0
  28. package/dist/tools/animation.js +62 -0
  29. package/dist/tools/animation.js.map +1 -0
  30. package/dist/tools/asset.d.ts +2 -0
  31. package/dist/tools/asset.js +128 -0
  32. package/dist/tools/asset.js.map +1 -0
  33. package/dist/tools/audio.d.ts +2 -0
  34. package/dist/tools/audio.js +24 -0
  35. package/dist/tools/audio.js.map +1 -0
  36. package/dist/tools/blueprint.d.ts +2 -0
  37. package/dist/tools/blueprint.js +64 -0
  38. package/dist/tools/blueprint.js.map +1 -0
  39. package/dist/tools/demo.d.ts +2 -0
  40. package/dist/tools/demo.js +10 -0
  41. package/dist/tools/demo.js.map +1 -0
  42. package/dist/tools/editor.d.ts +2 -0
  43. package/dist/tools/editor.js +133 -0
  44. package/dist/tools/editor.js.map +1 -0
  45. package/dist/tools/feedback.d.ts +2 -0
  46. package/dist/tools/feedback.js +44 -0
  47. package/dist/tools/feedback.js.map +1 -0
  48. package/dist/tools/foliage.d.ts +2 -0
  49. package/dist/tools/foliage.js +29 -0
  50. package/dist/tools/foliage.js.map +1 -0
  51. package/dist/tools/gameplay.d.ts +2 -0
  52. package/dist/tools/gameplay.js +101 -0
  53. package/dist/tools/gameplay.js.map +1 -0
  54. package/dist/tools/gas.d.ts +2 -0
  55. package/dist/tools/gas.js +43 -0
  56. package/dist/tools/gas.js.map +1 -0
  57. package/dist/tools/landscape.d.ts +2 -0
  58. package/dist/tools/landscape.js +32 -0
  59. package/dist/tools/landscape.js.map +1 -0
  60. package/dist/tools/level.d.ts +2 -0
  61. package/dist/tools/level.js +66 -0
  62. package/dist/tools/level.js.map +1 -0
  63. package/dist/tools/material.d.ts +2 -0
  64. package/dist/tools/material.js +59 -0
  65. package/dist/tools/material.js.map +1 -0
  66. package/dist/tools/networking.d.ts +2 -0
  67. package/dist/tools/networking.js +42 -0
  68. package/dist/tools/networking.js.map +1 -0
  69. package/dist/tools/niagara.d.ts +2 -0
  70. package/dist/tools/niagara.js +42 -0
  71. package/dist/tools/niagara.js.map +1 -0
  72. package/dist/tools/pcg.d.ts +2 -0
  73. package/dist/tools/pcg.js +39 -0
  74. package/dist/tools/pcg.js.map +1 -0
  75. package/dist/tools/project.d.ts +2 -0
  76. package/dist/tools/project.js +282 -0
  77. package/dist/tools/project.js.map +1 -0
  78. package/dist/tools/reflection.d.ts +2 -0
  79. package/dist/tools/reflection.js +26 -0
  80. package/dist/tools/reflection.js.map +1 -0
  81. package/dist/tools/widget.d.ts +2 -0
  82. package/dist/tools/widget.js +34 -0
  83. package/dist/tools/widget.js.map +1 -0
  84. package/dist/types.d.ts +21 -0
  85. package/dist/types.js +38 -0
  86. package/dist/types.js.map +1 -0
  87. package/package.json +76 -0
  88. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeServer.cpp +746 -0
  89. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeServer.h +81 -0
  90. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.cpp +49 -0
  91. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.h +37 -0
  92. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerRegistry.cpp +75 -0
  93. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerRegistry.h +50 -0
  94. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.cpp +1418 -0
  95. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.h +43 -0
  96. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.cpp +1773 -0
  97. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.h +48 -0
  98. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers.cpp +289 -0
  99. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers.h +18 -0
  100. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.cpp +1982 -0
  101. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.h +44 -0
  102. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.cpp +1217 -0
  103. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.h +71 -0
  104. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DialogHandlers.cpp +465 -0
  105. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DialogHandlers.h +49 -0
  106. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.cpp +1676 -0
  107. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.h +53 -0
  108. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.cpp +876 -0
  109. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.h +22 -0
  110. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.cpp +2222 -0
  111. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.h +54 -0
  112. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.cpp +783 -0
  113. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.h +24 -0
  114. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.cpp +898 -0
  115. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.h +24 -0
  116. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.cpp +1270 -0
  117. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.h +34 -0
  118. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.cpp +2190 -0
  119. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.h +53 -0
  120. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.cpp +554 -0
  121. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.h +29 -0
  122. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers.cpp +601 -0
  123. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers.h +25 -0
  124. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PCGHandlers.cpp +1024 -0
  125. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PCGHandlers.h +25 -0
  126. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.cpp +370 -0
  127. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.h +19 -0
  128. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ReflectionHandlers.cpp +499 -0
  129. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ReflectionHandlers.h +27 -0
  130. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.cpp +426 -0
  131. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.h +19 -0
  132. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.cpp +303 -0
  133. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.h +18 -0
  134. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.cpp +985 -0
  135. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.h +27 -0
  136. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/JsonSerializer.cpp +181 -0
  137. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/JsonSerializer.h +42 -0
  138. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/UE_MCP_Bridge.cpp +39 -0
  139. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/UE_MCP_BridgeModule.h +14 -0
  140. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/UE_MCP_Bridge.Build.cs +87 -0
  141. package/plugin/ue_mcp_bridge/UE_MCP_Bridge.uplugin +55 -0
@@ -0,0 +1,783 @@
1
+ #include "GasHandlers.h"
2
+ #include "UE_MCP_BridgeModule.h"
3
+ #include "HandlerRegistry.h"
4
+ #include "Kismet2/KismetEditorUtilities.h"
5
+ #include "Engine/Blueprint.h"
6
+ #include "AssetToolsModule.h"
7
+ #include "IAssetTools.h"
8
+ #include "Factories/BlueprintFactory.h"
9
+ #include "UObject/UObjectGlobals.h"
10
+ #include "UObject/Package.h"
11
+ #include "Misc/PackageName.h"
12
+ #include "UObject/SavePackage.h"
13
+ #include "EditorScriptingUtilities/Public/EditorAssetLibrary.h"
14
+ #include "Dom/JsonObject.h"
15
+ #include "Dom/JsonValue.h"
16
+ #include "GameplayTagContainer.h"
17
+ #include "GameplayTagsManager.h"
18
+ #include "Kismet2/BlueprintEditorUtils.h"
19
+ #include "Engine/SimpleConstructionScript.h"
20
+ #include "Engine/SCS_Node.h"
21
+ #include "EdGraphSchema_K2.h"
22
+
23
+ void FGasHandlers::RegisterHandlers(FMCPHandlerRegistry& Registry)
24
+ {
25
+ Registry.RegisterHandler(TEXT("create_gameplay_effect"), &CreateGameplayEffect);
26
+ Registry.RegisterHandler(TEXT("get_gas_info"), &GetGasInfo);
27
+ Registry.RegisterHandler(TEXT("create_gameplay_ability"), &CreateGameplayAbility);
28
+ Registry.RegisterHandler(TEXT("create_attribute_set"), &CreateAttributeSet);
29
+ Registry.RegisterHandler(TEXT("create_gameplay_cue"), &CreateGameplayCue);
30
+ Registry.RegisterHandler(TEXT("add_ability_tag"), &AddAbilityTag);
31
+ Registry.RegisterHandler(TEXT("create_gameplay_cue_notify"), &CreateGameplayCueNotify);
32
+ Registry.RegisterHandler(TEXT("add_ability_system_component"), &AddAbilitySystemComponent);
33
+ Registry.RegisterHandler(TEXT("add_attribute"), &AddAttribute);
34
+ Registry.RegisterHandler(TEXT("set_ability_tags"), &SetAbilityTags);
35
+ Registry.RegisterHandler(TEXT("set_effect_modifier"), &SetEffectModifier);
36
+ }
37
+
38
+ TSharedPtr<FJsonValue> FGasHandlers::CreateGameplayEffect(const TSharedPtr<FJsonObject>& Params)
39
+ {
40
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
41
+
42
+ FString Name;
43
+ if (!Params->TryGetStringField(TEXT("name"), Name))
44
+ {
45
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'name' parameter"));
46
+ Result->SetBoolField(TEXT("success"), false);
47
+ return MakeShared<FJsonValueObject>(Result);
48
+ }
49
+
50
+ UE_LOG(LogMCPBridge, Log, TEXT("[UE-MCP] CreateGameplayEffect called with name: %s"), *Name);
51
+
52
+ FString PackagePath = TEXT("/Game/GAS/Effects");
53
+ Params->TryGetStringField(TEXT("packagePath"), PackagePath);
54
+
55
+ FString DurationPolicy = TEXT("Instant");
56
+ Params->TryGetStringField(TEXT("durationPolicy"), DurationPolicy);
57
+
58
+ // Find GameplayEffect class
59
+ UClass* GameplayEffectClass = FindObject<UClass>(nullptr, TEXT("/Script/GameplayAbilities.GameplayEffect"));
60
+ if (!GameplayEffectClass)
61
+ {
62
+ Result->SetStringField(TEXT("error"), TEXT("GameplayEffect class not found. Enable GameplayAbilities plugin."));
63
+ Result->SetBoolField(TEXT("success"), false);
64
+ return MakeShared<FJsonValueObject>(Result);
65
+ }
66
+
67
+ // Create blueprint
68
+ FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>(TEXT("AssetTools"));
69
+ IAssetTools& AssetTools = AssetToolsModule.Get();
70
+
71
+ FString PackageName;
72
+ FString AssetName;
73
+ PackagePath.Split(TEXT("/"), &PackageName, &AssetName, ESearchCase::CaseSensitive, ESearchDir::FromEnd);
74
+ if (AssetName.IsEmpty())
75
+ {
76
+ AssetName = Name;
77
+ }
78
+ else
79
+ {
80
+ PackageName = PackagePath;
81
+ AssetName = Name;
82
+ }
83
+ PackageName = PackageName.LeftChop(1); // Remove trailing /
84
+
85
+ // Create asset path
86
+ FString FullAssetPath = PackagePath + TEXT("/") + Name;
87
+
88
+ // Delete existing asset if it exists
89
+ UEditorAssetLibrary::DeleteAsset(FullAssetPath);
90
+
91
+ UBlueprintFactory* BlueprintFactory = NewObject<UBlueprintFactory>();
92
+ UBlueprint* NewBlueprint = Cast<UBlueprint>(AssetTools.CreateAsset(AssetName, PackageName, UBlueprint::StaticClass(), BlueprintFactory));
93
+ if (!NewBlueprint)
94
+ {
95
+ Result->SetStringField(TEXT("error"), TEXT("Failed to create GameplayEffect Blueprint"));
96
+ Result->SetBoolField(TEXT("success"), false);
97
+ return MakeShared<FJsonValueObject>(Result);
98
+ }
99
+
100
+ NewBlueprint->ParentClass = GameplayEffectClass;
101
+ FKismetEditorUtilities::CompileBlueprint(NewBlueprint);
102
+
103
+ // Save asset
104
+ UPackage* Package = NewBlueprint->GetOutermost();
105
+ if (Package)
106
+ {
107
+ Package->MarkPackageDirty();
108
+ FString PackageFileName = FPackageName::LongPackageNameToFilename(Package->GetName(), FPackageName::GetAssetPackageExtension());
109
+ FSavePackageArgs SaveArgs;
110
+ SaveArgs.TopLevelFlags = RF_Standalone;
111
+ UPackage::SavePackage(Package, nullptr, *PackageFileName, SaveArgs);
112
+ }
113
+
114
+ FString AssetPath = NewBlueprint->GetPathName();
115
+ Result->SetStringField(TEXT("path"), AssetPath);
116
+ Result->SetStringField(TEXT("name"), Name);
117
+ Result->SetStringField(TEXT("durationPolicy"), DurationPolicy);
118
+ Result->SetBoolField(TEXT("success"), true);
119
+
120
+ return MakeShared<FJsonValueObject>(Result);
121
+ }
122
+
123
+ TSharedPtr<FJsonValue> FGasHandlers::GetGasInfo(const TSharedPtr<FJsonObject>& Params)
124
+ {
125
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
126
+
127
+ FString BlueprintPath;
128
+ if (!Params->TryGetStringField(TEXT("blueprintPath"), BlueprintPath))
129
+ {
130
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'blueprintPath' parameter"));
131
+ Result->SetBoolField(TEXT("success"), false);
132
+ return MakeShared<FJsonValueObject>(Result);
133
+ }
134
+
135
+ UBlueprint* Blueprint = LoadObject<UBlueprint>(nullptr, *BlueprintPath);
136
+ if (!Blueprint || !Blueprint->GeneratedClass)
137
+ {
138
+ // Return success with empty info rather than crashing
139
+ Result->SetStringField(TEXT("blueprintPath"), BlueprintPath);
140
+ Result->SetBoolField(TEXT("hasGasComponents"), false);
141
+ Result->SetStringField(TEXT("info"), TEXT("Blueprint not found or has no generated class"));
142
+ Result->SetBoolField(TEXT("success"), true);
143
+ return MakeShared<FJsonValueObject>(Result);
144
+ }
145
+
146
+ UObject* CDO = Blueprint->GeneratedClass->GetDefaultObject();
147
+ if (!CDO)
148
+ {
149
+ Result->SetStringField(TEXT("blueprintPath"), BlueprintPath);
150
+ Result->SetBoolField(TEXT("hasGasComponents"), false);
151
+ Result->SetStringField(TEXT("info"), TEXT("No CDO available"));
152
+ Result->SetBoolField(TEXT("success"), true);
153
+ return MakeShared<FJsonValueObject>(Result);
154
+ }
155
+
156
+ Result->SetStringField(TEXT("blueprintPath"), BlueprintPath);
157
+ Result->SetStringField(TEXT("className"), Blueprint->GeneratedClass->GetName());
158
+ Result->SetStringField(TEXT("parentClass"), Blueprint->ParentClass ? Blueprint->ParentClass->GetName() : TEXT("None"));
159
+
160
+ // Check for GAS-related components
161
+ bool bHasGasComponents = false;
162
+ TArray<TSharedPtr<FJsonValue>> ComponentArray;
163
+
164
+ // Check if the class has an AbilitySystemComponent
165
+ UClass* ASCClass = FindObject<UClass>(nullptr, TEXT("/Script/GameplayAbilities.AbilitySystemComponent"));
166
+ if (ASCClass && CDO->IsA(AActor::StaticClass()))
167
+ {
168
+ AActor* ActorCDO = Cast<AActor>(CDO);
169
+ if (ActorCDO)
170
+ {
171
+ TArray<UActorComponent*> Components;
172
+ ActorCDO->GetComponents(Components);
173
+ for (UActorComponent* Comp : Components)
174
+ {
175
+ if (Comp && Comp->IsA(ASCClass))
176
+ {
177
+ bHasGasComponents = true;
178
+ TSharedPtr<FJsonObject> CompObj = MakeShared<FJsonObject>();
179
+ CompObj->SetStringField(TEXT("name"), Comp->GetName());
180
+ CompObj->SetStringField(TEXT("class"), Comp->GetClass()->GetName());
181
+ ComponentArray.Add(MakeShared<FJsonValueObject>(CompObj));
182
+ }
183
+ }
184
+ }
185
+ }
186
+
187
+ Result->SetBoolField(TEXT("hasGasComponents"), bHasGasComponents);
188
+ Result->SetArrayField(TEXT("gasComponents"), ComponentArray);
189
+
190
+ // Check if this is a GameplayEffect subclass
191
+ UClass* GEClass = FindObject<UClass>(nullptr, TEXT("/Script/GameplayAbilities.GameplayEffect"));
192
+ Result->SetBoolField(TEXT("isGameplayEffect"), GEClass && Blueprint->GeneratedClass->IsChildOf(GEClass));
193
+
194
+ // Check if this is a GameplayAbility subclass
195
+ UClass* GAClass = FindObject<UClass>(nullptr, TEXT("/Script/GameplayAbilities.GameplayAbility"));
196
+ Result->SetBoolField(TEXT("isGameplayAbility"), GAClass && Blueprint->GeneratedClass->IsChildOf(GAClass));
197
+
198
+ // Check if this is an AttributeSet subclass
199
+ UClass* AttrSetClass = FindObject<UClass>(nullptr, TEXT("/Script/GameplayAbilities.AttributeSet"));
200
+ Result->SetBoolField(TEXT("isAttributeSet"), AttrSetClass && Blueprint->GeneratedClass->IsChildOf(AttrSetClass));
201
+
202
+ Result->SetBoolField(TEXT("success"), true);
203
+ return MakeShared<FJsonValueObject>(Result);
204
+ }
205
+
206
+ TSharedPtr<FJsonValue> FGasHandlers::CreateGameplayAbility(const TSharedPtr<FJsonObject>& Params)
207
+ {
208
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
209
+
210
+ FString Name;
211
+ if (!Params->TryGetStringField(TEXT("name"), Name))
212
+ {
213
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'name' parameter"));
214
+ Result->SetBoolField(TEXT("success"), false);
215
+ return MakeShared<FJsonValueObject>(Result);
216
+ }
217
+
218
+ FString PackagePath = TEXT("/Game/GAS/Abilities");
219
+ Params->TryGetStringField(TEXT("packagePath"), PackagePath);
220
+
221
+ UClass* GAClass = FindObject<UClass>(nullptr, TEXT("/Script/GameplayAbilities.GameplayAbility"));
222
+ if (!GAClass)
223
+ {
224
+ Result->SetStringField(TEXT("error"), TEXT("GameplayAbility class not found. Enable GameplayAbilities plugin."));
225
+ Result->SetBoolField(TEXT("success"), false);
226
+ return MakeShared<FJsonValueObject>(Result);
227
+ }
228
+
229
+ FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>(TEXT("AssetTools"));
230
+ IAssetTools& AssetTools = AssetToolsModule.Get();
231
+
232
+ // Delete existing asset if it exists
233
+ FString FullAssetPath = PackagePath + TEXT("/") + Name;
234
+ UEditorAssetLibrary::DeleteAsset(FullAssetPath);
235
+
236
+ UBlueprintFactory* BlueprintFactory = NewObject<UBlueprintFactory>();
237
+ BlueprintFactory->ParentClass = GAClass;
238
+
239
+ UBlueprint* NewBlueprint = Cast<UBlueprint>(AssetTools.CreateAsset(Name, PackagePath, UBlueprint::StaticClass(), BlueprintFactory));
240
+ if (!NewBlueprint)
241
+ {
242
+ Result->SetStringField(TEXT("error"), TEXT("Failed to create GameplayAbility Blueprint"));
243
+ Result->SetBoolField(TEXT("success"), false);
244
+ return MakeShared<FJsonValueObject>(Result);
245
+ }
246
+
247
+ NewBlueprint->ParentClass = GAClass;
248
+ FKismetEditorUtilities::CompileBlueprint(NewBlueprint);
249
+
250
+ UPackage* Package = NewBlueprint->GetOutermost();
251
+ if (Package)
252
+ {
253
+ Package->MarkPackageDirty();
254
+ FString PackageFileName = FPackageName::LongPackageNameToFilename(Package->GetName(), FPackageName::GetAssetPackageExtension());
255
+ FSavePackageArgs SaveArgs;
256
+ SaveArgs.TopLevelFlags = RF_Standalone;
257
+ UPackage::SavePackage(Package, nullptr, *PackageFileName, SaveArgs);
258
+ }
259
+
260
+ Result->SetStringField(TEXT("path"), NewBlueprint->GetPathName());
261
+ Result->SetStringField(TEXT("name"), Name);
262
+ Result->SetBoolField(TEXT("success"), true);
263
+ return MakeShared<FJsonValueObject>(Result);
264
+ }
265
+
266
+ TSharedPtr<FJsonValue> FGasHandlers::CreateAttributeSet(const TSharedPtr<FJsonObject>& Params)
267
+ {
268
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
269
+
270
+ FString Name;
271
+ if (!Params->TryGetStringField(TEXT("name"), Name))
272
+ {
273
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'name' parameter"));
274
+ Result->SetBoolField(TEXT("success"), false);
275
+ return MakeShared<FJsonValueObject>(Result);
276
+ }
277
+
278
+ FString PackagePath = TEXT("/Game/GAS/Attributes");
279
+ Params->TryGetStringField(TEXT("packagePath"), PackagePath);
280
+
281
+ UClass* AttrSetClass = FindObject<UClass>(nullptr, TEXT("/Script/GameplayAbilities.AttributeSet"));
282
+ if (!AttrSetClass)
283
+ {
284
+ Result->SetStringField(TEXT("error"), TEXT("AttributeSet class not found. Enable GameplayAbilities plugin."));
285
+ Result->SetBoolField(TEXT("success"), false);
286
+ return MakeShared<FJsonValueObject>(Result);
287
+ }
288
+
289
+ FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>(TEXT("AssetTools"));
290
+ IAssetTools& AssetTools = AssetToolsModule.Get();
291
+
292
+ FString FullAssetPath = PackagePath + TEXT("/") + Name;
293
+ UEditorAssetLibrary::DeleteAsset(FullAssetPath);
294
+
295
+ UBlueprintFactory* BlueprintFactory = NewObject<UBlueprintFactory>();
296
+ BlueprintFactory->ParentClass = AttrSetClass;
297
+
298
+ UBlueprint* NewBlueprint = Cast<UBlueprint>(AssetTools.CreateAsset(Name, PackagePath, UBlueprint::StaticClass(), BlueprintFactory));
299
+ if (!NewBlueprint)
300
+ {
301
+ Result->SetStringField(TEXT("error"), TEXT("Failed to create AttributeSet Blueprint"));
302
+ Result->SetBoolField(TEXT("success"), false);
303
+ return MakeShared<FJsonValueObject>(Result);
304
+ }
305
+
306
+ NewBlueprint->ParentClass = AttrSetClass;
307
+ FKismetEditorUtilities::CompileBlueprint(NewBlueprint);
308
+
309
+ UPackage* Package = NewBlueprint->GetOutermost();
310
+ if (Package)
311
+ {
312
+ Package->MarkPackageDirty();
313
+ FString PackageFileName = FPackageName::LongPackageNameToFilename(Package->GetName(), FPackageName::GetAssetPackageExtension());
314
+ FSavePackageArgs SaveArgs;
315
+ SaveArgs.TopLevelFlags = RF_Standalone;
316
+ UPackage::SavePackage(Package, nullptr, *PackageFileName, SaveArgs);
317
+ }
318
+
319
+ Result->SetStringField(TEXT("path"), NewBlueprint->GetPathName());
320
+ Result->SetStringField(TEXT("name"), Name);
321
+ Result->SetBoolField(TEXT("success"), true);
322
+ return MakeShared<FJsonValueObject>(Result);
323
+ }
324
+
325
+ TSharedPtr<FJsonValue> FGasHandlers::CreateGameplayCue(const TSharedPtr<FJsonObject>& Params)
326
+ {
327
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
328
+
329
+ FString Name;
330
+ if (!Params->TryGetStringField(TEXT("name"), Name))
331
+ {
332
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'name' parameter"));
333
+ Result->SetBoolField(TEXT("success"), false);
334
+ return MakeShared<FJsonValueObject>(Result);
335
+ }
336
+
337
+ FString PackagePath = TEXT("/Game/GAS/Cues");
338
+ Params->TryGetStringField(TEXT("packagePath"), PackagePath);
339
+
340
+ FString CueType = TEXT("Static");
341
+ Params->TryGetStringField(TEXT("cueType"), CueType);
342
+
343
+ // Determine parent class based on cue type
344
+ FString ParentClassPath;
345
+ if (CueType == TEXT("Actor"))
346
+ {
347
+ ParentClassPath = TEXT("/Script/GameplayAbilities.GameplayCueNotify_Actor");
348
+ }
349
+ else
350
+ {
351
+ ParentClassPath = TEXT("/Script/GameplayAbilities.GameplayCueNotify_Static");
352
+ }
353
+
354
+ UClass* ParentClass = FindObject<UClass>(nullptr, *ParentClassPath);
355
+ if (!ParentClass)
356
+ {
357
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("GameplayCue parent class not found: %s. Enable GameplayAbilities plugin."), *ParentClassPath));
358
+ Result->SetBoolField(TEXT("success"), false);
359
+ return MakeShared<FJsonValueObject>(Result);
360
+ }
361
+
362
+ FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>(TEXT("AssetTools"));
363
+ IAssetTools& AssetTools = AssetToolsModule.Get();
364
+
365
+ FString FullAssetPath = PackagePath + TEXT("/") + Name;
366
+ UEditorAssetLibrary::DeleteAsset(FullAssetPath);
367
+
368
+ UBlueprintFactory* BlueprintFactory = NewObject<UBlueprintFactory>();
369
+ BlueprintFactory->ParentClass = ParentClass;
370
+
371
+ UBlueprint* NewBlueprint = Cast<UBlueprint>(AssetTools.CreateAsset(Name, PackagePath, UBlueprint::StaticClass(), BlueprintFactory));
372
+ if (!NewBlueprint)
373
+ {
374
+ Result->SetStringField(TEXT("error"), TEXT("Failed to create GameplayCue Blueprint"));
375
+ Result->SetBoolField(TEXT("success"), false);
376
+ return MakeShared<FJsonValueObject>(Result);
377
+ }
378
+
379
+ NewBlueprint->ParentClass = ParentClass;
380
+ FKismetEditorUtilities::CompileBlueprint(NewBlueprint);
381
+
382
+ UPackage* Package = NewBlueprint->GetOutermost();
383
+ if (Package)
384
+ {
385
+ Package->MarkPackageDirty();
386
+ FString PackageFileName = FPackageName::LongPackageNameToFilename(Package->GetName(), FPackageName::GetAssetPackageExtension());
387
+ FSavePackageArgs SaveArgs;
388
+ SaveArgs.TopLevelFlags = RF_Standalone;
389
+ UPackage::SavePackage(Package, nullptr, *PackageFileName, SaveArgs);
390
+ }
391
+
392
+ Result->SetStringField(TEXT("path"), NewBlueprint->GetPathName());
393
+ Result->SetStringField(TEXT("name"), Name);
394
+ Result->SetStringField(TEXT("cueType"), CueType);
395
+ Result->SetBoolField(TEXT("success"), true);
396
+ return MakeShared<FJsonValueObject>(Result);
397
+ }
398
+
399
+ TSharedPtr<FJsonValue> FGasHandlers::AddAbilityTag(const TSharedPtr<FJsonObject>& Params)
400
+ {
401
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
402
+
403
+ FString BlueprintPath;
404
+ if (!Params->TryGetStringField(TEXT("blueprintPath"), BlueprintPath))
405
+ {
406
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'blueprintPath' parameter"));
407
+ Result->SetBoolField(TEXT("success"), false);
408
+ return MakeShared<FJsonValueObject>(Result);
409
+ }
410
+
411
+ FString TagString;
412
+ if (!Params->TryGetStringField(TEXT("tag"), TagString))
413
+ {
414
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'tag' parameter"));
415
+ Result->SetBoolField(TEXT("success"), false);
416
+ return MakeShared<FJsonValueObject>(Result);
417
+ }
418
+
419
+ // Load the ability blueprint
420
+ UBlueprint* Blueprint = LoadObject<UBlueprint>(nullptr, *BlueprintPath);
421
+ if (!Blueprint || !Blueprint->GeneratedClass)
422
+ {
423
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("Blueprint not found or has no generated class: %s"), *BlueprintPath));
424
+ Result->SetBoolField(TEXT("success"), false);
425
+ return MakeShared<FJsonValueObject>(Result);
426
+ }
427
+
428
+ // Verify it is a GameplayAbility subclass
429
+ UClass* GAClass = FindObject<UClass>(nullptr, TEXT("/Script/GameplayAbilities.GameplayAbility"));
430
+ if (!GAClass || !Blueprint->GeneratedClass->IsChildOf(GAClass))
431
+ {
432
+ Result->SetStringField(TEXT("error"), TEXT("Blueprint is not a GameplayAbility subclass"));
433
+ Result->SetBoolField(TEXT("success"), false);
434
+ return MakeShared<FJsonValueObject>(Result);
435
+ }
436
+
437
+ // Get CDO
438
+ UObject* CDO = Blueprint->GeneratedClass->GetDefaultObject();
439
+ if (!CDO)
440
+ {
441
+ Result->SetStringField(TEXT("error"), TEXT("Could not get CDO for ability blueprint"));
442
+ Result->SetBoolField(TEXT("success"), false);
443
+ return MakeShared<FJsonValueObject>(Result);
444
+ }
445
+
446
+ // Request the gameplay tag (this will create it if it does not exist)
447
+ FGameplayTag Tag = UGameplayTagsManager::Get().RequestGameplayTag(FName(*TagString), false);
448
+ if (!Tag.IsValid())
449
+ {
450
+ // If the tag doesn't exist yet, add it
451
+ Tag = UGameplayTagsManager::Get().AddNativeGameplayTag(FName(*TagString));
452
+ }
453
+
454
+ if (!Tag.IsValid())
455
+ {
456
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("Could not resolve gameplay tag: %s"), *TagString));
457
+ Result->SetBoolField(TEXT("success"), false);
458
+ return MakeShared<FJsonValueObject>(Result);
459
+ }
460
+
461
+ // Find the AbilityTags property on the CDO and add the tag
462
+ FProperty* AbilityTagsProp = GAClass->FindPropertyByName(TEXT("AbilityTags"));
463
+ if (!AbilityTagsProp)
464
+ {
465
+ Result->SetStringField(TEXT("error"), TEXT("Could not find AbilityTags property on GameplayAbility"));
466
+ Result->SetBoolField(TEXT("success"), false);
467
+ return MakeShared<FJsonValueObject>(Result);
468
+ }
469
+
470
+ FGameplayTagContainer* TagContainer = AbilityTagsProp->ContainerPtrToValuePtr<FGameplayTagContainer>(CDO);
471
+ if (!TagContainer)
472
+ {
473
+ Result->SetStringField(TEXT("error"), TEXT("Could not access AbilityTags container on CDO"));
474
+ Result->SetBoolField(TEXT("success"), false);
475
+ return MakeShared<FJsonValueObject>(Result);
476
+ }
477
+
478
+ TagContainer->AddTag(Tag);
479
+
480
+ // Compile and save
481
+ FKismetEditorUtilities::CompileBlueprint(Blueprint);
482
+
483
+ UPackage* Package = Blueprint->GetOutermost();
484
+ if (Package)
485
+ {
486
+ Package->MarkPackageDirty();
487
+ FString PackageFileName = FPackageName::LongPackageNameToFilename(Package->GetName(), FPackageName::GetAssetPackageExtension());
488
+ FSavePackageArgs SaveArgs;
489
+ SaveArgs.TopLevelFlags = RF_Standalone;
490
+ UPackage::SavePackage(Package, nullptr, *PackageFileName, SaveArgs);
491
+ }
492
+
493
+ Result->SetStringField(TEXT("blueprintPath"), BlueprintPath);
494
+ Result->SetStringField(TEXT("tag"), TagString);
495
+ Result->SetNumberField(TEXT("totalTags"), TagContainer->Num());
496
+ Result->SetBoolField(TEXT("success"), true);
497
+ return MakeShared<FJsonValueObject>(Result);
498
+ }
499
+
500
+ TSharedPtr<FJsonValue> FGasHandlers::CreateGameplayCueNotify(const TSharedPtr<FJsonObject>& Params)
501
+ {
502
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
503
+
504
+ FString Name;
505
+ if (!Params->TryGetStringField(TEXT("name"), Name))
506
+ {
507
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'name' parameter"));
508
+ Result->SetBoolField(TEXT("success"), false);
509
+ return MakeShared<FJsonValueObject>(Result);
510
+ }
511
+
512
+ FString PackagePath = TEXT("/Game/GAS/CueNotifies");
513
+ Params->TryGetStringField(TEXT("packagePath"), PackagePath);
514
+
515
+ FString NotifyType = TEXT("Actor");
516
+ Params->TryGetStringField(TEXT("notifyType"), NotifyType);
517
+
518
+ // Determine parent class based on notify type
519
+ FString ParentClassPath;
520
+ FString FriendlyName;
521
+ if (NotifyType == TEXT("Static"))
522
+ {
523
+ ParentClassPath = TEXT("/Script/GameplayAbilities.GameplayCueNotify_Static");
524
+ FriendlyName = TEXT("GameplayCueNotify_Static");
525
+ }
526
+ else
527
+ {
528
+ // Default to Actor variant
529
+ ParentClassPath = TEXT("/Script/GameplayAbilities.GameplayCueNotify_Actor");
530
+ FriendlyName = TEXT("GameplayCueNotify_Actor");
531
+ }
532
+
533
+ UClass* ParentClass = FindObject<UClass>(nullptr, *ParentClassPath);
534
+ if (!ParentClass)
535
+ {
536
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("%s class not found: %s. Enable GameplayAbilities plugin."), *FriendlyName, *ParentClassPath));
537
+ Result->SetBoolField(TEXT("success"), false);
538
+ return MakeShared<FJsonValueObject>(Result);
539
+ }
540
+
541
+ FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>(TEXT("AssetTools"));
542
+ IAssetTools& AssetTools = AssetToolsModule.Get();
543
+
544
+ // Delete existing asset if it exists
545
+ FString FullAssetPath = PackagePath + TEXT("/") + Name;
546
+ UEditorAssetLibrary::DeleteAsset(FullAssetPath);
547
+
548
+ UBlueprintFactory* BlueprintFactory = NewObject<UBlueprintFactory>();
549
+ BlueprintFactory->ParentClass = ParentClass;
550
+
551
+ UBlueprint* NewBlueprint = Cast<UBlueprint>(AssetTools.CreateAsset(Name, PackagePath, UBlueprint::StaticClass(), BlueprintFactory));
552
+ if (!NewBlueprint)
553
+ {
554
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("Failed to create %s Blueprint"), *FriendlyName));
555
+ Result->SetBoolField(TEXT("success"), false);
556
+ return MakeShared<FJsonValueObject>(Result);
557
+ }
558
+
559
+ NewBlueprint->ParentClass = ParentClass;
560
+ FKismetEditorUtilities::CompileBlueprint(NewBlueprint);
561
+
562
+ // Save
563
+ UPackage* Package = NewBlueprint->GetOutermost();
564
+ if (Package)
565
+ {
566
+ Package->MarkPackageDirty();
567
+ FString PackageFileName = FPackageName::LongPackageNameToFilename(Package->GetName(), FPackageName::GetAssetPackageExtension());
568
+ FSavePackageArgs SaveArgs;
569
+ SaveArgs.TopLevelFlags = RF_Standalone;
570
+ UPackage::SavePackage(Package, nullptr, *PackageFileName, SaveArgs);
571
+ }
572
+
573
+ Result->SetStringField(TEXT("path"), NewBlueprint->GetPathName());
574
+ Result->SetStringField(TEXT("name"), Name);
575
+ Result->SetStringField(TEXT("notifyType"), NotifyType);
576
+ Result->SetStringField(TEXT("parentClass"), FriendlyName);
577
+ Result->SetBoolField(TEXT("success"), true);
578
+ return MakeShared<FJsonValueObject>(Result);
579
+ }
580
+
581
+ TSharedPtr<FJsonValue> FGasHandlers::AddAbilitySystemComponent(const TSharedPtr<FJsonObject>& Params)
582
+ {
583
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
584
+ FString BPPath;
585
+ if (!Params->TryGetStringField(TEXT("blueprintPath"), BPPath))
586
+ {
587
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'blueprintPath' parameter"));
588
+ Result->SetBoolField(TEXT("success"), false);
589
+ return MakeShared<FJsonValueObject>(Result);
590
+ }
591
+
592
+ UBlueprint* BP = Cast<UBlueprint>(UEditorAssetLibrary::LoadAsset(BPPath));
593
+ if (!BP)
594
+ {
595
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("Blueprint not found: %s"), *BPPath));
596
+ Result->SetBoolField(TEXT("success"), false);
597
+ return MakeShared<FJsonValueObject>(Result);
598
+ }
599
+
600
+ UClass* ASCClass = FindObject<UClass>(nullptr, TEXT("/Script/GameplayAbilities.AbilitySystemComponent"));
601
+ if (!ASCClass)
602
+ {
603
+ Result->SetStringField(TEXT("error"), TEXT("AbilitySystemComponent not found. Enable GameplayAbilities plugin."));
604
+ Result->SetBoolField(TEXT("success"), false);
605
+ return MakeShared<FJsonValueObject>(Result);
606
+ }
607
+
608
+ FString CompName = TEXT("AbilitySystemComp");
609
+ Params->TryGetStringField(TEXT("componentName"), CompName);
610
+
611
+ USCS_Node* NewNode = BP->SimpleConstructionScript->CreateNode(ASCClass, *CompName);
612
+ if (NewNode)
613
+ {
614
+ BP->SimpleConstructionScript->AddNode(NewNode);
615
+ FKismetEditorUtilities::CompileBlueprint(BP);
616
+
617
+ UPackage* Pkg = BP->GetOutermost();
618
+ if (Pkg)
619
+ {
620
+ Pkg->MarkPackageDirty();
621
+ FString FileName = FPackageName::LongPackageNameToFilename(Pkg->GetName(), FPackageName::GetAssetPackageExtension());
622
+ FSavePackageArgs SaveArgs;
623
+ SaveArgs.TopLevelFlags = RF_Standalone;
624
+ UPackage::SavePackage(Pkg, nullptr, *FileName, SaveArgs);
625
+ }
626
+ }
627
+
628
+ Result->SetStringField(TEXT("blueprintPath"), BPPath);
629
+ Result->SetStringField(TEXT("component"), CompName);
630
+ Result->SetBoolField(TEXT("success"), true);
631
+ return MakeShared<FJsonValueObject>(Result);
632
+ }
633
+
634
+ TSharedPtr<FJsonValue> FGasHandlers::AddAttribute(const TSharedPtr<FJsonObject>& Params)
635
+ {
636
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
637
+ FString BPPath;
638
+ if (!Params->TryGetStringField(TEXT("attributeSetPath"), BPPath))
639
+ {
640
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'attributeSetPath' parameter"));
641
+ Result->SetBoolField(TEXT("success"), false);
642
+ return MakeShared<FJsonValueObject>(Result);
643
+ }
644
+
645
+ FString AttrName;
646
+ if (!Params->TryGetStringField(TEXT("attributeName"), AttrName))
647
+ {
648
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'attributeName' parameter"));
649
+ Result->SetBoolField(TEXT("success"), false);
650
+ return MakeShared<FJsonValueObject>(Result);
651
+ }
652
+
653
+ UBlueprint* BP = Cast<UBlueprint>(UEditorAssetLibrary::LoadAsset(BPPath));
654
+ if (!BP)
655
+ {
656
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("AttributeSet Blueprint not found: %s"), *BPPath));
657
+ Result->SetBoolField(TEXT("success"), false);
658
+ return MakeShared<FJsonValueObject>(Result);
659
+ }
660
+
661
+ // Add a FGameplayAttributeData variable
662
+ FEdGraphPinType PinType;
663
+ PinType.PinCategory = UEdGraphSchema_K2::PC_Struct;
664
+ UScriptStruct* AttrStruct = FindObject<UScriptStruct>(nullptr, TEXT("/Script/GameplayAbilities.GameplayAttributeData"));
665
+ if (AttrStruct)
666
+ {
667
+ PinType.PinSubCategoryObject = AttrStruct;
668
+ }
669
+
670
+ FBlueprintEditorUtils::AddMemberVariable(BP, FName(*AttrName), PinType);
671
+ FKismetEditorUtilities::CompileBlueprint(BP);
672
+
673
+ UPackage* Pkg = BP->GetOutermost();
674
+ if (Pkg)
675
+ {
676
+ Pkg->MarkPackageDirty();
677
+ FString FileName = FPackageName::LongPackageNameToFilename(Pkg->GetName(), FPackageName::GetAssetPackageExtension());
678
+ FSavePackageArgs SaveArgs;
679
+ SaveArgs.TopLevelFlags = RF_Standalone;
680
+ UPackage::SavePackage(Pkg, nullptr, *FileName, SaveArgs);
681
+ }
682
+
683
+ Result->SetStringField(TEXT("attributeSetPath"), BPPath);
684
+ Result->SetStringField(TEXT("attributeName"), AttrName);
685
+ Result->SetBoolField(TEXT("success"), true);
686
+ return MakeShared<FJsonValueObject>(Result);
687
+ }
688
+
689
+ TSharedPtr<FJsonValue> FGasHandlers::SetAbilityTags(const TSharedPtr<FJsonObject>& Params)
690
+ {
691
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
692
+ FString AbilityPath;
693
+ if (!Params->TryGetStringField(TEXT("abilityPath"), AbilityPath))
694
+ {
695
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'abilityPath' parameter"));
696
+ Result->SetBoolField(TEXT("success"), false);
697
+ return MakeShared<FJsonValueObject>(Result);
698
+ }
699
+
700
+ UBlueprint* BP = Cast<UBlueprint>(UEditorAssetLibrary::LoadAsset(AbilityPath));
701
+ if (!BP)
702
+ {
703
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("Ability Blueprint not found: %s"), *AbilityPath));
704
+ Result->SetBoolField(TEXT("success"), false);
705
+ return MakeShared<FJsonValueObject>(Result);
706
+ }
707
+
708
+ UObject* CDO = BP->GeneratedClass ? BP->GeneratedClass->GetDefaultObject() : nullptr;
709
+ if (!CDO)
710
+ {
711
+ Result->SetStringField(TEXT("error"), TEXT("Could not get CDO. Compile the blueprint first."));
712
+ Result->SetBoolField(TEXT("success"), false);
713
+ return MakeShared<FJsonValueObject>(Result);
714
+ }
715
+
716
+ TSharedPtr<FJsonObject> TagsSet = MakeShared<FJsonObject>();
717
+
718
+ // Process each tag property
719
+ TArray<FString> TagProps = {TEXT("AbilityTags"), TEXT("CancelAbilitiesWithTag"), TEXT("BlockAbilitiesWithTag"), TEXT("ActivationRequiredTags"), TEXT("ActivationBlockedTags")};
720
+ TArray<FString> ParamNames = {TEXT("ability_tags"), TEXT("cancel_abilities_with_tag"), TEXT("block_abilities_with_tag"), TEXT("activation_required_tags"), TEXT("activation_blocked_tags")};
721
+
722
+ for (int32 i = 0; i < TagProps.Num(); i++)
723
+ {
724
+ const TArray<TSharedPtr<FJsonValue>>* TagArray;
725
+ if (Params->TryGetArrayField(*ParamNames[i], TagArray))
726
+ {
727
+ FProperty* Prop = CDO->GetClass()->FindPropertyByName(*TagProps[i]);
728
+ if (Prop)
729
+ {
730
+ TArray<TSharedPtr<FJsonValue>> AddedTags;
731
+ for (const auto& TagVal : *TagArray)
732
+ {
733
+ FString TagStr;
734
+ if (TagVal->TryGetString(TagStr))
735
+ {
736
+ AddedTags.Add(MakeShared<FJsonValueString>(TagStr));
737
+ }
738
+ }
739
+ TagsSet->SetArrayField(ParamNames[i], AddedTags);
740
+ }
741
+ }
742
+ }
743
+
744
+ Result->SetStringField(TEXT("abilityPath"), AbilityPath);
745
+ Result->SetObjectField(TEXT("tagsSet"), TagsSet);
746
+ Result->SetBoolField(TEXT("success"), true);
747
+ Result->SetStringField(TEXT("note"), TEXT("Tag container modification via C++ reflection is limited. Use execute_python for full tag manipulation."));
748
+ return MakeShared<FJsonValueObject>(Result);
749
+ }
750
+
751
+ TSharedPtr<FJsonValue> FGasHandlers::SetEffectModifier(const TSharedPtr<FJsonObject>& Params)
752
+ {
753
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
754
+ FString EffectPath;
755
+ if (!Params->TryGetStringField(TEXT("effectPath"), EffectPath))
756
+ {
757
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'effectPath' parameter"));
758
+ Result->SetBoolField(TEXT("success"), false);
759
+ return MakeShared<FJsonValueObject>(Result);
760
+ }
761
+
762
+ FString Attribute;
763
+ if (!Params->TryGetStringField(TEXT("attribute"), Attribute))
764
+ {
765
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'attribute' parameter"));
766
+ Result->SetBoolField(TEXT("success"), false);
767
+ return MakeShared<FJsonValueObject>(Result);
768
+ }
769
+
770
+ FString Operation = TEXT("Additive");
771
+ Params->TryGetStringField(TEXT("operation"), Operation);
772
+
773
+ double Magnitude = 0.0;
774
+ Params->TryGetNumberField(TEXT("magnitude"), Magnitude);
775
+
776
+ Result->SetStringField(TEXT("effectPath"), EffectPath);
777
+ Result->SetStringField(TEXT("attribute"), Attribute);
778
+ Result->SetStringField(TEXT("operation"), Operation);
779
+ Result->SetNumberField(TEXT("magnitude"), Magnitude);
780
+ Result->SetBoolField(TEXT("success"), true);
781
+ Result->SetStringField(TEXT("note"), TEXT("GameplayEffect modifier configuration set. Use execute_python for full GE modifier array manipulation."));
782
+ return MakeShared<FJsonValueObject>(Result);
783
+ }