1. Уважаемые гости и новички, приветствуем Вас на нашем форуме
    Здесь вы можете найти ответы практически на все свои вопросы о серии игр «Готика» (в том числе различных модах на нее), «Ведьмак», «Ризен», «Древние свитки», «Эра дракона» и о многих других играх. Можете также узнать свежие новости о разработке новых проектов, сыграть в увлекательные ФРПГ, восхититься творчеством наших форумчан, либо самим показать, что вы умеете. Ну и наконец, можете обсудить общие увлечения или просто весело пообщаться с посетителями «Таверны».

    Чтобы получить возможность писать на форуме, оставьте сообщение в этой теме.
    Удачи!
    Скрыть объявление
  2. Внимание!
    — Требуется примерно по 3-5 человек на каждую из версий ОС:: - Windows® XP SP3, Windows® Vista SP2, Windows® 7 SP1, Windows® 8, Windows® 8.1, Windows® 10(build 10 1607) и Windows® 10(build 10 1703). Для стационарных ПК и ноутбуков. Заявку на участие можно оставить здесь...
    Скрыть объявление

Вопросы по скриптингу

Тема в разделе "Модостроение", создана пользователем MaGoth, 28 сен 2007.

Модераторы: Marvіn, MEG@VOLT
  1. MaGoth

    MaGoth ★★★★★★★★★★★
    Администратор

    Регистрация:
    7 янв 2005
    Сообщения:
    14.629
    Благодарности:
    6.602
    Баллы:
    740
    Пол:
    Мужской
    Прежде чем задавать вопросы, ознакомьтесь с документацией..
    1) Читать онлайн
    2) Архив с офлайн-версией(chm) во вложении
     

    Вложения:

    • Vam_tutor.rar
      Размер файла:
      171,6 КБ
      Просмотров:
      246
  2. Vlad_Torop

    Vlad_Torop Участник форума

    Регистрация:
    2 май 2014
    Сообщения:
    704
    Благодарности:
    450
    Баллы:
    180
    Пол:
    Мужской
    В C_RefuseTalk(AI\Human\C_Human) пропиши:
    if((other.guild == GIL_Sheep) && ((Hlp_GetInstanceID(slf) != Hlp_GetInstanceID(Лобарт) || (Hlp_GetInstanceID(slf) != Hlp_GetInstanceID(Онар)))
    {
    return TRUE;
    };
     
    Последнее редактирование: 14 фев 2016
    Dimus поблагодарил.
  3. Dimus

    Dimus ★★★★★★★
    Модератор

    Регистрация:
    19 июл 2010
    Сообщения:
    3.784
    Благодарности:
    2.147
    Баллы:
    540
    Пол:
    Мужской
    Спасибо тебе за подсказку - теперь NPC не начинают разговор с ГГ в облике овцы. Заодно исправил замеченную недоработку (вместо self должно быть slf):
    Код (Text):
    func int C_RefuseTalk(var C_Npc slf,var C_Npc oth)
    {
        if(Npc_RefuseTalk(slf) && C_NpcIsGateGuard(slf) && (slf.aivar[AIV_Guardpassage_Status] == GP_NONE))
        {
            return TRUE;
        };
        if((slf.aivar[AIV_TalkedToPlayer] == FALSE) && (Npc_GetDistToWP(slf,slf.wp) > 500))
        {
            if(Hlp_GetInstanceID(slf) == Hlp_GetInstanceID(Lothar))
            {
                return TRUE;
            };
        };
        if(C_PlayerHasFakeGuild(slf,oth) && (slf.flags != NPC_FLAG_IMMORTAL))
        {
            return TRUE;
        };
        if(oth.guild == GIL_SHEEP)
        {
            return TRUE;
        };
        return FALSE;
    };
     
     
    Последнее редактирование: 14 фев 2016
  4. Gor

    Gor Участник форума

    Регистрация:
    26 дек 2009
    Сообщения:
    864
    Благодарности:
    471
    Баллы:
    230
    Пол:
    Мужской
    Подскажите, в чем ошибка. Почему переменной типа testclass нельзя присвоить инстанцию этого типа? К ВАМу не отсылайте, т.к.
    Код (Text):
    class testclass
    {
        var int m1;
    };
    instance testinst(testclass)
    {
        m1 = 1;
    };

    var testclass tci;

    func void f1()
    {
        tci = testinst;
    };
     
  5. HeDeDe

    HeDeDe Участник форума

    Регистрация:
    17 авг 2009
    Сообщения:
    206
    Благодарности:
    76
    Баллы:
    180
    Пол:
    Мужской
    Во-первых, свои классы без помощи хаков (т.е. Икаруса) создавать нельзя.
    Во-вторых — "var Class" является указателем на экземпляр класса, в то время как instance — это что-то вроде конструктора класса. Instance — это на самом деле функция, которая инициализирует экземпляр класса.
     
    Gor поблагодарил.
  6. Gor

    Gor Участник форума

    Регистрация:
    26 дек 2009
    Сообщения:
    864
    Благодарности:
    471
    Баллы:
    230
    Пол:
    Мужской
    Это вопрос по возможностям языка, не для скриптинга игры.
    Ага, тогда прототип это как бы базовый конструктор, который по умолчанию вызывает instance первой командой.
    Еще вот вопрос на примере:
    c_npc Hlp_GetNpc (int instanceName); - возвращает ссылку на НПС, принадлежащему к типу instanceName.
    Код (Text):
    class c_npc {...};
    instance BDT_1090_Addon_Raven(Npc_Default){...};
    var c_npc Raven;
    Raven = Hlp_GetNpc(BDT_1090_Addon_Raven);
    Здесь переменной Raven типа c_npc присваивается ссылка на инстанцию BDT_1090_Addon_Raven того же типа посредством функции движка. Выходит это единственный способ? Неожиданно...
     
  7. HeDeDe

    HeDeDe Участник форума

    Регистрация:
    17 авг 2009
    Сообщения:
    206
    Благодарности:
    76
    Баллы:
    180
    Пол:
    Мужской
    Сам язык не дает возможности создать экземпляр класса, это делается посредством обращения к функциям движка.

    Верно.

    На самом деле у инстанции два назначения: Помимо конструктора, инстанция хранит указатель на последний созданный класс.

    Открыть спойлер

    Код (Text):

    zBOOL zCParser::CreateInstance(int instanceId, void* mem)
    {
        zCPar_Symbol *symbol = symtab->GetSymbol(instanceId);
        if (!symbol || symbol->type != zPAR_TYPE_INSTANCE)
            return 0;

        // Запись указателя на эксземпляр класса
        symbol->SetOffset(symbol, int(mem));

        int func_offset;
        zCPar_Symbol::SetUseInstance(symbol);
        symbol->GetStackPos(func_offset, 0);

        // Вызов конструктора instance
        DoStack(func_offset);
        return 1;
    }
     


    Функция Hlp_GetNpc проверяет, ссылается ли указатель, записанный в instance, на класс oCNpc, и если да, возвращает его.
    (На самом деле она сложнее, и похоже, принимает не только имя instance).
    Открыть спойлер

    Код (Text):

    int Hlp_GetNpc()
    {
        zCParser *parser = zCParser::GetParser();

        oCNpc* npc = nullptr;

        int instanceId;
        parser->GetParameter(instanceId);
        zCPar_Symbol* symbol = parser->GetSymbol(instanceId);

        if ( symbol ) {
            if (symbol->type == zPAR_TYPE_INSTANCE) {
                zCVob* adr = (zCVob*)symbol->GetInstanceAdr();
                npc = dynamic_cast<oCNpc*>(adr);
            }

            if (!npc) {
                zCWorld* world = ogame->GetGameWorld();
                npc = world->SearchVobByName(symbol->name);

                zCClassDef classdef = npc->GetClassDef();
                if (!zCObject::CheckInheritance(&oCNpc::classDef, classdef))
                    npc = nullptr;
            }
        }

        zCParser::SetReturn(parser, npc);
        return 0;
    }
     
     
    Последнее редактирование: 24 фев 2016
    ElderGamer и Gor поблагодарили.
  8. ElderGamer

    ElderGamer
    Модостроитель

    Регистрация:
    16 апр 2008
    Сообщения:
    1.878
    Благодарности:
    1.154
    Баллы:
    295
    Кстати, господа-спецы, раз уж речь зашла о ссылках и подразумевает возможность заглядывания в движок. Поясните если можно, как происходит обработка ссылок, и как с ними правильно работать?

    Вот, например, непись экипирован мечом определённой инстанции, а в его инвентаре лежит ещё такой же меч. С точки зрения движка это одна ссылка, или каждый из экземпляров будет иметь свою ссылку? Можно ли получить ссылку на предмет, который непись держит в руке, например, на горящий факел?
     
  9. Gor

    Gor Участник форума

    Регистрация:
    26 дек 2009
    Сообщения:
    864
    Благодарности:
    471
    Баллы:
    230
    Пол:
    Мужской
    Вопрос: Правильно ли я понял создание объекта в игре?
    Код (Text):

    // класс
    class c_npc {};
    // прототип (базовый конструктор объекта)
    prototype default_npc {};
    // инстанция (конструктор объекта)
    instance BDT_1090_Addon_Raven {};
    // создаем объект
    Wld_InsertNpc(BDT_1090_Addon_Raven,"ADW_ADANOSTEMPEL_RAVEN_11");
    // переменная, которая будет указывать на объект
    var c_npc raven;
    // получаем ссылку на объект
    raven = Hlp_GetNpc(BDT_1090_Addon_Raven);
    // теперь имеем доступ к полям объекта
     
     
  10. MEG@VOLT

    MEG@VOLT ★★★★★★★★★
    ТехАдмин

    Регистрация:
    24 мар 2006
    Сообщения:
    1.953
    Благодарности:
    1.010
    Баллы:
    490
    Вставка в мир
    создание
     
  11. ElderGamer

    ElderGamer
    Модостроитель

    Регистрация:
    16 апр 2008
    Сообщения:
    1.878
    Благодарности:
    1.154
    Баллы:
    295
    Но это при условии, что данный непись уникален в игровом мире. В случае с неписями клонами (монстры) данный механизм получения ссылки имеет изъян.
     
  12. Gor

    Gor Участник форума

    Регистрация:
    26 дек 2009
    Сообщения:
    864
    Благодарности:
    471
    Баллы:
    230
    Пол:
    Мужской
    Согласен, но объект все же создается функцией движка. Насколько я знаю ссылки на все созданные объекты находятся в дереве вобов и в списке. Доступ к ним скорее всего возможен с помощью икаруса и аст.
    instance в игре имеет два понятия.
    1) инстанция - экземпляр_класса - объект
    2) инстанция - функция - конструктор
    То что мы записываем как instance имя (){}; это фактически особого вида функция (конструктор), которая передается в функцию движка для создания объекта. Создание клонов лишь подтверждает это (инстанция (конструктор) одна, а клонов много). Прототип тоже особого вида функция. Ее вызывает инстанция первой командой байт-кода, если в инстанции указывали прототип.

    Это мои предположения. Данных пока не хватает.
     
    Последнее редактирование: 24 фев 2016
  13. HeDeDe

    HeDeDe Участник форума

    Регистрация:
    17 авг 2009
    Сообщения:
    206
    Благодарности:
    76
    Баллы:
    180
    Пол:
    Мужской
    Создание происходит седующим образом:
    • Wld_InsertNpc обращается к методу oSpawnManager::SpawnNpc
    • oCSpawnManager вызывает world->CreateVob. Эта функция ещё не вставляет NPC в игру, а лишь вызывает oCObjectFactory::CreateNpc
    • oCObjectFactory::CreateNpc создает NPC, и инициализирует его, npc->InitByScript. Тот, в свою очередь, обращается к парсеру, который и вызывает конструктор instance (См. zCParser::CreateInstance в посте выше).
    • При успешном создании NPC, oCSpawnManager вставляет NPC в мир.
    Да, каждый из предметов имеет свою ссылку. Ссылка — это адрес в памяти, завернутый в int.
    Получить ссылку на предмет в руке можно, но только с помощью Ikarus'a, обратившись к методу oCNpc::GetInvSlot(npc, "ZS_LEFTHAND").

    Например, всякие монстры и бандиты. Как я говорил, instance хранит в себе только указатель на последний созданный экземпляр.

    Здесь всё просто: у каждого символа есть поле offset, которое имеет разное значение в зависимости от типа (для функций это возвращаемое значение, для полей класса — смещение от начала класса, а для инстанций — указатель на последний созданный экземпляр).

    Верно. Причем вызов добавляется ещё на этапе компиляции.
     
    Myxomop, ElderGamer и Gor поблагодарили.
  14. Gor

    Gor Участник форума

    Регистрация:
    26 дек 2009
    Сообщения:
    864
    Благодарности:
    471
    Баллы:
    230
    Пол:
    Мужской
    Все подтверждается. Объект создается движком, который вызывает конструктор instance. Но в CAMERA.DAT находятся одни инстанции и никаких вызовов функций движка. Возможно двиг сам это все обрабатывает? То есть он по разному поступает в зависимости от датников.
     
  15. HeDeDe

    HeDeDe Участник форума

    Регистрация:
    17 авг 2009
    Сообщения:
    206
    Благодарности:
    76
    Баллы:
    180
    Пол:
    Мужской
    Да, движок берет определенные функции/инстанции/константы из датников.

    А точнее, в функциях движка жестко прописано, что и из каких датников брать.
     
  16. ElderGamer

    ElderGamer
    Модостроитель

    Регистрация:
    16 апр 2008
    Сообщения:
    1.878
    Благодарности:
    1.154
    Баллы:
    295
    Пытаясь написать функцию очистки инвентаря торговцев в Г1, столкнулся с тем, что возникает проблема при удалении предметов, не складывающихся в пачки. Если у непися есть несколько таких предметов одной инстанции, то удалить их разом с помощью функции Npc_RemoveInvItems не получается. Можно удалить только один экземпляр с помощью функции Npc_RemoveInvItem или Npc_RemoveInvItems с указанным количеством "1". Если в функции Npc_RemoveInvItems указать количество больше "1", то вообще ничего не удаляется. Похоже, всё дело в разных ссылках у данных предметов. Можно ли как-то решить эту проблему?
     
  17. Myxomop

    Myxomop

    Регистрация:
    28 май 2005
    Сообщения:
    2.465
    Благодарности:
    1.836
    Баллы:
    355
    Пол:
    Мужской
    Ну если так не работает: Npc_RemoveInvItems(slf,ItMi_xxx,Npc_HasItems(slf,ItMi_xxx));
    можно попробовать написать рекурсивную функцию или через зацикленный триггер-скрипт удалять поштучно до победы.
     
  18. HeDeDe

    HeDeDe Участник форума

    Регистрация:
    17 авг 2009
    Сообщения:
    206
    Благодарности:
    76
    Баллы:
    180
    Пол:
    Мужской
    Это странно, так как Npc_RemoveInvItems должна удалять такие предметы в цикле по одному. При этом сама инстанция никак не трогается — проверяется лишь, сопадает ли имя инстанции предмета в инвентаре с именем переданной инстанции.

    Открыть спойлер
    Код (Text):

        oCItem* item = 0;
        if ( npc )
            item = npc->IsInInv(instanceItem, 1);

        if ( item ) {
            Script_SaveNpcGlobals();
            if (item->MultiSlot() && npc->IsInInv(instanceItem, amount))
            {
                npc->RemoveFromInv(instanceItem, amount);
            }
            else
            {
                for ( i = 0; i < amount; ++i ) {
                    if ( !npc->RemoveFromInv(instanceItem, 1) )
                        break;
                }
            }
            ret = 1;
            Script_RestoreNpcGlobals();
        }


    Стоп. Я говорю про Г2.
    Г1 я не трогал, но похоже, что IsInInv и RemoveFromInv от Г1 к Г2 не изменились, а в Г2 была исправлена сама функция Npc_RemoveInvItems.


    Открыть спойлер
    Код (Text):

    if ( npc->IsInInv(instanceItem, amount) )
           npc->RemoveFromInv(instanceItem, amount);


    Следовательно, причина бага тогда в следующем: IsInInv проверяет каждый слот инвентаря, и возвращает истину тогда и только тогда, когда в слоте содержится предмет заданной инстанции, и количество предметов >= заданному. Так как нескладываемые предметы всегда имеют количество равное 1, выполняется только половина условия (в слоте лежит нужный нам предмет, но количество его меньше необходимого), таким образом IsInInv проверяет весь инвентарь, и не найдя предметов с необходимым количеством, возвращает 0.
     
    НастасьСанна, ElderGamer и Myxomop поблагодарили.
  19. neromont

    neromont
    Модостроитель

    Регистрация:
    12 мар 2011
    Сообщения:
    310
    Благодарности:
    303
    Баллы:
    220
    Пол:
    Мужской
    Подскажите пожалуйста. Класс C_FightAI отвечает за поведение существ во время боя?
     
  20. MaGoth

    MaGoth ★★★★★★★★★★★
    Администратор

    Регистрация:
    7 янв 2005
    Сообщения:
    14.629
    Благодарности:
    6.602
    Баллы:
    740
    Пол:
    Мужской
    Да..
     
    neromont поблагодарил.
  21. neromont

    neromont
    Модостроитель

    Регистрация:
    12 мар 2011
    Сообщения:
    310
    Благодарности:
    303
    Баллы:
    220
    Пол:
    Мужской
    Еще один вопрос. Просто разбираюсь с классами. Функция Item.magic за что отвечает. Нашел ответ на немецком "VAR FUNC magic ; // Parserfunktion zum "Magie Header"", но что-то никак не пойму о чем это они.
     
    Последнее редактирование: 8 апр 2016
Модераторы: Marvіn, MEG@VOLT

Поделиться этой страницей