Прежде всего, нужно рассказать немного о том, что собой представляет компьютерная память. Читатель, может быть ты и так это знаешь, но на всякий обрисую картину. Все без исключения игровые объекты - юниты, строки, числа - все это находится в компьютерной памяти. Память представляет собой просто последовательность идущих подряд ячеек, в каждую из которых записано определенное число. При помощи чисел можно закодировать все - и юниты и строки. Разные объекты занимают разное количество ячеек. Ведь чтобы записать объект юнит, нужно записать целую кучу информации о всех его параметрах. Это гораздо больше информации, чем то, которое несет какое-то значение типа integer. Вообще говоря разработчики war3 вряд ли хотели, чтобы картостроители могли работать с памятью, но они допустили при разработке один важный баг, которым научились пользоваться спецы по jass. Баг не позволяет менять содержимое ячейки памяти - но зато он дает возможность для любого игрового объекта найти номер ячейки памяти, в которую он записан, а также по номеру ячейки найти ссылку на объект. К примеру, рассмотрим функцию function FindHandle takes rect reg returns integer Что она по идее делает? В функцию передается параметр типа reg типа регион. Функция должна возвращать параметр типа integer. Вроде бы все нормально. Но почему-то присутствует два оператора return... Более того, первый из них говорит, что функция должна вернуть отнюдь не целочисленное значение, а наш регион reg. return 0 Если бы не было этой записи, war3 выдал бы ошибку - т.к. наблюдается несоответствие типов. Должны вернуть integer, а возвращаем rect. Но у нас два оператора return. war3 смотрит - вроде все нормально, ошибок нет. 0 -ведь целочисленное число, значит его можно вернуть. И невдомек ему бедному, что хитрый jass-ер уже поставил до этого еще один return. И вот, возникает интересная задача - игра должна вернуть регион reg, как целочисленное число. По идее это бессмысленно, но тут и срабатывает return bug. Результатом работы функции будет число, равное адресу ячейки памяти, в которой содержится информация по региону reg. Это первая часть бага. Есть и другая. Рассмотрим функцию: function FindRegion takes integer i returns rect Все аналогично. Функция должна вернуть регион, а вместо этого мы передаем ей параметр типа integer. Результатом будет то, что игра вернет регион, записанный по адресу i. Если конечно по этому адресу действительно записан регион. Впрочем, если не записан, это не будет ошибкой. Ошибка может возникнуть, если попробовать обратиться к недоступному участку памяти. Но это произойдет, разве что если ты будешь экспериментировать с памятью war3. Итак, у нас уже есть две функции, очень хорошо дополняющие одна другую. Создавать такие функции - очень просто. Так что для любого объекта в игре можно найти ячейку номер его ячейки в памяти. Какое может быть применение у return bug (RB)? Ну например, для наших функций. Зачем нам может понадобиться узнавать номера для регионов? Я этому сходу нашел следующее применение. В редакторе worldedit, к сожалению, невозможно простым и быстрым способом занести созданные регионы в массив. А ведь иногда бывает нужно. Скажем, на твоей карте несколько сотен регионов, в которых должны появиться одни и те же монстры и отправиться в патруль в следующую точку. Проще всего делать это через массивы с циклами. Но заносить вручную сотни регионов в массив - тоже приятного мало. Но конечно RB имеет гораздо более ценное применение. Дело в том, что все ячейки памяти имеют сквозную нумерацию. Т.е. благодаря RB мы можем сопоставить всем объектам их номера (точнее номера ячеек, которые они занимают в памяти). И все эти номера будут уникальны. Совпадений не будет. Эту нумерацию можно использовать, чтобы... Впрочем, это тема другой части :). 12. Тип Handle function <Имя> takes handle h returns <...> в аргументе указан тип handle. Так вот, в эту функцию в качестве параметра можно передавать ЛЮБОЙ игровой объект. Хочешь, посылай в качестве аргумента юнит, хочешь - регион, хочешь - точку и т.д. В связи с тем, что мы уже описали return bug, мы можем использовать его, чтобы найти ячейку в памяти, на которую ссылается handle: function H2I takes handle h returns integer Это дает нам определенное преимущество. Вот в прошлой статье мы рассмотрели функцию: function FindHandle takes rect reg returns integer Для региона находили номер. А как насчет других объектов? Юнитов, точек и пр.? Для каждого создавать свою функцию? Можно конечно, но используя тип handle мы значительно упростим задачу. Функцию H2I, рассмотренная чуть выше, предназначена как раз для этой цели. H2I(O) - и есть номер ячейки в памяти, которую занимает объект O, каким бы ни был этот объект. Напишешь set i = H2I(u) - в i попадет номер для юнита u. И т.д. | |
Просмотров: 767 | | |
Всего комментариев: 0 | |