Jump to content
Sign in to follow this  
Skelt

config.cpp /CfgSkeletons /CfgModel and animation

Recommended Posts

I accidentally posted this in the wrong forum yesterday morning, hopefully someone here can help.

Trying to get a unit to use a custom animation. Just a walk and idle would be fine. All of my configs are in

config.cpp:

class CfgPatches {
class my_unit_file
{
	units[] = {};
	weapons[] = {};
	requiredVersion = 0.00;
	requiredAddons[] = {"A3_Characters_F_Common", "A3_Characters_F"};
	version = "1.01";
};
};

class CfgVehicleClasses 
{
class myUnit 
{
	displayName = "MY_UNIT";
};
};

class CfgSkeltons
{
class Default
{
	isDiscrete = 1;
	skeletonInherit = "";
	skeletonBones[] = {};
};
class OFP2_ManSkeleton
{
	isDiscrete = 1;
	skeletonInherit="";
	skeletonBones[]=
	{
		"Pelvis","",
		"Spine","Pelvis",
		"Spine1","Spine",
		"Spine2","Spine1",
		"Spine3","Spine2",
		"Camera","Pelvis",
		"weapon","Spine1",
		"launcher","Spine1",
	//Head skeleton in hierarchy
		"neck","Spine3",
		"neck1","neck",
		"head","neck1",
	//New facial features
		"Face_Hub","head",
			"Face_Jawbone","Face_Hub",
				"Face_Jowl","Face_Jawbone",
				"Face_chopRight","Face_Jawbone",
				"Face_chopLeft","Face_Jawbone",
				"Face_LipLowerMiddle","Face_Jawbone",
				"Face_LipLowerLeft","Face_Jawbone",
				"Face_LipLowerRight","Face_Jawbone",
				"Face_Chin","Face_Jawbone",
				"Face_Tongue","Face_Jawbone",
			"Face_CornerRight","Face_Hub",
				"Face_CheekSideRight","Face_CornerRight",
			"Face_CornerLeft","Face_Hub",
				"Face_CheekSideLeft","Face_CornerLeft",
			"Face_CheekFrontRight","Face_Hub",
			"Face_CheekFrontLeft","Face_Hub",
			"Face_CheekUpperRight","Face_Hub",
			"Face_CheekUpperLeft","Face_Hub",
			"Face_LipUpperMiddle","Face_Hub",
			"Face_LipUpperRight","Face_Hub",
			"Face_LipUpperLeft","Face_Hub",
			"Face_NostrilRight","Face_Hub",
			"Face_NostrilLeft","Face_Hub",
			"Face_Forehead","Face_Hub",
				"Face_BrowFrontRight","Face_Forehead",
				"Face_BrowFrontLeft","Face_Forehead",
				"Face_BrowMiddle","Face_Forehead",
				"Face_BrowSideRight","Face_Forehead",
				"Face_BrowSideLeft","Face_Forehead",
			"Face_Eyelids","Face_Hub",
			"Face_EyelidUpperRight","Face_Hub",
			"Face_EyelidUpperLeft","Face_Hub",
			"Face_EyelidLowerRight","Face_Hub",
			"Face_EyelidLowerLeft","Face_Hub",
			"EyeLeft","Face_Hub",
			"EyeRight","Face_Hub",			
	//Left upper side
		"LeftShoulder","Spine3",
		"LeftArm","LeftShoulder",
		"LeftArmRoll","LeftArm",
		"LeftForeArm","LeftArmRoll",
		"LeftForeArmRoll","LeftForeArm",
		"LeftHand","LeftForeArmRoll",
		"LeftHandRing","LeftHand",
		"LeftHandRing1","LeftHandRing",
		"LeftHandRing2","LeftHandRing1",
		"LeftHandRing3","LeftHandRing2",
		"LeftHandPinky1","LeftHandRing",
		"LeftHandPinky2","LeftHandPinky1",
		"LeftHandPinky3","LeftHandPinky2",
		"LeftHandMiddle1","LeftHand",
		"LeftHandMiddle2","LeftHandMiddle1",
		"LeftHandMiddle3","LeftHandMiddle2",
		"LeftHandIndex1","LeftHand",
		"LeftHandIndex2","LeftHandIndex1",
		"LeftHandIndex3","LeftHandIndex2",
		"LeftHandThumb1","LeftHand",
		"LeftHandThumb2","LeftHandThumb1",
		"LeftHandThumb3","LeftHandThumb2",
	//Right upper side
		"RightShoulder","Spine3",
		"RightArm","RightShoulder",
		"RightArmRoll","RightArm",
		"RightForeArm","RightArmRoll",
		"RightForeArmRoll","RightForeArm",
		"RightHand","RightForeArmRoll",
		"RightHandRing","RightHand",
		"RightHandRing1","RightHandRing",
		"RightHandRing2","RightHandRing1",
		"RightHandRing3","RightHandRing2",
		"RightHandPinky1","RightHandRing",
		"RightHandPinky2","RightHandPinky1",
		"RightHandPinky3","RightHandPinky2",
		"RightHandMiddle1","RightHand",
		"RightHandMiddle2","RightHandMiddle1",
		"RightHandMiddle3","RightHandMiddle2",
		"RightHandIndex1","RightHand",
		"RightHandIndex2","RightHandIndex1",
		"RightHandIndex3","RightHandIndex2",
		"RightHandThumb1","RightHand",
		"RightHandThumb2","RightHandThumb1",
		"RightHandThumb3","RightHandThumb2",
	//Left lower side
		"LeftUpLeg","Pelvis",
		"LeftUpLegRoll","LeftUpLeg",
		"LeftLeg","LeftUpLegRoll",
		"LeftLegRoll","LeftLeg",
		"LeftFoot","LeftLegRoll",
		"LeftToeBase","LeftFoot",
	//Right lower side
		"RightUpLeg","Pelvis",
		"RightUpLegRoll","RightUpLeg",
		"RightLeg","RightUpLegRoll",
		"RightLegRoll","RightLeg",
		"RightFoot","RightLegRoll",
		"RightToeBase","RightFoot"	
	};
	// location of pivot points (local axes) for hierarchical animation
	pivotsModel="A3\anims_f\data\skeleton\SkeletonPivots.p3d";	
};
};

class CfgModels 
{

class Default
{
	sectionsInherit="";
	sections[] = {};
	skeletonName = "";
};

class ArmaMan : Default
{
	htMin = 60;
	htMax = 1800;
	afMax = 30;
	mfMax = 0;
	mFact = 1;
	tBody = 37;

	sections[]=
	{
		"osobnost","Head_Injury","Body_Injury","l_leg_injury","l_arm_injury","r_arm_injury","r_leg_injury","injury_body", "injury_legs", "injury_hands",
		"clan","clan_sign","Camo","CamoB","Camo1","Camo2","personality","hl", "injury_head"	
	};
	skeletonName = "OFP2_ManSkeleton";
};

class Animations
{

	class myIdle
	{
		type = "direct";
		source = "user";
		selection = "";
		axis = "";
		memory = 1;
		sourceAddress="loop";
		minValue = 0;
		maxValue = 0;
		angle0 = 0;
		angle1 = "rad -360";

	};
	class myWalk
	{
		type = "translation";
		source = "user";
		selection = "";
		axis = "";
		memory = 1;
		sourceAddress="loop";
		minValue = 0;
		maxValue = 1;
		angle0 = 0;
		angle1 = "rad -360";
	};
};

};

class CfgMovesBasic; 


class CfgMovesMaleSdr: CfgMovesBasic 

{
skeletonName="OFP2_ManSkeleton";
gestures="CfgGesturesMale"; 

class States
{
	//Idle1
	class AidlPercMstpSnonWnonDnon_AI; //Standard A3 civi idle
	class myIdle : AidlPercMstpSnonWnonDnon_AI
	{
		looped = 1; 
		speed = -5; 
		file = "\my_unit_file\data\anims\myIdle.rtm"; //thought to be replaced by myIdle
		canBlendStep = 0; 
		minPlayTime= 0.95; 

		//If they are the same, use ConnectTo[] instead.
		//InterpolateTo[] = 
		//{
		//	"AidlPercMstpSnonWnonDnon_AI", 0.5  

		//};
	};
	//Walk Forward
	class AmovPercMwlkSnonWnonDf; //Standard a3 civi walk
	class myWalk : AmovPercMwlkSnonWnonDf
	{
		looped = 1;
		speed = -5;
		file = "\my_unit_file\data\anims\myWalk.rtm"; //thought to be replaced by myWalk
		canBlendStep = 0;
		minPlayTime=0.95;

		//InterpolateTo[] =
		//{
		//	"AmovPercMwlkSnonWnonDf", 0.5
		//};
	};
};
};

//CfgVehicles---------------
class CfgVehicles {


class C_man_polo_1_F;

class myguy1: C_man_polo_1_F
{
	side = 3;
	scope = 2;
	author = "Bones";
	vehicleClass = "myUnit";	
	uniformClass = "my_texture";
	displayName = "My Unit In Game";
	hiddenSelections[] = {"Camo"};
	hiddenSelectionsTextures[] = {"\my_unit_file\data\clothing\my_texture.paa"};
};



//CfgWeapons---------------
class CfgWeapons 
{

// Uniforms
class U_C_Poloshirt_blue;
class UniformItem;

class my_texture: U_C_Poloshirt_blue {
	scope = 2;
	displayName = "My Unit In Game";
	hiddenSelectionsTextures[] = {"\my_unit_file\data\clothing\my_texture.paa"};

	class ItemInfo: UniformItem {
		uniformModel = "-";
		uniformClass = "my_texture";
		containerClass = "Supply50";
		mass = 50;
		hiddenSelections[] = {"Camo"};
	};
};	
};

I can get my custom skins into the game, but they inherit from BI civilian units. You can probably tell from my config I have a bit of trouble understanding how it all works together. If someone could tell me how to get this unit to use a custom walk/run, and idle animation I'd be ecstatic. My report file is clean and the units show in the editor, but after many of tries and changes to the configs, I can't get him to change his animation.

I was planning on leaving everything in the config.cpp, don't particularly see a need to separate them.

Share this post


Link to post
Share on other sites

CfgSkeltons and CfgModels is meant to be defined in the model.cfg and is merged into the p3d when binarized.

no idea if that approach works; not much into anims - if you were to call them via SQF, it might work already.

However adding to or replacing the standard anims is a different ball game.

Best check other addons/mods that have done that

Share this post


Link to post
Share on other sites

Yeah, I decided to define them in config.cpp for now while I get things working (still should work the same). Although I am unsure of their proper nesting / order, or even if that matters at all.

It would appear most of the mods I have been through that made significant changes all have their configs in binary, which is not user friendly at all, or if I can get into them, they are related to A2, which doesn't help much either.

Share this post


Link to post
Share on other sites

The order of base classes does not matter.

The inheritance and such looks fine.

You can derapify a config.bin to cpp (text) with eliteness/extractpbo/derap from mikero.

Share this post


Link to post
Share on other sites

You need to make a .rtm animation for character models, not a model.cfg+class animations type animation. Those are only for weapons and vehicles.

Configuring player animations is described in this thread:

http://forums.bistudio.com/showthread.php?177500-Animation-explanation-of-the-magic-behind

Making the .rtm is the hard part.

Share this post


Link to post
Share on other sites

You can safely delete CfgSkel(e!)tons and CfgModels. The skeleton to be used by human characters in the game already exists and needs no modification. cfgModels is used for something else entirely, not for RTM character animations (motion captured or keyframed). It's used for simple procedural animations, like rotations around one axis, translation, hiding objects, etc..

Focus on CfgMovesMaleSdr. If you want to overwrite the default civilian/unarmed idle, don't create a new animation (class myIdle), just replace the file path of AidlPercMstpSnonWnonDnon_AI to point to your RTM instead. But pay attention, there is not just one single idle animation for unarmed civilians, there are several, and they are played randomly. Also, "AidlPercMstpSnonWnonDnon_AI" refers only to the AI and not player characters.

If you unpack anims_f.pbo, and look at the config, if you search for "class CivilStandActions" you will se that the default animation for that is "AmovPercMstpSnonWnonDnon". And now if you look further, moving from Actions to States, and look up "class AmovPercMstpSnonWnonDnon", you will see that it has 6 other animations that are played randomly/alternatively:

		class AmovPercMstpSnonWnonDnon: StandBase
	{
		variantsPlayer[]=
		{
			"AidlPercMstpSnonWnonDnon_G01",
			0.16,
			"AidlPercMstpSnonWnonDnon_G02",
			0.16,
			"AidlPercMstpSnonWnonDnon_G03",
			0.16,
			"AidlPercMstpSnonWnonDnon_G04",
			0.16,
			"AidlPercMstpSnonWnonDnon_G05",
			0.16,
			"AidlPercMstpSnonWnonDnon_G06",
			0.16
		};
...

If you don't want to alter the game content, but would rather add your things to them, create your own moves class and inherit from CfgMovesMaleSdr, then do the modifications inside that. And point your cfgVehicles human, to use your newly created moves class.

The introduction here might clarify a few things about animation config:

https://community.bistudio.com/wiki/CfgMoves_Config_Reference

ArmA2 mods can be just as educational as ArmA3 ones, regarding config, and animation config. All config.bin files can be converted to human readable config.cpp.

Edited by teaCup

Share this post


Link to post
Share on other sites

You can derapify a config.bin to cpp (text) with eliteness/extractpbo/derap from mikero.

Ah thank you, I had been looking for something that would work; I guess my google search criteria was not up to snuff, because all I found was people saying it was prohibited by BI to de-bin it.

Configuring player animations is described in this thread

Yeah I followed that thread and incorporated it into my config thinking it somehow worked with CfgModel & CfgSkeleton. From looking at CfgMovesBasic & CfgMovesMaleSdr, it seemed as though I would put in the animation I wanted to change, then link it to my custom file:

//Warning! This code is not valid and for illustration purposes only!

class CfgMovesBasic; 
class CfgMovesMaleSdr: CfgMovesBasic 
{
skeletonName="OFP2_ManSkeleton";
gestures="CfgGesturesMale"; 

class States
{
	//Idle1
	class AidlPercMstpSnonWnonDnon_AI;            //<---------- I thought I put the animation I wanted to change here
	class myIdle : AidlPercMstpSnonWnonDnon_AI //<---------inherited from it here
	{
		looped = 1; 
		speed = -5; 
		file = "\my_unit_file\data\anims\myIdle.rtm"; //<-----chose my new animation here
		canBlendStep = 0; 
		minPlayTime= 0.95; 
	};

I have a bunch of .rtm animation files from Arma 2, which I have read from a BI developer they should work just fine provided they are not facial animations. Definitely moving in the right direction with you guys help though!!

You can safely delete CfgSkel(e!)tons and CfgModels.

Done Sir! Done! Can't say I am sad to see them go, I thought it seemed awfully strange to have a need to define which bone would be effected by an animation...

Edit: You are also quite correct with my lovely misspelling of Skeletons... you'd think with a name like Skelt I might get that one right lol. Sometimes it doesn't pay to stare at code all night :)

create your own moves class and inherit from CfgMovesMaleSdr

That seems like the best option for me. Looking at github, I found a nice example (first class shown only, the rest can be found here):

// Generated by unRap v1.06 by Kegetys

class CfgMovesMaleSdr : CfgMovesBasic {
skeletonName = "OFP2_ManSkeleton";
gestures = "CfgGesturesMale";

class States {
	class DeadState : Default {
		actions = "DeadActions";
		file = "\ca\Anims\Characters\data\Anim\Sdr\dth\pne\stp\ras\Rfl\AdthPpneMstpSrasWrflDnon_1";
		speed = 1.67;
		looped = "false";
		onLandBeg = "true";
		onLandEnd = "true";
		soundEnabled = "false";
		terminal = "true";
		canPullTrigger = "true";
		headBobMode = 2;
		ConnectTo[] = {};
		InterpolateTo[] = {};
	};

Looking through it, it would appear I will need to define each animation individually, which isn't too much of a problem because I only need a few. But as in some examples, it shows:

variantsPlayer[] = {"AinvPknlMstpSnonWnonDnon_medic0", 0.15, "AinvPknlMstpSnonWnonDnon_medic1", 0.15, "AinvPknlMstpSnonWnonDnon_medic2"...

If I just point the file location to the first (in this example _medic0), will the engine automatically know where to look for the following animations? It looks as though only one file can be pointed to per class. Could you give me the bare bones inheritance framework? I have my units, I'm putting together the class:

 
MyCustomMoves : CfgMovesMaleSdr
class States
{
   class myIdle
   {
       //---> my anim data <---
   };
};

Still a bit shotty as how to get my vehicle class man to inherit and use them, but I have a bit of coding to do before I get to that.

Thank you all so much for your helpful replies*

Edited by Skelt

Share this post


Link to post
Share on other sites
Still a bit shotty as how to get my vehicle class man to inherit and use them

I'd suggest trying something like this (code below not tested):

class CfgMovesMaleSdr;
class [color="#B22222"][b]MY_MOVES[/b][/color]: CfgMovesMaleSdr
{
skeletonName="OFP2_ManSkeleton";
gestures="CfgGesturesMale";
class States
{
	class AmovPercMstpSnonWnonDnon
	{
		variantsPlayer[]={};
		file = "\my_unit_file\data\anims\myIdle.rtm";
	};
};
};

class CfgVehicles 
{
class C_man_polo_1_F;
class myguy1: C_man_polo_1_F
{
	side = 3;
	scope = 2;
	author = "Bones";
	vehicleClass = "myUnit";	
	uniformClass = "my_texture";
	displayName = "My Unit In Game";

	[color="#B22222"][b]moves="MY_MOVES";[/b][/color]
};
};

Notice how I emptied the variantsPlayer array. This way, if you have only one idle animation, you can have that one loop for ever, instead of having the animation state-machine keep randomly alternating between 6 different idle animations.

Share this post


Link to post
Share on other sites

That is exactly what I needed, although easier than expected! (moves = ).

Notice how I emptied the variantsPlayer array. This way, if you have only one idle animation, you can have that one loop for ever

That is incredibly important to my implementation! Right now I have my full framework in place (besides for the variantsPlayer[]={}; which I will add now), just need to plug in my rtm files and begin debugging this bad boy haha. Man, you guys got me straightened out in no time flat! I'd imagine I will run into something, but for now: to the code!

Share this post


Link to post
Share on other sites

Getting errors:

No geometry level found in collision shape

ca\anims\characters\data\geom\sdr\geom_adth.p3d

Cannot open object

ca\anims\characters\data\geom\sdr\geom_adth.p3d

That is the collision mesh from the CfgMoves reference. Not sure why it is saying it can't open it. Any thoughts? Thanks

Fixed: Just removed it all together...

Still have some funny behavior:

My AI plays the correct idle animation, but they are stuck in that loop, and cannot move otherwise.

Also, for some reason the change is impacting the player controls, the player also get's stuck in what ever animation he enters.

Edited by Skelt

Share this post


Link to post
Share on other sites
Cannot open object

ca\anims\characters\data\geom\sdr\geom_adth.p3d

That path points to an ArmA2 collision model, one made specifically for a death animation ("dth"). ArmA3 obviously can't find the file, and even if it did, it would likely be the wrong collision shape for your idle animation. ArmA3 collision paths look like this (rooted in A3\anims_f rather than ca\anims):
collisionShape="A3\anims_f\Data\Geom\Sdr\Perc_Wnon.p3d";
Older tutorials and ArmA1/2 configs are good for learning the principles, but for integrating your addon into the current ArmA3 structure, you must unpack anims_f.pbo and look at the configs inside.

Characters stuck in animation? If I would have to guess, maybe it's misconfigured ConnectTo[]= and InterpolateTo[]= properties. But we're not psychic, you will have to post your config if you want assistance.

Share this post


Link to post
Share on other sites

Hey teaCup, you were exactly right my friend. I did not have my ConnectTo / InterpolateTo-From in correctly -- I had animation names in the array rather than class names. I got my animations working, but I had to go with what seems like an odd implementation because of CfgMovesMaleSdr / CfgMovesBasic in regard to the Actions class. Seemed like no matter what I tried it would always pop up a missing action (state). So in order to get around incorporating the entire 4000 or so lines of class Actions I used CfgMovesAnimal_Base_F which got around the missing actions and appears so far to work for my AIs. I am just now testing it. So far so good, I havn't noticed any funny behavior but it will need a few more hours of testing.

Do you happen to know any way around the missing actions (class Actions : MyActions {...}; gives missing actions at run-time) when inheriting from CfgMovesMaleSdr / CfgMovesBasic.

I will probably be editing my first post in this thread to change it to a tutorial for getting animations into the game for other people who are in, and will be in my position in the future. Thanks again for your help teaCup, it was extremely valuable to my project.

Share this post


Link to post
Share on other sites

Man IS an animal, so philosophically, i have no beef with you resorting to CfgMovesAnimal_Base_F :) If it suits your needs, and you can live with the reduction in functionality, great. But in principle, you should try to inherit all of the human movement tree. It shouldn't be that complicated, you don't even have to touch the Actions section for what you want to achieve (if I understood your intentions), nor should it involve mass quoting of the original game config.cpp normally.

class Actions : MyActions {...};
Shouldn't that be the other way around?
class MyActions : Actions {...};
Usually, your custom actions are derived/inherited from the default game actions and not the other way around. Don't be a masochist.. :)

Extending or modifying an existing class with a new one, is not that complicated. Basic OOP. Debugging any config errors like undefined base classes or unintentional overwriting of base classes is not that complicated. Make sure to check the RPT as well, because ArmA will only give you one popup message for each kind of error, and will write the rest of the errors to the RPT. And as always, upload or post your config if you need help, it's next to impossible to assist you in the blind.

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×