www.mudconnector.su

Национальный мадконнектор.
Текущее время: Вт авг 16, 2022 2:20 am

Часовой пояс: UTC + 3 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 32 ]  На страницу 1, 2, 3, 4  След.
Автор Сообщение
 Заголовок сообщения: Фреймворк для билдера
СообщениеДобавлено: Пт авг 28, 2009 2:03 pm 
Не в сети

Зарегистрирован: Вт мар 24, 2009 6:20 pm
Сообщений: 213
Вступление

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

Предыстория

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 писал(а):
Тут вопрос в том, что нужна непротиворечивая надстройка в виде набора необходимых функций. Причем надстройка удобная в работе. Это подразумевает совсем иной уровень, существенно выше того, который обеспечивает к примеру С++. В том числе и уровень контроля над ошибками. Понимаете... средство разработки зон должно быть ориентированно не на программистов вовсе. Это создание именно своего ЯЗЫКА... задача не такая простая, как кажется.

Это очень правильно конечно, но ведь все зоны очень разные (в идеале, конечно). Поэтому де факто мне в голову приходит лишь несколько вещей, которые можно включить в обсуждаемый фреймворк.


Фреймворк

Хочется немного конкретики и примеров. Каким он может быть, этот фреймворк?
Итак, сначала выясним, что же требуется делать билдеру чаще всего:
  • перечислять объекты (чаще всего персонажей, но также и предметы) по определенному фильтру (по комнате, по лидеру, по признаку моб/не моб, по наличию денег, по внумам и т.п. - по сути это может быть произвольный фильтр) и что-нибудь с ними делать
  • выдавать квесты пойди-принеси
  • выводить сообщения по типу act
В общем, это и есть те вещи, которые фреймворк должен максимально упростить.


Перечисления

Думаю, оптимально было бы ввести некую абстрактную конструкцию, например так:
Код:
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



Вот примерно так. Дополнения приветствуются.


Последний раз редактировалось omlin Пт авг 28, 2009 2:59 pm, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Фреймворк для билдера
СообщениеДобавлено: Пт авг 28, 2009 2:46 pm 
Не в сети
Site Admin

Зарегистрирован: Пт май 16, 2008 4:14 pm
Сообщений: 1415
Говоря о теории и вступлении и С++.
Все это хорошо в теории, то что я видел на практике выглядит настолько неудобоваримым, насколько это возможно.
Если есть примеры, готов их прокомментировать.

Вы абсолютно зря вообще используете dg_scripts.
Задача превзойти язык созданный 10-15 лет назад в других условиях и под другие задачи довольно проста
и на мой взгляд не стоит...

В целом у вас абсолютно правильные примеры для for_each и в целом абсолютно верное направление движения.
В частностях могут быть свои заморочки, но это действительно то, что сэкономит много нервов.
Но примеры довольно простые. Есть и посложнее. Например, нигде не рассмотрены действия по истечению
таймеров... итд итп.

Я готов выложить типовую "зону с заморочками" на растерзание. По-моему она выдавалась в паблик с
нашими редакторами. Если есть желающие (пусть даже 1 человек) я готов на ее примере обсосать
все тонкости и обдумать как на базе луа создать что-то более продвинутое. Отчасти потому, что это
все-равно мне понадобится, а взгляд со стороны несомненно лучше.

Думаю, также имеет смысл рассмотреть конкретные команды и сам фреймворк. Если есть желание.
Можно сделать это и в почте, могу сделать отдельный подфорум.

ЗЫ. Я несколько обеспокоен идеей шаблонов, не задавит ли мысль и идеи ?
Однако нужность очевидна.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Фреймворк для билдера
СообщениеДобавлено: Пт авг 28, 2009 3:17 pm 
Не в сети

Зарегистрирован: Вт мар 24, 2009 6:20 pm
Сообщений: 213
отлично, я рад, что мои идеи возымели определенный успех :)
я полностью "за" обсуждение, почему бы и нет
насчет организации:
  • почтой - непублично. а значит могут быть упущены некоторые весомые мнения. мозговой штурм в данном случае важен, и особенно - мнение рядовых билдеров. кто знает, может они сюда захаживают :)
  • подфорум с топиками на каждую команду/функцию - громоздко. если во фреймворке окажется хотя бы штук 20 конструкций, то придется лазить между 20 разными топиками. да и вообще в форуме когда обсуждение доходит эдак страницы до 5й, то его нить для вновь вступающих в него - теряется.
предлагаю компромиссный вариант:
Обсуждение проводится где-нибудь здесь, в одном или нескольких топиках, а результаты можно выложить в отдельный раздел в Wiki, со ссылками на форум.

P.S. Да, насчет зоны - наверное можно выложить одну общую, хотя думаю у всех свои зоны есть, и все будут смотреть конкретику своих зон. так и получится разнообразие. У меня лично недостатка в зонах нет)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Фреймворк для билдера
СообщениеДобавлено: Пт авг 28, 2009 3:25 pm 
Не в сети
Site Admin

Зарегистрирован: Пт май 16, 2008 4:14 pm
Сообщений: 1415
Тут вопрос целей.
Если цель - создание удачных реализаций, то непонятно зачем все в одну кучу валить.
http://www.a-mud.ru/builder/builder/272.zip 46килобайт trg-файла
В идеале его порезать по числу триггеров или задач на топике и в каждом
уже искать лучший вариант.

Проблемы в том или ином виде видны невооруженным взглядом уже после чтения
первых 10-15 строк.

Это хорошо что у всех много своих приватных зон, я за всех рад.
Однако найти решения их проблемам я возможности не вижу :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Фреймворк для билдера
СообщениеДобавлено: Пт авг 28, 2009 4:01 pm 
Не в сети

Зарегистрирован: Чт авг 27, 2009 2:27 pm
Сообщений: 63
Фреймворк должен позволять работать с событиями.
Например:
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)
и т.п.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Фреймворк для билдера
СообщениеДобавлено: Пт авг 28, 2009 5:36 pm 
Не в сети

Зарегистрирован: Вт мар 24, 2009 6:20 pm
Сообщений: 213
Прицепляемые переменные

Ну во-первых, амудовские 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 секунд, причем при этом в выполнении триггера задержки не будет, действия по таймеру выполняются асинхронно.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Фреймворк для билдера
СообщениеДобавлено: Пт авг 28, 2009 6:35 pm 
Не в сети
Site Admin

Зарегистрирован: Пт май 16, 2008 4:14 pm
Сообщений: 1415
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 разу через Х секунд что-ли сработают ?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Фреймворк для билдера
СообщениеДобавлено: Пт авг 28, 2009 7:58 pm 
Не в сети

Зарегистрирован: Вт мар 24, 2009 6:20 pm
Сообщений: 213
KadVar писал(а):
Разница подхода в том, где и как вы задаете когда должна обнулиться переменная.В практике - 9 из 10 в вашем случае просто забудут.

А где в адамантовских триггерах написано, что нужно вызвать set_var_reset ? :) Почему set_var_reset точно также не могут забыть? )

Нет, ну зерно истины конечно тут есть, не спорю. Создается, вроде как, дополнительная конструкция, необходимость которой для большинства билдеров интуитивно неясна с первого раза.
В принципе, единственная альтернатива которую я могу предложить здесь - это делать все локальные переменные обнуляемыми по умолчанию при ресете зоны. А чтобы сделать их перманентными, потребуется их, к примеру, зарегистрировать:
Код:
actor.new_local_var = 10
actor:make_permanent(new_local_var)


А вообще, эвентная модель это стандарт де-факто в современном программировании, и все хоть немного программисты прекрасно понимают как работать с эвентами. К тому же, все очень просто... По сути дела, это то же самое, что аттач новых триггеров, тока эти триггеры написаны в виде подпрограмм (функций).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Фреймворк для билдера
СообщениеДобавлено: Сб авг 29, 2009 12:57 pm 
Не в сети

Зарегистрирован: Вт мар 24, 2009 6:20 pm
Сообщений: 213
KadVar писал(а):
Что-то посмотрел еще раз... и эээ... совсем не понял. Они по 1 разу через Х секунд что-ли сработают?


Именно так.

......момент вызова set_timer в триггере......
прошло 5 секунд
моб1 сказал: "Привет!"
прошло еще 5 секунд
моб2 сказал: "Привет!"
прошло еще 5 секунд
моб3 сказал: "Привет!"
прошло еще 5 секунд
моб4 сказал: "Привет!"


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Фреймворк для билдера
СообщениеДобавлено: Пн авг 31, 2009 12:22 pm 
Не в сети
Site Admin

Зарегистрирован: Пт май 16, 2008 4:14 pm
Сообщений: 1415
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 писал(а):
А вообще, эвентная модель это стандарт де-факто в современном программировании, и все хоть немного программисты прекрасно понимают как работать с эвентами. К тому же, все очень просто... По сути дела, это то же самое, что аттач новых триггеров, тока эти триггеры написаны в виде подпрограмм (функций).

Вы меня простите, но причем тут программисты ?
К слову сказать аттач новых тригеров, детач старых итп - не очень хорошая практика применяемая
в некоторых проектах. Особенно там, где по репопу ничто не переаттачивается автоматом...
Лично я считаю, что вместо этого должно быть состояние зоны, которое так или иначе
описывается переменными.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 32 ]  На страницу 1, 2, 3, 4  След.

Часовой пояс: UTC + 3 часа [ Летнее время ]


Кто сейчас на конференции


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron