Jump to content
kresjah

Confusion with custom classes in description.ext

Recommended Posts

Quick background

I've created a script for automatic doors. It works more or less as intended, however, I'm now in the process of polishing it as much as possible. As part of that process, I plan to move some of the settings away from the actual scripts and into description.ext as classes. I'm currently running the 1.56 RC. I've run into some behaviour I find confusing with fetching both lists of subclasses with inheritance, as well as getting values "the correct way". I'll explain the problems first, but if needed, you'll find the description.ext at the bottom of the post.

 

First problem

First things first, fetching values from these classes. After reading on the BIKI, using getMissionConfigValue seemed like the way to go. However, instead of returning values, it seems to return a hash. Example:

hint format["Value: %1", getMissionConfigValue "CfgAutodoor" >> "Vehicles" >> "Land_Airport_left_F" >> "Door_8" >> "disablerBIS" >> "value"];
// Displays Value: 02558CB8

I'd expected this to return 1 (in reference to the description.ext I've attached below). Ok, so I tried getMissionConfig combined with getNumber, which does indeed fetch the right value. I was, however, under the impression that the whole point of the getMissionConfigValue command was to be able to do just that. Have I misunderstood something here?

hint format["Value: %1", getNumber(getMissionConfig "CfgAutodoor" >> "Vehicles" >> "Land_Airport_left_F" >> "Door_8" >> "disablerBIS" >> "value")];
// Displays Value: 1

Second problem

Now, I want to return the children of some of the subclasses so I can use their data to set up the doors. My attempts fail though, as it seems not to return the children of classes that have a parent. Oddly enough, fetching a value from within the inherited class still works. Let's look at the  CfgAutodoor / Vehicles / Land_Airport_left_F class. Land_Airport_left_F here inherits from Land_Airport_side_base_F. As you might have noticed, Land_Airport_left_F is the same class I fetched the value from in the first problem, which should as far as I can see indicate that it does indeed inherit its properties correctly. What I want to do is use the script is to look up Land_Airport_left_F, then get an array in return which contains its children (which would be Door_7 and Door_8).

 

I've tried two methods here which both return an empty array for some reason.

_autodoorObjectCfg = getMissionConfig "CfgAutodoor" >> "Vehicles" >> "Land_Airport_left_F";
_autodoorObjectCfg = "true" configClasses (getMissionConfig "CfgAutodoor" >> "Vehicles" >> "Land_Airport_left_F");

This had me stumped at first. I could fetch the actual values from inside it as detailed in the first problem, but from some reason it refuses to list the children. Then I tried the following:

_autodoorObjectCfg = "true" configClasses (getMissionConfig "CfgAutodoor" >> "Vehicles" >> "Land_Airport_side_base_F");

Lo, and behold, the array suddenly has the two expected entries. So, it doesn't work with the class I want, but if I fetch the parent I can get its children? Is there no way to do this by requesting the inherited children from Land_Airport_left_F instead of using a workaround by asking its parent (Land_Airport_side_base_F) instead? Am I missing something here?

 

Description.ext

For the sake of clearing up things, and incase I've done something wrong with the classes themselves triggering my problems, here's the description.ext I am using:

allowFunctionsLog = 1;

class CfgFunctions {
    // tag = "KRSJ";
    class KRSJ
    {
        class Animation
        {
            class isFullyAnimated {};
        };
        class Array
        {
            class makeSureIsArray {};
        };
        class Autodoor
        {
            class autodoorGetDoorList {};
            class autodoorGetNextEventTime {};
            class autodoorInit {};
            class autodoorInitObject {};
            class autodoorIsActive {};
            class autodoorIsDoorFullyAnimated {};
            class autodoorIsNextEventTimePassed {};
            class autodoorIsSensorTriggered {};
            class autodoorSetAnimations {};
            class autodoorSetAnimationsFromDoorName {};
            class autodoorSetNextEventTime {};
            class autodoorSetSensorState {};
        };
        class AutodoorSM
        {
            class autodoorSMActivate {};
            class autodoorSMClosed {};
            class autodoorSMClosing {};
            class autodoorSMClosingActive {};
            class autodoorSMDeactivate {};
            class autodoorSMDeactivated {};
            class autodoorSMHalt {};
            class autodoorSMHalted {};
            class autodoorSMOpen {};
            class autodoorSMOpening {};
            class autodoorStateMachine {};
        };
        class Misc
        {
            class getWorldPositionFromSelection {};
        };
    };
};


class CfgAutodoor {
    class Vehicles {
        class Land_Airport_side_base_F {
            class Door_7 {
                class delays {
                    stayOpen = 5;
                    reopen = 0.5;
                    closeReactivate = 0.1;
                };
                class disablerBIS {
                    value = 1;
                    varname = "bis_disabled_Door_7";
                };
                doorList[] = {
                    "Door_7A_move",
                    "Door_7B_move"
                };
                class sensor {
                    radius = 4;
                    triggerSelection = "Door_7_trigger";
                };
            };
            class Door_8: Door_7 {
                class disablerBIS: disablerBIS {
                    varname = "bis_disabled_Door_8";
                };
                doorList[] = {
                    "Door_8A_move",
                    "Door_8B_move"
                };
                class sensor: sensor {
                    triggerSelection = "Door_8_trigger";
                };
            };
        };
        class Land_Airport_right_F: Land_Airport_side_base_F {};
        class Land_Airport_left_F: Land_Airport_side_base_F {};
    };
};

Share this post


Link to post
Share on other sites

Configs are somewhat difficult to figure out, I even had to get help when I first wanted to learn how to use them too. Once you get the hang of it, it never goes away though.

 

For your first problem, you're assuming that commands, once introduced, will always work as intended and cannot get broken by an update. It's possible, though, I can't say if it's ever happened since I don't use the dev branch.

If you can't get it to work at all, you need to use the commands getNumber, getText, getArray to get data from a config.

getNumber (missionConfig >> "CfgAutodoor" >> "Vehicles" >> "Land_Airport_side_base_F" >> "delays" >> "stayOpen");
getText (missionConfig >> "CfgAutodoor" >> "Vehicles" >> "Land_Airport_side_base_F" >> "disablerBIS" >> "varname");
getArray (missionConfig >> "CfgAutodoor" >> "Vehicles" >> "Land_Airport_side_base_F" >> "doorList");

To return a child from a class (including child classes), you just need to use the select command and use a config as input

_config = missionConfigFile >> "CfgAutodoor" >> "Vehicles" >> "Land_Airport_side_base_F";
_count = (count _config) - 1;
for "_i" from 0 to _count do
{
	systemChat str (_config select _i); //Each is a child - includes child classes
};

I believe forEach will not work with configs as they are not arrays, however. It is necessary to use a for loop. Configs are always parsed in the same order as the description.ext

_config = missionConfigFile >> "CfgAutodoor" >> "Vehicles" >> "Land_Airport_side_base_F";
_config select 0; //will always refer to "Door_7" class
_config select 1; //will always refer to "Door_8" class
//^ unless you manually change the order

//You could also use select to get to that config
_config = missionConfigFile >> "CfgAutodoor";
_vehiclesClass = _config select 0;
_airportClass = _vehiclesClass select 0; 

Using a combination of these, you can get all doors in a class (really getting all children), and execute code on it

_configParent = missionConfigFile >> "CfgAutodoor" >> "Vehicles" >> "Land_Airport_side_base_F";
_count = (count _configParent) - 1;
for "_i" from 0 to _count do
{
	_doorClass = _configParent select _i;
	_delays = _doorClass select 0; //Alternatively you could use _delays = _doorClass >> "delays";
	_disablerBIS = _doorClass select 1; //Alternatively you could use _disablerBIS = _doorClass >> "disablerBIS"
	_doorList = getArray (_doorClass select 2); //Alternatively you could use _doorList = getArray (_doorClass >> "doorList");
	_sensor = _doorClass select 3; //Alternatively you could use _sensor = _doorClass >> "sensor";
};

For classes that you know the structure of, you're probably better off using the >> (config navigation) rather than doing hard-coded select (It could result in an error idk).

Hope this helps

Share this post


Link to post
Share on other sites

The whole process of getting values from classes inside missionConfig does seem very flakey indeed. Especially when using some of the newer commands.

What with the inclusion of Eden coming and the whole modability of it pushing us towards storing data in the sqm and being able to retrieve said data via getMissionConfig is a little worrying.

 

As for your second question you can retrieve the inherited class values by using configProperties..

configProperties [ (getMissionConfig "CfgAutodoor" >> "Vehicles" >> "Land_Airport_left_F"), "isclass _x",true]

Which will return an array holding the config paths to the two inherit classes Door7 and Door8.

Which you can then retrieve their values like...

getarray(((configProperties [ (getMissionConfig "CfgAutodoor" >> "Vehicles" >> "Land_Airport_left_F"), "isclass _x",true]) select 0) >> "doorlist")

Which would return Door7's doorList array. Or drill down even further via configProperties to retrieve the properties and  the values you need.

Share this post


Link to post
Share on other sites

Thank you both for your answers.

 

--------

EDIT: I've gotten replies on the ticket, and it was indeed me who was misinterpreting the command. I missed this little detail on the BIKI: "Returns value of given scenario attribute from the 1st tier." The key words here being "1st tier". An honest mistake, but still a mistake. Regardless, I think it is a shame there is no native alternative for returning a value without resorting to scripting solutions for returning the right type of value.

 

Leaving the link to the ticket though in just in case: http://feedback.arma3.com/view.php?id=27936

--------

 

@dreadedentity

Nah, not really assuming that they always work as intended, but rather that there is always a higher likelihood of user error (yep, me doing something wrong like using incorrect syntax or misunderstanding its purpose) than actual bugs. I couldn't find anything about it in the bugtracker nor when searching the forums either.

 

I did forget to mention that I had tried the count/for/select variant. Thing is that it doesn't quite work. Well, your example works, as it requests data from the base class (Land_Airport_side_base_F). If you trying doing the exact same and just change Land_Airport_side_base_F with Land_Airport_left_F (which inherits from the same base class) you end up getting nothing.

 

Sure, as mentioned, I can get it to work using getText/getNumber/getArray combined with getMissionConfig, but as far as I've understood the entire point of getMissionConfigValue was to be able to get a value without knowing in advance what type of value would be returned and having to create special cases for it.

 

@larrow

It is a bit worrying indeed. By all means, I think it is a good move per se, but it requires that the framework around it works.

 

I did look at the BIKI but for some reason the configProperties command had completely eluded me. Haven't gotten around to testing it, but it seems like it should do the trick.

 

Whilst the difference is probably neglible, I still think using configClasses would be a better solution (that is, if it read from classes it is inherited from). After all, configProperties requires a scripted condition check to only return subclasses, whilst configClasses would do it natively. But yeah, I don't think anyone would notice the performance difference - it's just the perfectionist in me. :P

 

Regarding parsing via classes inherited from, I did find a ticket on the tracker today... but it worries me that it was reported in 2014 with version 1.26, that it was assigned in 2014 and nothing has happened since:

http://feedback.arma3.com/view.php?id=20479

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

×