Example problem: I have a class name which I know is of type Actor, but I don't know anything else about it. I need to check if this class is an Inventory, and if it is, then print its default MaxAmount.
Seems easy, right? Let's use GetDefaultByType for this:
Code: Select all
class Test
{
static void PrintMaxAmountIfInventory(name className)
{
let defaultInstance = GetDefaultByType((class<Actor>)(className));
let inventory = Inventory(defaultInstance);
if (inventory)
{
Console.Printf("Max amount of %s: %d", className, inventory.MaxAmount);
}
else
{
Console.Printf("%s is not of type Inventory.", className);
}
}
}
Code: Select all
Script error, "zscript.txt:ZSCRIPT" line 6:
Cannot cast a readonly pointer
Actually, this is completely understandable, so this is NOT the question - please read on. This error has appeared because the value GetDefaultByType returns is not an Actor but a readonly<Actor> - something akin to a const AActor* in C++ code. This is because we are not supposed to modify the instance GetDefaultByType has returned. We can only read its fields, and we can call its functions only if they are marked const. We can't write a new value to any field or call any non-const function. While I think it would be a useful feature to be able to change actors' defaults sometimes, that is a whole another story and thus also not the point of this thread.
Okay, so we can't cast the result to Inventory because it would violate const-correctness since Inventory is not readonly, and if we were allowed to do such a cast, then we could modify the instance. All right, let's try to cast the result to readonly<Inventory> then!
Code: Select all
... class and function declarations omitted
let defaultInstance = GetDefaultByType((class<Actor>)(className));
let inventory = (readonly<Inventory>)(defaultInstance);
if (inventory)
{
... rest omitted
Code: Select all
Script error, "zscript.txt:ZSCRIPT" line 6:
Unexpected 'readonly'
Expecting '-' or '+' or '++' or '--' or '(' or 'class' or identifier or string constant or 'super' or '~' or '!' or 'sizeof' or 'alignof' or integer constant or unsigned constant or float constant or name constant or 'false' or 'true' or 'null'
Code: Select all
... class and function declarations omitted
let defaultInstance = GetDefaultByType((class<Actor>)(className));
if (defaultInstance is "Inventory")
{
... rest omitted
Code: Select all
Script error, "zscript.txt:ZSCRIPT" line 7:
Cannot convert Pointer<Class<Actor>readonly > to Pointer<Class<Object>>
Okay, well, I thought, there has to be some way to achieve what I want! And indeed there is. It turns out that I need to cast not the instance that is returned by GetDefaultByType but the class name. Then check if the resulting class is not null. The correct code looks like this:
Code: Select all
class Test
{
static void PrintMaxAmountIfInventory(name className)
{
let inventoryClass = (class<Inventory>)(className);
if (inventoryClass)
{
let inventory = GetDefaultByType(inventoryClass);
Console.Printf("Max amount of %s: %d", className, inventory.MaxAmount);
}
else
{
Console.Printf("Class %s is not of type Inventory.", className);
}
}
}