Hide bone through Kismet

Just tried doing it the way Epic does it. Node:


/**
* This kismet node is used to hide a bone
*/
class SeqAct_BoneRemoval extends SequenceAction;

var() Object SkelMesh;
var() name BoneName;

defaultproperties
{
ObjName="Bone Removal"
ObjCategory="Misc"
VariableLinks.Empty
VariableLinks(0)=(ExpectedType=class'SeqVar_Object',LinkDesc="Target",PropertyName=Targets)
}

Then I added to SkeletalMeshComponent.uc this function:


function OnBoneRemoval(SeqAct_BoneRemoval Action, SkeletalMeshComponent SkelMesh, name BoneName)
{	
    (SkelMesh).HideBoneByName(BoneName,PBO_Term);
}

Once again I get the same error. At this point I’m fairly sure it’s not a matter of syntax, so there must be something else that’s not working properly. Any suggestion?

EDIT: Found someone that encountered the same error as I did:

They said ‘solved the error part.
forgot the sequence class and method name in the function call as the error correctly tells me to do’

Not sure what to do about this?

I finally managed to get the node to work, but there’s still work to do. To make it work I removed the typecasting from the function, and also removed all parameters but one.

SeqAct_BoneRemoval.uc


/**
* This kismet node is used to hide a bone
*/
class SeqAct_BoneRemoval extends SequenceAction;

var() Object SkelMesh;
var() name BoneName;

defaultproperties
{
ObjName="Bone Removal"
ObjCategory="Misc"
VariableLinks.Empty
VariableLinks(0)=(ExpectedType=class'SeqVar_Object',LinkDesc="Target",PropertyName=Targets)
}

SkeletalMeshComponent.uc


function OnBoneRemoval(SeqAct_BoneRemoval Action)
{	
    HideBoneByName('b_MF_Head',PBO_Term);
}

Unfortunately I cannot pass the bone name as a variable to the function, which means I cannot change the bone from the Kismet. I could make a function for each bone but that’s really bad design and it would only postpone the problem: if instead of hiding the bone I want to use BreakConstraint I’ll need to pass the function the hit vector, and that MUST be done through kismet. Any idea on how to proceed?

is it both the casting and the params that break it? can you confirm it’s not just one of the two?

if it all fails you could make a new name var in the skeletalmeshcomponent where you set the bone from a new kismet node first, and then call your BoneRemoval kismet node which would use the previously saved bone name

I tried to test this but failed to do so. Since I cannot pass the skel mesh as a variable I tried hardcoding it in as a test. So I wrote:


function OnBoneRemoval(SeqAct_BoneRemoval Action)
{	
    SkeletalMeshComponent_32.HideBoneByName('b_MF_Head',PBO_Term);
}

Error, ‘SkeletalMeshComponent_32’: Bad command or expression


function OnBoneRemoval(SeqAct_BoneRemoval Action)
{	
    (SkeletalMeshComponent_32).HideBoneByName('b_MF_Head',PBO_Term);
}

Error, Bad or missing expression in parenthesis


function OnBoneRemoval(SeqAct_BoneRemoval Action)
{	
    'SkeletalMeshComponent_32'.HideBoneByName('b_MF_Head',PBO_Term);
}


function OnBoneRemoval(SeqAct_BoneRemoval Action)
{	
    'SkeletalMeshComponent_32'.HideBoneByName('b_MF_Head',PBO_Term);
}

For both of these I get ‘Error, Unexpected ‘.’ following ‘SkeletalMeshComponent_32’’.

Yeah I’ll try to do that now.

SkeletalMeshComponent_32 is the name of an instance of an object in the level, not a variable in the context of the class.
in short: you cannot call it like that

for testing try to just iterate on all skeletal mesh actors, and use the skeletalmeshcomponent from them

How would I go about doing that? I tried using a SkeletalMeshComponent variable added at the top but the function stops working it seems.

Ok so I tried a different approach:


function OnBoneRemoval(SeqAct_BoneRemoval Action)
{
    local Sequence GSeq;
    local array<SequenceObject> AllSeqObjs;
    local int i;
    local name FoundBone;

    GSeq = Actor.WorldInfo.GetGameSequence();
    if(GSeq != None)
    {
        GSeq.FindSeqObjectsByClass(class'SeqAct_BoneRemoval', true, AllSeqObjs);
        for(i = 0; i < AllSeqObjs.length; i++)
        {
            //FoundBone = SeqAct_BoneRemoval(SeqObjs*).Value;
        }
    HideBoneByName(FoundBone,PBO_Term);
    }
}

Unfortunately this doesn’t work because SkeletalMeshComponent is not in the same hierarchy as WorldInfo, or at least that’s the reason I think it doesn’t work. How can I call functions from 2 classes that are not in the same hierarchy?

the hierarchy doesn’t matter, it’s the scope. but the scope in this case is fine

this looks wrong though:


GSeq = Actor.WorldInfo.GetGameSequence();

What is even “Actor” ?

try this instead:


GSeq = class'WorldInfo'.static.GetWorldInfo().GetGameSequence();

Thanks for your help as usual.

I updated the code:



simulated function OnBoneRemoval(SeqAct_BoneRemoval action)
{	
	local Sequence GSeq;
	local array<SequenceObject> AllSeqObjs;
	local int i;
	local name FoundBone;

	GSeq = class'WorldInfo'.static.GetWorldInfo().GetGameSequence();
	if(GSeq != None)
	{
		GSeq.FindSeqObjectsByClass(class'SeqAct_BoneRemoval', true, AllSeqObjs);
		for(i = 0; i < AllSeqObjs.length; i++)
		{
			FoundBone = SeqAct_BoneRemoval(SeqObjs*).Value;
		}
	}
	HideBoneByName(FoundBone,PBO_Term);
}


I still get an error. :frowning:

Why do HideBone and similar fuctions not work if I pass them multiple values anyway? I would have been done ages ago if it wasn’t for that error.

can you post the error you’re getting now? :wink:

I apologize, I thought I did:

Error, Bad or missing expression for token: SeqAct_BoneRemoval, in ‘=’


FoundBone = SeqAct_BoneRemoval(SeqObjs*).Value;

what is Value in the first place? it’s not something that is defined in any of the versions of your SeqAct_BoneRemoval class code that you’ve posted so far

but well, why are you even looping through all the kismet nodes? your kismet node will call OnBoneRemoval() already!

I’m not really sure, I just copied the code off someone saying that was a way to store the variables in an array. What is the best way to get the bone name (and eventually the hit vector) without passing them to the function since I can’t do that?