Topic: Работа с диалогами, квесты

Всем доброго утра!

Пишу я тут значит квестик пробный, дабы себя занять, да разобраться, как там что делается
в Инстеде. Оно все на очень начальных стадиях, и есть у меня одна show-stopper problem.

У меня по сюжету безумное количесво диалогов. Персонажей очень много, и с каждым можно поговорить.
Соответственно каждый диалог состоит из
- стандартных вопросов и реплик, вопросы про имя, настроение, и тп. Их задача прокачивать отношение NPC к ГГ,
чтобы открылись другие реплики.
- Уникальные вопросы-ответы к персонажу по сюжету
- Квестовые вопросы.

Как бы мне это как-то модульно организовать? Когда реализуешь "по-тупому" от сложности просто разрыв мозга случается.
Что касается квестовых вопросов-ответов тоже надо подумать, нужно квесты организовать как-то так,
чтобы их менеджить тоже было легко, и отдельно от диалогов. Квест можно активировать (нужным пермонажам добавляютя вопросы и реплики, появляются квестовые объекты и тп.) Просто хочется выделить это и держать как-то отдельно со списком квестов.
Есть идеи, как это все сделать удобно

Re: Работа с диалогами, квесты

Посмотрите, как сделаны диалоги в "Переходе". Может, вам понравится.

Re: Работа с диалогами, квесты

Короче, это все немного не то.

Я хочу сделать вот так:

alice = obj {
     nam = "Алиса",
...
     dlg = dlg {
...
              phr = {
                   {"Привет!", "Здравствуй!", [[pon("intro");]]},
                   {false, tag = "intro", "Хорошая погода сегодня...", "Наверное...",[[chars.alice.relationship.grow(1);if (chars.alice.friend) then pon("friend") end;]]},
                    {false, tag = "intro", "Мое имя зовут Яков, а как тебя зовут?", "Алиса", [[chars.alice.known = true;]]},
...
             },
...
}

...
weapon_quest = obj {
    nam = "Получение оружия",
...
    person = alice,
    dlg = dlg {
....
           phr = {
                 {"А как мне себя защитить?", [[Пропробуй немного подумать. Тебе нужно оружие, что-то чем ты сможешь
                    пользоваться немедленно, внезапно проснувшись от шороха. Найди себе крепкую палку, с которой ты
                    сможешь убить противника, хотя бы крысу. Заодно добудешь себе пропитание.]]},
...
           },
           place = passage_n,
           obj = {
                 'stick2',
          },
}

то есть идея в том, что есть стандартные диалоги, привязанные к разным людям
(люди размещаются в комнатах как обычные объекты), при обращении (клике), если уровень отношений не слишком низкий, запускается диалог. Если запустился квест, то в диалог NPC (указанного в квесте)
добавляются реплики из квеста. Причем есть реплики для начала квеста и для ситуации, когда он выполнен (нужный предмет есть в инвентаре).
Как бы мне такое реализовать, чтобы не утонуть совсем?

Re: Работа с диалогами, квесты

Да, и реплики должны удалиться, когда квест деактивирован/выполнен...

Re: Работа с диалогами, квесты

не знаю, я пишу по старинке. если есть npc, у него и прописаны сразу все реплики.
пользуйся tag, false и прочими штуками.
короче я бы сразу в диалог с алисой вбил бы ветку про предмет из квеста.
дают квест -- делаешь команду alisa_dlg:pon('weapon_quest');
завершил квест -- alisa_dlg:poff('weapon_quest');

а тэги у этой ветки в диалоге -- false, always = true (ну или не надо последнего, если надо только чтобы один раз была активной)

Re: Работа с диалогами, квесты

Дык квестов много, путано очень получается, перестаю понимать что происходит. Да и когда квесты разрешаются разными способами, получается ад. Чревато кучей багов, короче. Хочется наглядности. Чтобы табличкой их
всех, или как-то так... Просто если захочу переместить на другого npc, чтобы кучу всего не лопатить...

Re: Работа с диалогами, квесты

Наваял вот такое:

function npc(name, data)
        local cp = charstats[name]
        local r = obj {
                nam = cp.name,
                _data = cp,
                _dlg = cp.dlg,
                dsc = function(s)
                        local kdsc
                        local ukdsc

                        if s._data.knowndsc then
                                kdsc = s._data.knowndsc
                        else
                                kdsc = "Я вижу {"..s.nam.."}"
                        end
                        if s._data.unknowndsc then
                                ukdsc = s._data.unknowndsc
                        else
                                if s._data.class == "female" then
                                        ukdsc = "Я вижу незнакомую {девушку}."
                                elseif  s._data.class == "male" then
                                        ukdsc = "Я вижу {незнакомца}."
                                end
                        end


                        if s._data.known then
                                ldsc = kdsc
                        else
                                ldsc = ukdsc
                        end
                        p(ldsc)
                        if s._data.firsttime then
                                p(s._data.firsttext)
                                s._data.firsttime = false
                        end
                end,
                act = function(s)
                        if s._data.acttext then
                                p(s._data.acttext)
                        end
                        walkin(s._dlg)
                end,
                life = function(s)
                        if player_moved() and where(s) ~= s._data.where then
                                move(s, s._data.where, where(s))
                        end
                end,
        }
        local k, v
        for k, v in pairs(data) do
                r[k] = v
        end
        return r
end
...
global {
        charstats = {
                alice = {
                        name = "Алиса",
                        strength = 100,
                        health = 100,
                        class = "female",
                        known = false,
                        knowndsc = [[Я вижу {Алису}, сидящую в кресле]],
                        unknowndsc = [[Я вижу худую {девушку} с каштановыми волосами,
                                     сидящую в кресле]],
                        firsttime = true,
                        firsttext = [[Ее худоба, ее взъерошенные волосы, темные, почти черные глаза, в этом адском освещении
                        создавали ощущение, что передо мной не девушка, изможденная, но за невзгодами не утратившая еще
                        своей природной красоты, а существо с другой планеты, или чудовище, сошедшее со страниц каких-нибудь
                        страшных сказок]],
                        where = 'dorm1_ent_chairs',
                        dlg = dlg {
                                nam = "Алиса",
                                hideinv = true,
                                phr = {
                                        {
                                                "Привет!", "Здравствуй.", [[pon('hi');]],
                                        },
                                        {
                                                 tag = 'hi', false, "Меня зовут Яков. А как тебя зовут?", "Алиса",
                                                [[charstats.alice.known = true;pon('intro');]],
                                        },
                                        {
                                                 tag = 'intro', false, always = true, "Я здесь новенький. Может расскажешь мне что здесь и как?",
                                                "Ты разберешься. Повзрослеешь и поумнеешь. Если выживешь.", [[pon('survive');]],
                                        },
...
                                }
                        },
                },
...
        }
}
...
dorm1_ent_chairs = room {
        nam = [[Стол и кресла]],
        dsc = [[Стол и кресла представляют с собой образчик старой мебели, классифицируемой как рухлядь.
                Цвет обивки стульев навозможно разобрать, а поверхность стола выщерблена, как будто
                на нем рубили дрова. Но видно, что мебель еще прочная, и используется -- на стульях
                видны следы ремонта.]],
        way = {
                'dorm1_enterance',
        },
}
place(alice1, alice1._data.where)

Собственно вопросы - насколько легитивно менять phr в диалоге напрямую, то есть можно ли динамисески
добавлять фразы?

Как при такой конфигурации сделать нормально работающее сохранение игры?

Re: Работа с диалогами, квесты

Может быть, как-то так?

-- $Name: test$
-- $Version: 0.1$
instead_version "1.8.2"

require "para"
require "dash"
require "xact"

main2=dlg {
    nam='test2';
    phr={{1,'выаываывэ','asdasdasdas'}};
    way={main};
}
main=room {
    nam='test';
    dsc=[[давайте {addp|добавим фразу}]];
    obj={
        xact('addp',code[[
            table.insert(
                main2.phr,{2,'3123123','sadasdasd'}
                );
            ]]
        ),
    };
    way={main2};
}

(я не настоящий сварщик)

Re: Работа с диалогами, квесты

Да, так работает, то есть я могу добавлять реплики с тегами и для квестов, потом раскрывать их.
А вот сохранение не работает. Мне в такой конфигурации надо писать свою функцию сохранения, или
можно как-то помочь штатной?

Re: Работа с диалогами, квесты

К сожалению, совсем динамически нельзя (можно, но надо руками писать). Но можно вопросы и ответы делать функциями, если это поможет.

Re: Работа с диалогами, квесты

А можно пример варианта руками и с функциями?

А еще помогите пожалуйста с сохранением игры в примере из ОП, как мне там быть?

p.s. (пожалуйста со мной "на ты", мне 36 и я бородат, а то я прям теряюсь просто).

Re: Работа с диалогами, квесты

Вот это вот пытаюсь забороть, пока не выходит sad

Warning: room alice1["_data"]["dlg"] can not be saved!

(использую код из ОП)

Re: Работа с диалогами, квесты

мне 35 smile сегодня уже не получится, отпишу позже

Re: Работа с диалогами, квесты

Пора бы уже при регистрации сделать галочку - "Мне больше 30, и у меня есть борода". Если не помечена - не регистрировать smile

Re: Работа с диалогами, квесты

OK, жду smile

Re: Работа с диалогами, квесты

Вариант, когда вопросы и ответы это функции -- очень прост.

instead_version "1.9.1"

main = dlg {
    nam = 'test';
    phr = {
        { always= true, function()
            p ("вопрос", rnd(100))
        end,
        function()
            p ("ответ", rnd(100))
        end,
        function()
            p "реакция"
        end,
        }
    }
}

Понятно, что такие вопросы тоже можно дизаблить и энаблить, а уж что там в функциях - дело разработчика.
На самом деле это почти тоже самое что динамически добавлять удалять фразы - только число их будет ограничено заранее максимально расставленными фразами.

Еще можно сделать отдельно диалог для каждого задания и переходить на него в реакции...

Насчет сохранений - дальше...

Re: Работа с диалогами, квесты

Насчет сохранений, не рекомендую, но рассказываю.
Дело в том, что новая схема с phr = это просто обертка вокруг старых диалогов. Это значит, что вы может делать так:

instead_version "1.9.1"

main = dlg {
    nam = 'test';
    phr = {
        { always= true, function()
            p ("вопрос", rnd(100))
        end,
        function()
            p ("ответ", rnd(100))
        end,
        function()
            p "реакция"
            put(phr("вопрос saved", "ответ saved"))
        end,
        }
    }
}

Но это плохой способ, так как сохраняться могут только фразы без функций, либо если там использован code:

instead_version "1.9.1"

main = dlg {
    nam = 'test';
    phr = {
        { always= true, function()
            p ("вопрос", rnd(100))
        end,
        function()
            p ("ответ", rnd(100))
        end,
        function()
            p "реакция"
            put(phr("вопрос saved", code [[ p "ответ saved" ]]))
        end,
        }
    }
}

Есть и другие способы, но я бы не хотел засорять ими обсуждение. На мой взгляд в 99% хватает и того, что я написал.

Re: Работа с диалогами, квесты

Пётр,
первый и второй примеры в 17-м комментарии посимвольно идентичны, наверное имелось в виду что-то другое...

Re: Работа с диалогами, квесты

АААА, прошу прощения, теперь суть понял!