Что это такое?
Этот инклуд позволяет использовать псевдооператор switchrand() - аналог switch со случайным выполнением одного из кейсов (case).
Где это может понадобиться?
В любых системах, где нужно случайно выбрать один из кейсов в switch, и при этом нумерация в кейсах прерывается (например, "1, 2, 3, 6, 7").
Допустим, решили вы сделать пикап, который выдаёт случайный приз:
И всё, вроде бы, хорошо, система работает, а игроки довольны. Но тут в одном из обновлений вам нужно убрать case 1, ибо игроки расстраиваются, когда у них отбирают деньги. Если вы просто удалите его - система не будет работать в 1 случае из 6, ибо random() всё ещё будет иногда выдавать единицу. Чтобы это исправить, придётся сделать что-то одно:
- Объединить 1-й кейс с каким-то другим (например, case 0, 1:), но это фактически увеличит шанс выпадения другого приза.
- Добавить какой-то новый приз вместо удалённого (придётся думать и писать новый код, что, естественно, большущий минус
).
- Сместить номера всех кейсов, которые шли после единицы, + исправить значение в random().
- Придумать костыль по типу добавления goto, который бы отправлял обработчик в позицию перед switch, дабы random() сгенерировало новое число.
И если на подобном switch с малым количеством кейсов все перечисленные пункты могут показаться незначительными, то представьте, что switch у вас состоит из 50, 100 и т.д. кейсов. В этом случае switchrand довольно сильно упростит поддержку кода, сняв с вас и нужду думать насчёт того, чтоб все кейсы были по порядку, и нужду в изменении значения, указанного в random() при изменении количества кейсов.
Ещё один пример ситуации - RP-мод с системой фракций (банд/мафий/организаций), в котором при выполнении какого-то задания нужно отправить игрока в одну из трёх армий. При этом так получилось, что ID армий в списке фракций - 2, 15, 22.
В случае со switchrand решение будет выглядеть примерно так:
Без switchrand есть 2 варианта решения:
- Поместить все нужные данные в массивы, определять рандомно индекс и уже отображать игроку нужную информацию из массивов согласно получившемуся индексу (но если у нас для каждой отдельной фракции нужно выполнить уникальный код, могут возникнуть проблемы. Да и в целом код получится довольно сложным и менее гибким относительно варианта switchrand).
- Сделать нечто подобное:
Но тут придётся следить за тем, чтоб значения в массиве и номера кейсов совпадали, что может быть проблематично (особенно в моменты когда кейсы наполнятся кодом и/или количество кейсов возрастёт).
new army_frac[] = {2, 15, 22}; switch(fid) { case 2: { // ... } case 15: { // ... } case 22: { // ... } }
Иными словами, главная задача switchrand - упростить работу со связкой "random + switch", избавив пользователя от рутинной задачи по слежению за номерами кейсов и числом в random().
Плюсы реализации:
- Не требует наличия YSI, amx_assembly или каких-либо других сторонних инклудов.
- Совместим с JIT.
Недостатки:
- Из-за использования оператора __emit (необходимо для совместимости с JIT) инклуд совместим только с новыми версиями компилятора (3.10.6 и новее).
Использование
Просто подключите random_switch.inc и используйте макрос switchrand(), как если бы использовали оператор switch:
Скачать: https://www.dropbox.com/s/ew9px62sec...witch.zip?dl=1
Благодарности:
- DeimoS - идея, примеры использования.
- VVWVV - изначальная реализация.
История версий:
- (03.12.2019) Первый релиз.
- (05.12.2019) Добавлен обход проблемы с падением компилятора (баг специфичен для версий компилятора 3.10.7 - 3.10.9).
- (31.12.2019) Оптимизирован код.