-
Notifications
You must be signed in to change notification settings - Fork 211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Механика варнингов #2094
Механика варнингов #2094
Conversation
code/_helpers/warnings.dm
Outdated
if(!type) | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Если здесь type == null, то скорее всего где-то серьезная ошибка, которая может сломать загрузку/сохранение истории варнингов, что может привести, например, к спаму игроков каждый раунд.
Мне кажется здесь целесообразно использовать ASSERT, чтобы в случае такой ошибки мы получали рантайм и смогли заметить её как можно раньше.
if(!type) | |
return | |
ASSERT(type) |
Подробнее можно почитать в нашем Guide to Contribute
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Тоже самое в других местах с похожими проверками. Если проверяемое условие НИКОГДА не должно выполняться, то нужно использовать ASSERT, чтобы ловить рантаймы, когда условие все-таки выполнится.
if(user.client.check_warnings("heads") && !(user.client.key in GLOB.newcomers_head_warned)) | ||
if(role == "Captain" || role == "Head of Personnel" || role == "Chief Engineer" || role == "Chief Medical Officer" || role == "Research Director" || role == "Head of Security") | ||
user.client.warn_player("heads", "window=Warning;size=440x300;can_resize=0;can_minimize=0") | ||
var/answer = alert(user, "Are you sure you want to play as head of department?",, "Yes", "No") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Это будет выглядеть костыльно. Два окна открываются моментально и тупо спамят игроку. Думаю тут будет еще больше шансов, что он закроет их не читая. Еще и мешанина русского и английского...
Предлагаю убрать этот alert пока, а потом лучше в сам варнинг добавим кнопки. Ну или можешь сейчас этим заняться, если есть желание. Это, конечно, уже не входит в иссуй, но улучшение будет полезным.
В любом случае, я думаю алерт этот не нужен.
code/modules/client/preferences.dm
Outdated
if(!(C.key in GLOB.newcomers_warned) && C.check_warnings("newcommers")) | ||
C.warn_player("newcommers", "window=Warning;size=360x240;can_resize=0;can_minimize=0") | ||
GLOB.newcomers_warned.Add(C.key) | ||
C.warned("newcommers") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Вот это все - это же цельная логика предупреждения игрока. Почему нельзя сделать одну фунцию, которая будет все это делать? Чтобы выглядело примерно так:
client.show_warning(NEWCOMMERS_WARNING_TYPE)
В моем варианте, как минимум, будет сложно что-то забыть. А то я вот буду добавлять новое предупреждение и мне придется помнить, что тут нужно написать аж 4 строчки! Последние две уж точно легко будет забыть.
Для этого, очевидно, надо будет еще где-то определить
#define NEWCOMMERS_WARNING_TYPE "newcommers"
Кстати сделав такие дефайны, искать по коду будет гораздо проще. "NEWCOMMERS_WARNING_TYPE" встречается реже, чем "newcommers", а "HEADS_WARNING_TYPE" будет проще найти, чем "heads".
code/_helpers/warnings.dm
Outdated
return | ||
var/datum/warn/W = new() | ||
var/message = file(W.warnings_path+type+".html") | ||
show_browser(src, message, options) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Комментарий, касательно всей архитектуры в целом.
Мне тут еще очень не нравится две вещи: какие-то глобальные списки, которые нужно пилить отдельно для каждого варнинга - хотелось бы обобщить, чтобы твоя система автоматически запоминала для каждого варнинга какие варнинги уже показывались игроку в этом раунде. Чтобы в коде, который пытается отправлять такие варнинги, не приходилось об этом думать каждый раз заново.
Второе - загрузка/сохранение варнингов каждый раз. На первых стартах после обновы к нам по вечерам будет заходить 50 игроков за раз и каждому нужно будет выдать варнинг. Каждый показ варнинга - это сохранение/загрузка файла, а учитывая что это будет происходит единомоментно на старте раунда, то тут сильно аффектнет производительность - будут тормоза. Хочется чтобы варнинги загружались и сохранялись лишь по необходимости. Загружались - на старте. А сохранялись только на изменениях.
Всего этого проще добиться, если сделать глобальную ПОДСИСТЕМУ "warnings", которая будет загружать на старте sav-файл, хранить историю варнингов в себе, а также хранить в себе все твои глобальные списки и прочую информацию, которая тебе нужна.
Подсистема реализуется примерно так:
SUBSYSTEM_DEF(warnings)
name = "Warnings"
init_order = SS_INIT_WARNINGS
flags = SS_NO_FIRE // это означает, что подсистему не нужно вызывать каждый тик - она просто хранит информацию, а вызывается напрямую через `SSwarnings.func()`
var/list/shown_warnings = new // все предупреждения когда либо показанные игрокам. В листе лежат типы варнингов, каждому типу соответствует список сикеев.
var/list/shown_warnings_this_round = new // предупреждения, показанные в этом раунде. Тот же формат
/datum/controller/subsystem/warnings/Initialize(timeofday)
var/savefile/S = new(WARNINGS_DATA_PATH)
for (var/type in S)
S[type] >> shown_warnings[type]
for (var/type in WARNINGS_ALL_TYPES)
shown_warnings_this_round[type] = list() // изначально пустой
/datum/controller/subsystem/warnings/proc/show_warning(client/client, type)
ASSERT(client)
if (!(client.ckey in shown_warnings_this_round[type]) && !(client.ckey in shown_warnings[type]))
var/message = file(WARNINGS_TEMPLATES_PATH+type+".html")
show_browser(client, message, "window=Warning;size=480x320")
shown_warnings_this_round[type] += client.ckey
shown_warnings[type] += client.ckey
__save_shown_warnings()
/datum/controller/subsystem/warnings/proc/__save_shown_warnings() // __ указывают, что функция предназначена только для внутреннего использования
fdel(file(WARNINGS_DATA_PATH))
var/savefile/S = new(WARNINGS_DATA_PATH)
for(var/type in shown_warnings)
S[I] << shown_warnings[type]
Где-то в дефайнах определяем дефайны. WARNINGS_ALL_TYPES нужно по аналогии сделать:
#define PATREON_NONE "none"
#define PATREON_CARGO "cargo"
#define PATREON_ENGINEER "engineer"
#define PATREON_SCIENTIST "scientist"
#define PATREON_HOS "hos"
#define PATREON_CAPTAIN "captain"
#define PATREON_WIZARD "wizard"
#define PATREON_CULTIST "cultist"
#define PATREON_ASSISTANT "assistant"
#define PATREON_ALL_TIERS list(\
PATREON_NONE, PATREON_CARGO, PATREON_ENGINEER, \
PATREON_SCIENTIST, PATREON_HOS, PATREON_CAPTAIN, \
PATREON_WIZARD, PATREON_CULTIST, PATREON_ASSISTANT)
В коде, который использует варнинги, пользуемся так:
if (do_we_need_warn())
SSwarnings.show_warning(mob.client, WARNING_TYPE)
Код выше я не компилировал и не проверял. Это общий набросок архитектуры, как можно сделать сильно проще и понятнее + избавиться от проблем глобальных списков и лагов из-за многочисленных сохранений/загрузок файлов.
Ну ты все-таки прочитай, там много полезных и интересных вещей написано |
@Epicus7 сделал как субсистему. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"newcomers" пишется с одной m, пофиксите плс, читать больно.
Я знаю, просто когда уже всё готово было уже не хотелось менять. Поменяю позже, когда эпикус отпишет, мб там ещё что-то менять нужно будет |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ну во, по коду уже красиво получилось. Небольшая придирка только по магическому числу.
Дизайн окошек хромает на две ноги, но тут сложно придираться, конкретных предложений у меня сейчас нет.
code/_helpers/warnings.dm
Outdated
ASSERT(C) | ||
ASSERT(type) | ||
ASSERT(options) | ||
if (!(C.key in shown_warnings_this_round[type]) && (shown_warnings[type][C.key] < 3)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3 - "магическое" число, такое лучше через define определять.
#define WARNINGS_REPEAT_TIMES 3
@@ -272,6 +272,8 @@ | |||
pref.job_low |= job.title | |||
return 1 | |||
|
|||
if(role == "Captain" || role == "Head of Personnel" || role == "Chief Engineer" || role == "Chief Medical Officer" || role == "Research Director" || role == "Head of Security") | |||
SSwarnings.show_warning(user.client, WARNINGS_HEADS, "window=Warning;size=440x300;can_resize=0;can_minimize=0") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Опции вылезли - это не очень, о них надо тоже помнить постоянно, когда варнинги хочешь показывать.
Алсо окно, конечно, получается не слишком красивое. Шаблоны на HTML довольно бедные, не переиспользуют готовые стили, например, от NanoUI. Еще можно было бы подумать, как избавиться от тайтлбара в этих окошках вообще.
Но это так, мысли вслух. У меня нет конкретного предложения как это сейчас сделать лучше, так что можно оставить пока как есть. Оставим на будущее.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ну, в опциях размер указывать нужно, так что не знаю, если хочешь без опций то скажи размер дэфолтный.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Дефолтный размер это неоч, в идеале бы динамически его считать, в зависимости от контента. Но я сам сейчас не знаю как это сделать.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Можно в самом хтмл файле давать размер body а потом в бйонде парсить его для окна.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Так это тоже самое, все равно размеры руками указывать.
Добавляет предупреждения игрокам перед заходом в игру и когда они хотят играть за глав первые три раза. Как и писалось в иссуе, это можно копипастить в другие части кода где нужно.
close #1247