🌞 Victory Plugin ~ 's Extra Blueprint Nodes for UE5, No C++ Required!

h

UENUM(BlueprintType) enum class ETF:uint8{True_, False_};

// Получить делегаты
UFUNCTION(Category="IVS|Get", BlueprintCallable) static TArray<FString> GetDelegates(UObject* ObjectDelegate, FName Delegate/*='Rpl'*/){
TArray<FString> Functions;
if(ObjectDelegate!=nullptr && Delegate!=NAME_None){
FMulticastDelegateProperty* P=FindFProperty<FMulticastDelegateProperty>(ObjectDelegate->GetClass(), Delegate);
if(NULL!=P){
FString S;
int16 I;
P->ExportTextItem(S, P->ContainerPtrToValuePtr<uint8>(ObjectDelegate), nullptr, ObjectDelegate, 0, nullptr);
//Delegates.Add(S);//"()"
//S="(RBttBrd.Change1,RBttBrd.Change2)";
//Delegates.Add(S.Right(1)); =")"
//Delegates.Add(S.Left(1)); ="("
//Delegates.Add(S.Mid(1, S.Len()-2)); ="RBttBrd.Change1,RBttBrd.Change2"
//int16 I=S.Find(",", ESearchCase::IgnoreCase, ESearchDir::FromStart);
//Delegates.Add(S.Mid(I+1)); ="RBttBrd.Change2"
S=S.Mid(1, S.Len()-2);
while(S!=""){I=S.Find(",", ESearchCase::IgnoreCase, ESearchDir::FromStart); if(I>-1){Functions.Add(S.Left(I)); S=S.Mid(I+1);}else{Functions.Add(S); break;}}
}
}
return Functions;
}

// Содержит ли делегат функцию?
UFUNCTION(Category="IVS|Check", BlueprintCallable, Meta=(DefaultToSelf="ObjectValue", ExpandEnumAsExecs="Branches")) static void DelegateHasFunction(ETF& Branches, bool& Success, UObject* ObjectValue, UObject* ObjectDelegate, FName Delegate/*='Rpl'*/, const FString &Function);

cpp

void UILbr::DelegateHasFunction(ETF &Branches, bool &Success, UObject* ObjectValue, UObject* ObjectDelegate, FName Delegate/*='Rpl'*/, const FString &Function){
Success=UILbr::GetDelegates(ObjectDelegate, Delegate).Contains(UKismetSystemLibrary::GetDisplayName(ObjectValue)+"."+Function);
Branches=Success? ETF::True_: ETF::False_;
}

, you are a legend, look at this thing. It should be engine standard content!

I have a question though, or maybe problem. I’m trying to parse a JSON file with load string array from file and it wont read the second index, I think maybe the way it parses the information is getting read as code instructions or something, and terminating early?

Thats a guess, im not really a programmer.

tex_32_41_4.json (482 Bytes)

Thats the JSON anway, I can only get it to read down past index 1’s brackets, and then nothing.

Any help would be appreciated!

1 Like

Hey, :wave:
I really like your work, this plugin is great! You asked to write about the nodes that we would like to see. I would really like to see the “Server Travel” feature again in the new version. I previously used 4.26.2, and there this feature helped to transfer all players in multiplayer into new/next level. And in version UE5.0 this function was no longer in the plugin. Only same name UE node :frowning:
And also pure func “IsEmtry” with bool result.
I think this functions would be very useful!
Thanks!

ZXn1boUArM

Q3diDQTF21

Hi ,

Thank you for your work on this plugin, it’s quite often a default install on my projects.

Do you happen to have or know of an equivalent of “ClosestPointsonTwoLine” from the UE4 plugin? I am using it to find the intersection of two lines drawn by two sets of coordinates (the intersections is outside of the bounds of the coordinates themselves)

Thanks.
Phil

Hey @! Would you be able to get the “is PIE world” node added to the UE5 version? This has been by far the most useful function for most of my projects, as it helps a lot with enabling things for editor while disabling them when sharing work with clients.

3 Likes

Hello @ you are doing a great job, your plugin really helps me in my project.
I’m migrating my game to UE5 and I encountered a problem with “Victory Set Custom Config Var String” Nodes. There are any plans to add this in the UE5 plugin?

I need following nodes
Victory Get Custom Config Var Float
Victory Get Custom Config Var Int
Victory Get Custom Config Var String
Victory Get Custom Config Var Bool

Victory Set Custom Config Var Float
Victory Set Custom Config Var Int
Victory Set Custom Config Var String
Victory Set Custom Config Var Bool

I haven’t had time to check what’s updated yet, but just in case:
Victory Save String to OSClipboard [exists, thanks]
Victory Simulate Key Press [exists, thanks]

:heart_eyes:

1 Like

Widget Get Children of Class already updated?

image
Ah yep, thank you!
image

Sort Array (of widgets in a scrollbox for instance) seems missing, maybe someone already mentioned.

1 Like

I will add these, thank you for letting me know Everyone!

:heart:

Victory Plugin for 5.0.2 With New Nodes (Yes!!!)

The Nodes listed in above posts have been added!

:racehorse: :dash: Annnnd… :racehorse: :dash:

:sparkling_heart: Get Static Mesh Vertex Positions :sparkling_heart: (Scaled, Rotated, & Translated!)
is :zap: :zap: :zap: BACK :zap: :zap: :zap:

The C++ Code

//Build.cs "MeshDescription"
#include "StaticMeshDescription.h"
bool URamaCodePluginBPLibrary::GetStaticMeshVertexLocations(UStaticMeshComponent* Comp, TArray<FVector>& VertexPositions, int32 LodIndex)
{
	if(!Comp) 
	{
		return false;
	}
	
	TObjectPtr<UStaticMesh> MeshPtr = Comp->GetStaticMesh();
	if(!MeshPtr)
	{
		return false;
	}
	
	UStaticMeshDescription* Desc = MeshPtr->GetStaticMeshDescription(LodIndex);
	if(!Desc)
	{ 
		return false;
	}
	
	FTransform WorldTransform = Comp->GetComponentTransform();
	FVertexArray& Verts = Desc->Vertices();
	for (FVertexID EachVertId : Verts.GetElementIDs())
	{   
		VertexPositions.Add(
			WorldTransform.TransformPosition( Desc->GetVertexPosition(EachVertId) ) 
		);
	}  
	 
	return true;
}

Enjoy!

:zap: :sparkling_heart: :zap:

2 Likes


Array sort in the new version seems to only be Integer,Float,String.

My Ue5 Plugin (Game creation library including advanced gameplay data saving and some of the planned save UI elements)
I would like an assessment, and participation in the implementation of cool interfaces and game blanks.

Requires a couple of paid plugins for server and client code (in the process of testing). Ignore and you can remove the server and client code from the plugin content. I can also create an IVSContentServerClient plugin.

1 Like

When attempting to package a project, I get this error:

ERROR: Expecting to find a type to be declared in a module rules named ue5

Followed by the link to the victory plugin. I’ve searched, but can’t find a solid answer on fixing this.

1 Like

Amazing! I don’t think the “Insert child at” node has been added though.

image

I don’t think it can be done through standard unreal blueprints

1 Like

I just packaged a UE5 game with Victory plugin without any issues :rose:

Can you compose a :tulip: repro project :tulip: containingly on the content needed to demonstrate the issue you are experiencing?

Noted! I will check this out!

:heart:

1 Like

:zap: Save Any Dynamic Mesh as a New Static Mesh Asset in Editor Builds :zap:

(17 min video showing you exactly how to use the new content included with Victory Plugin!)


(Dynamic Mesh Actor + Spline Component + Victory Plugin = New Static Mesh Asset!)

Dear Community,

I’ve added a new node to Victory Plugin so you can easily save out as a new Static Mesh Asset, any Dynamic Mesh you create using any of your own custom logic in constructor script to make really fancy shapes!

Yes!!!

So you really can :star2: make your own modelling tools :star2: inside of Unreal Engine, using BP constructor script, and then make new Static Mesh Assets that will ship with your game!

Create Your Own Static Mesh Asset Modeling Tools!
EX: Dynamic Mesh + Spline Component Modeling Tool

I show you an example of what I mean in the video, creating a Spline Mesh Modeling Tool in BP, a BP which you can find in the Content Folder of the Victory Plugin, along with the example assets!

Please note this BP node is Editor Only, I explain more in the video!

:zap: The Relevant C++ Code :zap:

Because I let you choose any asset path with your game’s content folder for your new Static Mesh Asset, create the folder structure for you, handle the case of if the asset path is already in use, there is some extra file handling code, but the rest is the utilization of the new MeshModelingToolset plugin that exists in UE5!

:heart: Thank You Epic Devs! :heart:

//~~~ CreateStaticMeshAssetFromDynamicMesh ~~~
#include "GeometryFramework/Public/Components/DynamicMeshComponent.h"

//Runtime
//Engine\Plugins\Runtime\MeshModelingToolset\Source\ModelingComponents\Public\ModelingObjectsCreationAPI.h
#include "ModelingObjectsCreationAPI.h"
 
//Editor
#if WITH_EDITOR
	//"ModelingComponentsEditorOnly" in build.cs ♥ 
	#include "AssetUtils/CreateStaticMeshUtil.h"
#endif
//~~~~ End CreateStaticMeshAssetFromDynamicMesh ~~~

UStaticMesh* UVictoryBPFunctionLibrary::CreateStaticMeshAssetFromDynamicMesh( 
	FString ContentFolderPath,
	UDynamicMeshComponent* DynamicMeshComp, 
	FString& Status, 
	FString& NewAssetFilePath, 
	bool& Success
){
	NewAssetFilePath = "";
	
	#if WITH_EDITOR
		
	//Comp?
	if(!DynamicMeshComp || !DynamicMeshComp->GetDynamicMesh())
	{
		Status = "No valid Dynamic Mesh Component was supplied!";
		Success = false;
		return nullptr;
	}
	
	//No Triangles?
	if(DynamicMeshComp->GetDynamicMesh()->IsEmpty())
	{
		Status = "Dynamic Mesh has no triangles!";
		Success = false;
		return nullptr;
	}
	
	//Make sure to remove extension if user added it ♥ 
	
	//File without any extension
	ContentFolderPath.ReplaceInline(TEXT(".uasset"),TEXT(""));
	  
	//~~~ Create possibly numbered new filename, if supplied exists! ♥ 
	FString FinalRelativePath = "";
	bool FolderTreeCreated = UVictoryBPFunctionLibrary::GenerateUniqueContentRelativeFileName(ContentFolderPath + ".uasset",FinalRelativePath,NewAssetFilePath);
	  
	if(!FolderTreeCreated)
	{
		Status = "Could not create the specified directory tree";
		Success = false;
		return false;
	}
	
	//Remove ext before sending to AssetUtils
	//// Path is now Relative with no extension, possibly with 1,2,3 added for each create event in editor! <3 
	FinalRelativePath.ReplaceInline(TEXT(".uasset"),TEXT(""));
	
	//~~~ End of file path input handling ♥  ~~~
	
	//Create Mesh Base Params
	FCreateMeshObjectParams CreateMeshParams;
	
	CreateMeshParams.BaseName 		= FinalRelativePath;
	
	//~~~ Materials ~~~
	DynamicMeshComp->ValidateMaterialSlots();
	
	for(int32 v = 0; v < DynamicMeshComp->GetNumMaterials() ; v++)
	{
		CreateMeshParams.Materials.Add(DynamicMeshComp->GetMaterial(v));
	}
	 
	//Set from FDynamicMesh3 (the actual mesh herself, not from a MeshDescription)
	CreateMeshParams.SetMesh(DynamicMeshComp->GetMesh());
	
	//Ensure Set to DynamicMesh
	CreateMeshParams.MeshType = ECreateMeshObjectSourceMeshType::DynamicMesh;
	
	//~~~
	//~~~
	//~~~
	
	//~~~~~~~~~~~~~~~~~
	// Code from UE_5.0\Engine\Plugins\Runtime\MeshModelingToolset\Source\ModelingComponentsEditorOnly\PublicEditorModelingObjectsCreationAPI.cpp
	
	//Static Mesh!
	//CreateMeshObjectResult = EditorCreateMeshAPI->CreateStaticMeshAsset(CreateMeshParams);
	
	//Static Asset Options
	UE::AssetUtils::FStaticMeshAssetOptions AssetOptions;
	AssetOptions.NewAssetPath = "/Game/" + CreateMeshParams.BaseName;
	 
	//Ensure no // 
	FPaths::RemoveDuplicateSlashes(AssetOptions.NewAssetPath);
	 
	AssetOptions.NumSourceModels = 1;
	AssetOptions.NumMaterialSlots = CreateMeshParams.Materials.Num();
	
	//Got rid of FilterMaterials part <3 
	AssetOptions.AssetMaterials = (CreateMeshParams.AssetMaterials.Num() == AssetOptions.NumMaterialSlots) 
		? CreateMeshParams.AssetMaterials 
		: CreateMeshParams.Materials;

	AssetOptions.bEnableRecomputeNormals 	= CreateMeshParams.bEnableRecomputeNormals;
	AssetOptions.bEnableRecomputeTangents 	= CreateMeshParams.bEnableRecomputeTangents;
	AssetOptions.bGenerateNaniteEnabledMesh = CreateMeshParams.bEnableNanite;
	AssetOptions.NaniteProxyTrianglePercent = CreateMeshParams.NaniteProxyTrianglePercent;

	AssetOptions.bCreatePhysicsBody 		= CreateMeshParams.bEnableCollision;
	AssetOptions.CollisionType 				= CreateMeshParams.CollisionMode;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//Dynamic Mesh! ♥ 
	FDynamicMesh3* DynamicMesh = &CreateMeshParams.DynamicMesh.GetValue();
	AssetOptions.SourceMeshes.DynamicMeshes.Add(DynamicMesh);
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	
	//Static Mesh Result
	UE::AssetUtils::FStaticMeshResults ResultData;
	 
	//==========
	//CREATE!!!
	UE::AssetUtils::ECreateStaticMeshResult AssetResult = UE::AssetUtils::CreateStaticMeshAsset(AssetOptions, ResultData);
	//==========
 
	if (AssetResult != UE::AssetUtils::ECreateStaticMeshResult::Ok)
	{
		Status = "UE::AssetUtils::ECreateStaticMeshResult is ECreateModelingObjectResult::Failed_AssetCreationFailed";
		Success = false;
		return false;
	}
  
	// End of code from PublicEditorModelingObjectsCreationAPI.cpp
	//~~~~~~~~~~~~~~~~~
	
	Status = "Victory!";
	Success = true;
	return ResultData.StaticMesh;
	#endif
	
	Status = "This node is for Editor Builds only, but does create static mesh assets that can ship with your packaged game! ♥ ";
	Success = false;
	return nullptr;
}


bool UVictoryBPFunctionLibrary::GenerateUniqueContentRelativeFileName(FString ContentRelativeFilePath, FString& ContentRelativeNewFileName, FString& AbsolutePath, bool CreateFolderTree)
{
	//UE User-Input Assistance (inline) ♥ 
	FPaths::NormalizeFilename(ContentRelativeFilePath);
	FPaths::RemoveDuplicateSlashes(ContentRelativeFilePath);
	
	FString AbsContentPath = FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir());
	
	//Extension
	FString FileExt		=  FPaths::GetExtension(ContentRelativeFilePath, true); //include .
	
	//File without any extension
	FString AssetFile 	= FPaths::GetBaseFilename(ContentRelativeFilePath);
	
	//Everything but the file
	FString BasePath 	= FPaths::GetPath(ContentRelativeFilePath);
	
	
	if(ContentRelativeFilePath.Contains("/"))
	{	
		//Absolute Path
		BasePath = AbsContentPath + BasePath; 
		 
		if(CreateFolderTree)
		{
			//Folder?
			if(!FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*BasePath))
			{ 
				//Info out to user about what was attempted
				AbsolutePath = BasePath;
				return false;
				//~~~~~~~~~~~~~~~~~~~~~~
			}
		}
	}
	
	//~~~
	// Make path with extension
	if(BasePath != "")
	{
		AbsolutePath = BasePath + "/" + AssetFile;
	}
	else
	{
		AbsolutePath = AbsContentPath + AssetFile;
	}
	 
	//Check if file exists already, increment int as needed, ♥ 
	 
	//Absolute Path + File, Still No Extension yet
	BasePath 		= AbsolutePath;
	  
	int32 FileNameInt 	= 1;
	AbsolutePath 		= BasePath + FileExt;
	while(FPlatformFileManager::Get().GetPlatformFile().FileExists( *AbsolutePath))
	{
		FileNameInt++;
		AbsolutePath = BasePath + FString::FromInt(FileNameInt) + FileExt;
	}
	
	FString Left;
	
	//Make Relative
	AbsolutePath.Split(TEXT("/Content/"),&Left,&ContentRelativeNewFileName);
	
	return true;
}

:sparkling_heart: Have Fun Creating Static Mesh Assets Using Your Own Custom Modeling Tools :sparkling_heart:

And Modeling to Your Creative Heart’s Content in the Level Viewport! :sparkling_heart:

:heart:

PS: You will want to enable this plugin for use with the new content in the Victory Plugin Content Folder:

(The content demoed in the video is zipped inside Victory Plugin Content Folder so you can make sure you have Geometry Script Plugin enabled first)

Hello , I have the same problem as Sotalo with game package.

I create a empty project(BP) with enable your Plugin “VictoryBPLibrary” and package project (dev+win) with default settings.

ERROR: Expecting to find a type to be declared in a module rules named ‘VictoryBPLibrary’

My “VictoryBPLibrary” Plugin is installed under: UE_5.0\Engine\Plugins\VictoryBPLibrary

Here my empty project for testing:

Thank you this works, but when i start the package version, then have a “failed to load because module Victory Library” could not be found. Do I still have to compile the plugin for release version?

UPDATE: Engine/Plugins/Marketplace folder will work as well!

Hi there!

I tested the Project Level solution, and packaged a game, and the Victory Plugin did actually get loaded, I presume you are using a C++ project? Here’s what I saw in my log, as well as my actual test working in the packaged game:

Sample Log for a Successful Load of Plugin in Packaged UE5 Build

LogPluginManager: Mounting Engine plugin WebMMoviePlayer
LogPluginManager: Mounting Engine plugin WindowsDeviceProfileSelector
LogPluginManager: Mounting Engine plugin WindowsMoviePlayer
LogPluginManager: Mounting Project plugin VictoryBPLibrary     //<~~~~~~~~
LogPackageName: Display: FPackageName: Mount point added: '../../../Engine/Plugins/2D/Paper2D/Content/' mounted to '/Paper2D/'
LogPackageName: Display: FPackageName: Mount point added: '../../../Engine/Plugins/Animation/ControlRig/Content/' mounted to '/ControlRig/'

Solution 1: :star2: Engine/Plugins/Marketplace :star2: Folder

Actually I found that if you move the Victory Plugin to Engine/Plugins/Marketplace

Then the error goes away, so that is a solution for those of you using the Victory Plugin in multiple projects!

If you do not wish to do the above, you can do the below!

Solution 2

Move Plugin To Project Level

  1. Create a folder called, precisely :star2: “Plugins” :star2: in the root folder of YourProject

  2. Move the plugin (works for any plugin having this issue) to YourProject/Plugins, removing it from the Engine install level (the default location for Marketplace plugins is the Engine level, specifically, UE_5.0/Engine/Plugins/Marketplace)

  3. For VictoryPlugin this should look like “YourProject/Plugins/VictoryPlugin”

  4. Spelling does matter, if you have any issues make sure the folder is indeed named “Plugins”

  5. You can repeat this process for :star2: all UE5 projects :star2:, each project can have their own “Plugins” folder, just copy the plugin as needed!

  6. :rose: Continue Developing in UE5 Joyfully :rose:, saving any CPU cycles that were waiting for a fix this, because I don’t now when that will be, and it seems to be pervading issue that will likely get fixed by Epic in the next UE5 release.

:heart:

1 Like