Добавлен , опубликован

Программирование Корсаров: продвинутый уровень

Содержание:
Я уже говорил, что ООП в Корсарах нет. И тем не менее, в уроке о типах данных я писал о неких структурах, которые называются объектами. Давайте разбираться.

Объекты

Объект представляет собой древовидную текстовую структуру произвольной формы. Это означает, что он может хранить любое количество полей в текстовой форме (string), хотя указание числа без кавычек тоже допускается.
// синтаксис
object object_name;
    
// пример
object Sky;

if (!isEntity(&Sky))
{
    CreateEntity(&Sky, "Sky");
}

Sky.State = "sunset";
Sky.Size = 10;
Sky.Angle = "25.0f";

float skyAngle = stf(Sky.Angle);    // 25.0f
int skySize = sti(Sky.Size);        // 10
Не забываем, что данные в структуре хранятся в текстовом формате string. Поэтому перед использованием их необходимо конвертировать в соответствующий тип данных при помощи функций, которые мы рассматривали в разделе преобразование типов.
Неинициализированные объекты по-прежнему могут создаваться и использоваться в скриптах, за исключением того, что они не будут восприниматься таковыми API движка.
К объектам также можно получить доступ по ссылке, определяемой как ref. Обычно это используется для доступа к определенному объекту внутри массива. Сама ссылка создается при помощи функции makeref(). Синтаксис использования ссылки идентичен использованию объекта.
// синтаксис
object obj_name;
ref ref_name;
makeref(ref, obj);

// пример
object SkyStates[SKY_STATES_N];
ref Sky;
int n = 0;

// итерируем элементы
makeref(Sky, SkyStates[n]);
Sky.State = "sunset";
Sky.Size = "10";
Sky.Angle = "25.0f";
n++;
К атрибуту объекта также можно получить доступ по ссылке типа aref. Аналогично ref, для создания такой ссылки есть специальная функция makearef():
// синтаксис
obj obj_name;
aref aref_name;
makearef(aref, obj);

// пример
object Item;
aref ItemType;

Item.type = "sword";

makearef(ItemType, Item.type);
Если вы обращаетесь к атрибуту через переменную, следует поместить эту переменную в скобки:
aref aSky;
string attribute = "d20";

aSky.Dir.d20 = "NNE";         // OK
aSky.Dir.(attribute) = "NNE"; // OK
aSky.Dir.attribute = "NNE";   // ошибка
Цитата Rosarak:
Движок по-разому воспринимает числа, переданные в виде int и string.
Нужно быть очень внимательным и, во избежание путаницы, конвертировать все числа в string при помощи ф-ций вроде its(i) или сложение с пустой строкой s = "" + i. А лучше вообще отказаться от числовых имен атрибутов и всегда добавлять к имени какую-то букву.
int iNumber = 4;
string sNumber = "4";

pchar.biba.(iNumber).boba = "some data";	// это один атрибут
pchar.biba.(sNumber).boba = "some data";	// а это совсем другой

string sNumber = its(iNumber);
pchar.biba.(sNumber).boba = "some data";	// а вот это попадет в тот же атрибут, что на предыдущей строке

string sNumber = "" + iNumber;
pchar.biba.(sNumber).boba = "some data";	// и это тоже

Атрибуты

Для удобной работы с атрибутами есть целый ряд функций. Они позволяют уйти от ручного доступа к атрибутам объекта, позволяя таким образом автоматизировать обработку и поиск атрибутов в цикле, а также создавать унифицированные функции.

Get​Attributes​Num

// синтаксис
int GetAttributesNum(object obj);
int GetAttributesNum(ref obj);
int GetAttributesNum(aref attribute);

// пример
int count = GetAttributesNum(arRoot);
for (i = 0; i < count; i++)
{
    aref attribute = GetAttributeN(arRoot, i);
    // ... 
    // Манипуляции с атрибутом
    // ... 
}
GetAttributesNum - подсчитывает, сколько дочерних атрибутов имеет объект (нерекурсивно).
object obj, ref obj, aref attribute - объект или атрибут, для которого будут посчитаны дочерние атрибуты.
Как правило, эта функция используется вместе с GetAttributeN() для итерирования атрибутов.

GetAttributeN

// синтаксис
aref GetAttributeN(object obj, int index);
aref GetAttributeN(ref obj, int index);
aref GetAttributeN(aref attribute, int index);

// пример
int count = GetAttributesNum(arRoot);
for (i = 0; i < count; i++)
{
    aref attribute = GetAttributeN(arRoot, i);
    // ... 
    // Манипуляции с атрибутом
    // ... 
}
GetAttributeN - осуществляет доступ к дочернему атрибуту по индексу.
object obj, ref obj, aref attribute - объект или атрибут, дочерние атрибуты которого перебираются.
int index - порядковый номер атрибута, к которому осуществляется доступ.
Эта функция, в основном, используется в цикле, совместно с GetAttributeNum(), для перебора атрибутов объекта.

Get​Attribute​Name

// синтаксис
string GetAttributeName(object obj);
string GetAttributeName(ref obj);
string GetAttributeName(aref attribute);

// пример
object Test;
Test.value = "hello";
string attrName = GetAttributeName(Test.value); // "value"
GetAttributeName - возвращает имя переданного атрибута или объекта.
object obj, ref obj, aref attribute - объект или атрибут, имя которого нужно получить.

Get​Attribute​Value

// синтаксис
string GetAttributeValue(object obj);
string GetAttributeValue(ref obj);
string GetAttributeValue(aref attribute);

// пример
object Test;
Test.value = "hello";
string attrValue = GetAttributeValue(Test.value); // "hello"
GetAttributeValue - возвращает значение переданного атрибута или объекта.
object obj, ref obj, aref attribute - объект или атрибут, значение которого нужно получить.
Помните, что каждое значение хранится как строка! Сохраненные объекты, числа с плавающей точкой и целые числа необходимо преобразовать соответствующим образом перед использованием.

CopyAttributes

// синтаксис
void CopyAttributes(object &destination, object source);

// пример
object Tmp;
CopyAttributes(&Tmp, CargoOne);
CopyAttributes - копирует все атрибуты объекта в новый объект.
object &destination - ссылка на объект, в который будут скопированы атрибуты.
object source - объект, с которого будет снята копия.

DumpAttributes

// синтаксис
void DumpAttributes(object obj);
void DumpAttributes(ref obj);
void DumpAttributes(aref attribute);

// пример
trace("nConditionsNum : " + nConditionsNum);
DumpAttributes(conditions);
DumpAttributes - трассировка (лог) всех данных об атрибутах заданного объекта.
object obj, ref obj, aref attribute - объект или атрибут, с которого снимается дамп.

CheckAttribute

// синтаксис
bool CheckAttribute(object &obj, string attribute);

// пример
if (!CheckAttribute(&Weather, "Stars.Enable"))
{
    Weather.Stars.Enable = false;
};
CheckAttribute - проверка существует ли атрибут.
object &obj - ссылка на объект, для которого проверяется атрибут.
string attribute - имя атрибута.

TestRef

// синтаксис
bool TestRef(ref target); 
bool TestRef(aref target); 

// пример
bool LAi_CheckCharacter(aref chr, string out)
{
    if (!TestRef(chr))
    {
        Trace("LAi_CheckCharacter -> invalid aref, call from " + out);
        return false;
    }

    return true;
}
TestRef - проверка, что атрибут или объект все еще существует.
ref target, aref target - ссылка на объект или атрибут, который проверяем.

DeleteAttribute

// синтаксис
void DeleteAttribute(object obj, string attribute); 

// пример
DeleteAttribute(&Sky, "");          // очистить объект
DeleteAttribute(pchar, "Items");    // удалить все предметы у персонажа 
string sQuest2 = "quest.Deposits." + city + "_Type2";
DeleteAttribute(pchar, sQuest2);
DeleteAttribute - удаляет атрибут (поле и данные) из указанного объекта.
object obj - объект, из которого удаляем.
string attribute - имя атрибута, который удаляем.
Если передать "" (пустую строку) в качестве имени атрибута - будут удалены все атрибуты объекта.

Содержание
`
ОЖИДАНИЕ РЕКЛАМЫ...
38
Самое главное бы рассказать - как я могу менять объекты, переданные в функцию извне, чтобы потом они могли видеться как изменённые.
И что там со временем жизни ссылок, про стек, про аллокацию в хип
Ответы (1)
23
ScorpioT1000, мне бы для начала последние три статьи перевести на человеческий язык и дополнить реальными примерами.
А то они сейчас выглядят как документация, а не обучающий материал для новичка. 😅
За наводки большое спасибо, занесу это в таск-лист.
23
Вышла новая версия! Прокрутить к ресурсу
  • Добавлен раздел, описывающий функции для работы с атрибутами объекта.
позже будет добавлен раздел практических примеров работы с объектами
23
Вышла новая версия! Прокрутить к ресурсу
  • Описана проблема при обращении к атрибуту
Спасибо камраду Rosarak
Ответы (1)
23
Дополнено.
Проблема была в восприятии движком числа в int и числа в string по-разному.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.