www.mudconnector.su https://forum.mudconnector.su/ |
|
Фреймворк для билдера https://forum.mudconnector.su/viewtopic.php?f=15&t=126 |
Страница 1 из 4 |
Автор: | omlin [ Пт авг 28, 2009 2:03 pm ] |
Заголовок сообщения: | Фреймворк для билдера |
Вступление Очень интересен вопрос о создании фреймворка для билдера. То есть, некоторой совокупности частоупотребимых схем, которые используют билдеры, представленных в виде функций, языковых конструкций или операторов - в качестве надстройки к скриптовым движкам. Предыстория KadVar писал(а): Как бы это сказать. С++ конечно хороший язык, но причем тут триггера итп ? Я видел то, что сделали в сфере, простите но мой вывод: "ниже плинтуса". Продраться через это практически невозможно. Проблема не в синтаксисе, хотя у С++ он АБСОЛЮТНО не подходит, проблема в библиотеках, которые вы должны создать для нормальной работы. Код циркловых мадов, таких как былины и хьервард, а по большей части - и адамант, это native Си-код. Иными словами, куча структурок, процедурное программирование, широкое использование дефайнов. Насчет сферы, это мад с новой кодовой базой. Там, слава богу, нормальный ООП. И по сравнению с DG-скрипт, это шаг вперед. Посудите сами, ведь гораздо проще и понятнее фрагмент: Код: foreach (Char ch in Room.Chars) ch.damage(10); , чем существующая конструкция в DG-скриптах, повторяющая убогость стековой системы циркла: Код: set ch %self.people% while (%ch%) set next %ch.next_in_room% wdamage %ch.name% 10 set ch %next% end При отсутствии фреймворка, и при наличии ООП в коде мада - я считаю даже вывод С++ - это очень разумный подход. Хотя, конечно, лучше, вывести мад-объекты на более дружественные новичкам скриптовые языки, такие как LUA(http://ru.wikipedia.org/wiki/Lua), python, и т.п. KadVar писал(а): Можно открыть все возможности, но как вы будете контролировать то, что понафигачит рядовой билдер ? Возможностей в любом случае придется открывать немало. Поэтому контроль - это отдельная тема KadVar писал(а): Тут вопрос в том, что нужна непротиворечивая надстройка в виде набора необходимых функций. Причем надстройка удобная в работе. Это подразумевает совсем иной уровень, существенно выше того, который обеспечивает к примеру С++. В том числе и уровень контроля над ошибками. Понимаете... средство разработки зон должно быть ориентированно не на программистов вовсе. Это создание именно своего ЯЗЫКА... задача не такая простая, как кажется. Это очень правильно конечно, но ведь все зоны очень разные (в идеале, конечно). Поэтому де факто мне в голову приходит лишь несколько вещей, которые можно включить в обсуждаемый фреймворк. Фреймворк Хочется немного конкретики и примеров. Каким он может быть, этот фреймворк? Итак, сначала выясним, что же требуется делать билдеру чаще всего:
Перечисления Думаю, оптимально было бы ввести некую абстрактную конструкцию, например так: Код: foreach переменная_объекта in класс_объекта where фильтр ** действия над переменной_объекта next переменная_объекта - название произвольной переменной, которой будет присвоен "текущий" объект, с которым можно будет оперировать класс_объекта - один из: персонажи, предметы, комнаты. фильтр - условие, в котором можно использовать поля персонажей/предметов/комнат Примеры: Код: foreach ch in chars where room=self.room and !is_npc and align>0 ch.damage(10); next Код: num_of_coins = 0 foreach obj in objects where owner=actor and vnum=8120 num_of_coins += 2 obj.purge next if num_of_coins>0 say Отлично, я вижу ты принес то что я просил. Вот твоя награда! ** сгенерим монеты, на случай если у нас столько нет self.money += num_of_coins ** отдадим их тому кто сделал квест give actor num_of_coins монет end Оба примера предполагаются быть моб-триггерами (self - это моб). Язык абстрактный, с закосом под адамантовский dg_script. Первый пример дамажит всех светлых плееров в комнате с текущим мобом. Второй пример ищет в инвентаре у игрока все предметы с определенным внумом, уничтожает эти предметы и выдает за них по 2 монеты. Квесты принеси-подай Это очень частые квесты, и я думаю очень было бы классно, если бы внутри триггеров они были МАКСИМАЛЬНО простыми. Например, рассмотрим фрагмент: Код: register_quest init cur_time = get_time() end greet say Привет! Я потерял свою любимую запонку. Если найдешь ее - награжу! get_mob(1023).attach_death_obj(1020, 100%) end award say Отлично! А я уже и не надеялся ее найти! Вот твоя награда load obj 1040 give obj_1040 actor end conditions if was_zone_reset_since(10, cur_time) reset_quest end end end Подразумевается, что монстр будет давать этот квест один раз за репоп собственной зоны, запонка будет лоадиться в труп монстра 1023 только после того как квест будет взят, награда если принести запонку - предмет 1040. Согласен, тут много недоработок, но общая мысль, надеюсь понятна: от билдера требуется лишь придумать сообщения, награду, и откуда попится "заказываемый" предмет. Очень важно, что квест таким образом весь на виду, а не разбросан по разным триггерам: проще искать ошибки. Сообщения Ну тут главное задокументировать как следует, и отказаться от мадовских $N $n $y $g $u $t ..... Я вот сколько лет уже билдю - до сих пор не запомнил. Тем более, что у разных мадов разные переменные... Так что первейшее дело - это переменные назвать, и конечно связать их с объектами. Пример: Код: act to_vict => "Вы содрогнулись от удара молнии, посланной " ch.tname to_not_vict => vict.name + "содрогнул" + vict.lingvo_sya + " от удара молнии, посланной " ch.tname to_char => vict.name + "содрогнул" + vict.lingvo_sya + " от удара молнии, посланной Вами!" end Вот примерно так. Дополнения приветствуются. |
Автор: | KadVar [ Пт авг 28, 2009 2:46 pm ] |
Заголовок сообщения: | Re: Фреймворк для билдера |
Говоря о теории и вступлении и С++. Все это хорошо в теории, то что я видел на практике выглядит настолько неудобоваримым, насколько это возможно. Если есть примеры, готов их прокомментировать. Вы абсолютно зря вообще используете dg_scripts. Задача превзойти язык созданный 10-15 лет назад в других условиях и под другие задачи довольно проста и на мой взгляд не стоит... В целом у вас абсолютно правильные примеры для for_each и в целом абсолютно верное направление движения. В частностях могут быть свои заморочки, но это действительно то, что сэкономит много нервов. Но примеры довольно простые. Есть и посложнее. Например, нигде не рассмотрены действия по истечению таймеров... итд итп. Я готов выложить типовую "зону с заморочками" на растерзание. По-моему она выдавалась в паблик с нашими редакторами. Если есть желающие (пусть даже 1 человек) я готов на ее примере обсосать все тонкости и обдумать как на базе луа создать что-то более продвинутое. Отчасти потому, что это все-равно мне понадобится, а взгляд со стороны несомненно лучше. Думаю, также имеет смысл рассмотреть конкретные команды и сам фреймворк. Если есть желание. Можно сделать это и в почте, могу сделать отдельный подфорум. ЗЫ. Я несколько обеспокоен идеей шаблонов, не задавит ли мысль и идеи ? Однако нужность очевидна. |
Автор: | omlin [ Пт авг 28, 2009 3:17 pm ] |
Заголовок сообщения: | Re: Фреймворк для билдера |
отлично, я рад, что мои идеи возымели определенный успех я полностью "за" обсуждение, почему бы и нет насчет организации:
Обсуждение проводится где-нибудь здесь, в одном или нескольких топиках, а результаты можно выложить в отдельный раздел в Wiki, со ссылками на форум. P.S. Да, насчет зоны - наверное можно выложить одну общую, хотя думаю у всех свои зоны есть, и все будут смотреть конкретику своих зон. так и получится разнообразие. У меня лично недостатка в зонах нет) |
Автор: | KadVar [ Пт авг 28, 2009 3:25 pm ] |
Заголовок сообщения: | Re: Фреймворк для билдера |
Тут вопрос целей. Если цель - создание удачных реализаций, то непонятно зачем все в одну кучу валить. http://www.a-mud.ru/builder/builder/272.zip 46килобайт trg-файла В идеале его порезать по числу триггеров или задач на топике и в каждом уже искать лучший вариант. Проблемы в том или ином виде видны невооруженным взглядом уже после чтения первых 10-15 строк. Это хорошо что у всех много своих приватных зон, я за всех рад. Однако найти решения их проблемам я возможности не вижу |
Автор: | Кошир [ Пт авг 28, 2009 4:01 pm ] |
Заголовок сообщения: | Re: Фреймворк для билдера |
Фреймворк должен позволять работать с событиями. Например: some_item.add_event(take, deal_damage_to_all) some_weapon.add_event(deal_damage, deal_damage_to_owner) some_room.add_event(enter, load_some_evil_mobs) some_item.add_event(wear, add_ressurect_event) some_character.add_event(die, ressurect_and_destroy_relic) и т.п. |
Автор: | omlin [ Пт авг 28, 2009 5:36 pm ] |
Заголовок сообщения: | Re: Фреймворк для билдера |
Прицепляемые переменные Ну во-первых, амудовские get_var, set_var, set_var_reset - это чудовищные конструкции, жутко неудобные и сложные поначалу для запоминания. Например LUA в хьервардовской реализации позволяет к любым своим объектам по определению цеплять любые поля, и это выглядит намного проще, например: Код: if (mob.quest_given == nil) mob.quest_given = 1 mob.do_cmd("г Привет тебе, "..actor.name[0]) end Так что я не буду рассматривать проблемы, связанные с прицепляемыми переменными, кроме одной: Это - проблема замены set_var_reset. Запланированный уже при выдаче квеста, ресет переменной, - это очень правильно и очень наглядно. По сути, пока я писал, Кошир эту проблему уже решил. Это действительно проще сделать через некие слизанные откуда-нибудь эвентные модели. Вот пример: Код: mob.add_event(event_reset_zone,function f self.quest_given = nil end) Здесь переменная монстра quest_given будет обнуляться при репопе зоны, к которой принадлежит монстр. Еще отдельно по таймеру, аналог амудовского set_var_reset("var" "round" "%n%"). Эта фишка бывает полезной. Вот пример: Код: function hello self:do_cmd("г Привет!") end mob1:set_timer(5,hello) mob2:set_timer(10,hello) mob3:set_timer(15,hello) mob4:set_timer(20,hello) Монстры с 1го по 4й будут говорить "Привет!" через каждые 5 секунд, причем при этом в выполнении триггера задержки не будет, действия по таймеру выполняются асинхронно. |
Автор: | KadVar [ Пт авг 28, 2009 6:35 pm ] |
Заголовок сообщения: | Re: Фреймворк для билдера |
omlin писал(а): Прицепляемые переменные Ну во-первых, амудовские get_var, set_var, set_var_reset - это чудовищные конструкции, жутко неудобные и сложные поначалу для запоминания. Например LUA в хьервардовской реализации позволяет к любым своим объектам по определению цеплять любые поля, и это выглядит намного проще, например: Код: if (mob.quest_given == nil) mob.quest_given = 1 mob.do_cmd("г Привет тебе, "..actor.name[0]) end Так что я не буду рассматривать проблемы, связанные с прицепляемыми переменными, кроме одной: Это - проблема замены set_var_reset. Запланированный уже при выдаче квеста, ресет переменной, - это очень правильно и очень наглядно. Вы немного недопонимаете зачем там эти переменные. Они ценны именно тем, что обнуляются и этим можно управлять. В вашем примере на lua я не очень понимаю как что и когда прийдет в стартовое состояние... omlin писал(а): По сути, пока я писал, Кошир эту проблему уже решил. Это действительно проще сделать через некие слизанные откуда-нибудь эвентные модели. Вот пример: Код: mob.add_event(event_reset_zone,function f self.quest_given = nil end) Здесь переменная монстра quest_given будет обнуляться при репопе зоны, к которой принадлежит монстр. По мне, так это - пример чудовищной конструкции. Эвенты ? Объясните что это такое выпускнуку суриковского в 3х словах . Разница подхода в том, где и как вы задаете когда должна обнулиться переменная. В практике - 9 из 10 в вашем случае просто забудут. omlin писал(а): Еще отдельно по таймеру, аналог амудовского set_var_reset("var" "round" "%n%"). Эта фишка бывает полезной. Вот пример: Код: function hello self:do_cmd("г Привет!") end mob1:set_timer(5,hello) mob2:set_timer(10,hello) mob3:set_timer(15,hello) mob4:set_timer(20,hello) Монстры с 1го по 4й будут говорить "Привет!" через каждые 5 секунд, причем при этом в выполнении триггера задержки не будет, действия по таймеру выполняются асинхронно. Кстати очень небезопасная конструкция. Как показывает практика делать что-то асинхронно не всегда хорошо (та самая set_var_reset тоже вполне асинхронна) - это с одной стороны. С другой - обычно все надо сделать 1 раз. Где тут это указано ? Что-то посмотрел еще раз... и эээ... совсем не понял. Они по 1 разу через Х секунд что-ли сработают ? |
Автор: | omlin [ Пт авг 28, 2009 7:58 pm ] |
Заголовок сообщения: | Re: Фреймворк для билдера |
KadVar писал(а): Разница подхода в том, где и как вы задаете когда должна обнулиться переменная.В практике - 9 из 10 в вашем случае просто забудут. А где в адамантовских триггерах написано, что нужно вызвать set_var_reset ? Почему set_var_reset точно также не могут забыть? ) Нет, ну зерно истины конечно тут есть, не спорю. Создается, вроде как, дополнительная конструкция, необходимость которой для большинства билдеров интуитивно неясна с первого раза. В принципе, единственная альтернатива которую я могу предложить здесь - это делать все локальные переменные обнуляемыми по умолчанию при ресете зоны. А чтобы сделать их перманентными, потребуется их, к примеру, зарегистрировать: Код: actor.new_local_var = 10 actor:make_permanent(new_local_var) А вообще, эвентная модель это стандарт де-факто в современном программировании, и все хоть немного программисты прекрасно понимают как работать с эвентами. К тому же, все очень просто... По сути дела, это то же самое, что аттач новых триггеров, тока эти триггеры написаны в виде подпрограмм (функций). |
Автор: | omlin [ Сб авг 29, 2009 12:57 pm ] |
Заголовок сообщения: | Re: Фреймворк для билдера |
KadVar писал(а): Что-то посмотрел еще раз... и эээ... совсем не понял. Они по 1 разу через Х секунд что-ли сработают? Именно так. ......момент вызова set_timer в триггере...... прошло 5 секунд моб1 сказал: "Привет!" прошло еще 5 секунд моб2 сказал: "Привет!" прошло еще 5 секунд моб3 сказал: "Привет!" прошло еще 5 секунд моб4 сказал: "Привет!" |
Автор: | KadVar [ Пн авг 31, 2009 12:22 pm ] |
Заголовок сообщения: | Re: Фреймворк для билдера |
omlin писал(а): KadVar писал(а): Разница подхода в том, где и как вы задаете когда должна обнулиться переменная.В практике - 9 из 10 в вашем случае просто забудут. А где в адамантовских триггерах написано, что нужно вызвать set_var_reset ? Почему set_var_reset точно также не могут забыть? ) Я еще раз могу только еще раз порадоваться, что лет 5 назад мне удалось создать маяк, на который ориентируются и поныне. Несмотря на то, что все было спроектировано так, чтобы было легче внедрить, а не пользоваться . Но меня очень огорчает то, что многие и поныне пытаются превзойти неудачные примеры реализаций созданные многие годы назад... на мой взгляд это КРАЙНЕ непродуктивно... надо делать нормальные реализации, а не радоваться тому, что у кого-то еще кривее чем у тебя... Ответом на ваш вопрос служит то, что лично я проверяю каждую строчку написанного кода и четко реагирую на код, в котором эти две строки не идут подряд. Более того, как показывает практика билдеры не забывают этого написать, т.к. копируют из примеров. Конечно строка должна была быть одна, не могу сейчас сказать почему это не было сделано, но вероятно была причина. omlin писал(а): В принципе, единственная альтернатива которую я могу предложить здесь - это делать все локальные переменные обнуляемыми по умолчанию при ресете зоны. А чтобы сделать их перманентными, потребуется их, к примеру, зарегистрировать: Код: actor.new_local_var = 10 actor:make_permanent(new_local_var) Да - подобным образом это можно скрыть. Вопрос в целях. В целом да - наверное это даже более правильный подход. Но надо хорошо понимать, что в этом случае билдеры не будут озабочены приведением зоны в состояние по умолчанию, что в 99% современных движков приведет к трудноустранимым проблемам. omlin писал(а): А вообще, эвентная модель это стандарт де-факто в современном программировании, и все хоть немного программисты прекрасно понимают как работать с эвентами. К тому же, все очень просто... По сути дела, это то же самое, что аттач новых триггеров, тока эти триггеры написаны в виде подпрограмм (функций). Вы меня простите, но причем тут программисты ? К слову сказать аттач новых тригеров, детач старых итп - не очень хорошая практика применяемая в некоторых проектах. Особенно там, где по репопу ничто не переаттачивается автоматом... Лично я считаю, что вместо этого должно быть состояние зоны, которое так или иначе описывается переменными. |
Страница 1 из 4 | Часовой пояс: UTC + 3 часа [ Летнее время ] |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |