Guide: Interacting with game objects - AurieFramework/YYToolkit GitHub Wiki

Note

This guide is written with YYToolkit Next in mind. While it is possible to adapt the techniques below to YYTK Legacy, support will not be provided for such cases.

Accessing struct member variables

While making games, developers often use the concept of structs to group variables together. Internally, these structs are represented as YYObjectBase objects. Variables are stored in a hashmap accessible under m_YYVarsMap when using Internal Structure Access.

For demonstration purposes, let us access the item_value variable, located inside self.my_struct.nested_struct, and change its value to 50.

Method 1: Using GetInstanceMember

This is the most verbose method, and is the only one that allows C++ code to safely access any struct's member variables. Due to the AurieStatus value returned from the function, code can act upon the member variable not existing and gracefully exit.

AurieStatus last_status = AURIE_SUCCESS;
RValue* my_struct = nullptr;

// Access self.my_struct
last_status = module_interface->GetInstanceMember(
    self,
    "my_struct",
    my_struct
);

if (!AurieSuccess(last_status)) { /* ... */ }

// Access my_struct.nested_struct
RValue* nested_struct = nullptr;
last_status = module_interface->GetInstanceMember(
    *my_struct,
    "nested_struct",
    nested_struct
);

if (!AurieSuccess(last_status)) { /* ... */ }

// Access nested_struct.item_value
RValue* item_value = nullptr;
last_status = module_interface->GetInstanceMember(
    *nested_struct,
    "item_value",
    item_value
);

if (!AurieSuccess(last_status)) { /* ... */ }

// Change item_value to 50
*item_value = 50;

Method 2: Using GetMember or GetRefMember

A slightly cleaner way is to use the GetMember and GetRefMember methods of RValue.

These functions are thin wrappers around GetInstanceMember. They log errors to the console, and return nullptr on failure instead of a status code. While both functions appear to do the same thing, there is a key difference between them.

  • GetMember returns a copy of the variable.
    • Your code owns this copy, and changes to it will not reflect inside of the game's copy.
    • The variable is safe to store for later use.
  • GetRefMember returns a pointer to the variable.
    • The game owns the variable, and changes to it are instantly reflected inside of the game's variable.
    • The pointer is not safe to store, as the parent object may be destroyed, invalidating it.

The two functions are best used in cases where the programmer still needs some level of error handling, but doesn't need the full status code that GetInstanceMember provides.

// Convert self to an RValue
RValue rv_self = self;

// Access self.my_struct
RValue* my_struct = rv_self.GetRefMember("my_struct");

if (!my_struct) { /* ... */ }

// Access my_struct.nested_struct
RValue* nested_struct = my_struct->GetRefMember("nested_struct");

if (!nested_struct) { /* ... */ }

// Access nested_struct.item_value
RValue* item_value = nested_struct->GetRefMember("item_value");

if (!item_value) { /* ... */ }

// Change item_value to 50
*item_value = 50;

Method 3: The one-liner

If you are absolutely sure that access to the variable cannot fail, you may choose to use the indexing operators.
While this syntax is by far the most eye-pleasing, it offers no error handling, and may crash your game if a non-existent variable is accessed.

// Convert self to an RValue
RValue rv_self = self;

// Access the item_value variable directly
rv_self["my_struct"]["nested_struct"]["item_value"] = 50;

Note

For const RValue objects, the indexing operator does not return references, and instead returns copies.

⚠️ **GitHub.com Fallback** ⚠️