Оглавление | Сообщение об ошибках | Ваше мнение о проекте | E-Mail автору |
xt.dp.asteroidcollector (захват астероида)
Это
скрипт захвата астероида xt.dp.asteroidcollector из пакета "XenonTomb
Device Pack v2".
Скрипт задействует самые разные команды: торговые, навигационые, общесистемные,
аудио, бортжурнала и проч., использует операторы условного и безусловного
перехода, циклы, языковые ресурсы, команды поиска и поэтому, как мне кажется,
будет достаточно полезным для обучения. Сам скрипт можно скачать на страничке
"Собрание скриптов пилотов". Номера фраз борткомпьютера можно поглядеть в MSCI
Handbook на стр. 98.
001 $ship = [THIS]
Передаем переменной $ship указатель на корабль, на котором запущен этот скрипт.
002
003 skip if $ship == [PLAYERSHIP]
004 return null
Проверяем, является ли корабль тем кораблем, в котором сидит игрок, если нет, то
выходим из скрипта.
005
006 $loaded = $ship -> get amount of ware
Астероид
in cargo bay
Получаем в переменную $loaded количество
товара "Астероид", предположительно имеющегося на борту.
007 skip if not $loaded
008 goto label unload.asteroid
Проверяем, если товар есть ($loaded>0, что соответствует логическому значению
TRUE. Значение 0 считается FALSE), то переходим на метку unload.asteroid (строка
088), чтобы выполнить разгрузку. Если же товара нет, будем загружаться (скрипт
выполняется дальше).
009
010 * ---------------------- LOADING --------------------- Это просто коментарий
"ЗАГРУЗКА"
011
012 if not $ship -> get free amount of ware Астероид in cargo bay
013 @ = wait 2000 ms
014 = speak text: page=13 id=135 priority=0
015 = speak text: page=13 id=1253 priority=0
016 return null
017 end
Смысл этого блока сводится к следующему: в строке 012 проверяем, сколько товара
"Астероид" может поместится в трюм на текущий момент. Можно было бы поступить
по-другому: зная, что товар "Астероид" и меет размер 10000 ST, можно
узнатькол-во свободного места, поделить его на 10000 и получить кол-во. Команда
get free amount of ware позволяет нам не заниматься арифметикой, ничего не знать
о возможности корабля перевозить груз ST, и даже не знать, какой размер имеет
единица товара, а сразу получить кол-во. Далее, если места для товара нет
(команда get free amount of ware вернула 0), то в строке 013 ждем 2 секунды (в
это время борткомпьютер договаривает фразу "Автопилот активирован"), в строках
014 и 015 заставляем тетку сказать "Команда отклонена" и "Нехватает места в
трюме", и в строке 016 выходим из скрипта. Если же место в трюме у нас есть
(команда get free amount of ware вернула число >0), то продолжаем выполнять
скрипт.
018
019 $target = get player tracking aim
020 skip if $target -> is of class Астероид
021 goto label not.correct
Получаем в переменную $target указатель на объект, который находится в прицеле к
орабля. Далее проверяем, принадлежит ли этот объект классу "Астероид". Если
объект - не астероид, переходим по метке not.correct (строка 118), иначе
продолжаем выполнять скрипт.
022
023 $dist = get distance between $ship and $target
024 skip if $dist <= 3000
025 goto label not.correct
Получаем в переменную $dist расстояние в метрах между кораблем $ship и целью
$target (астероид). Если расстояние более 3000 метров, переходим по метке
not.correct, иначе продолжаем выполнять скрипт.
Теперь начинется интересное: выяснение жирности (значения yield) астероида.
Задача усложняется тем, что нет функции, которая бы вернула это значение,
поэтому придется извращаться. Извращаться мы будем в строках
027-049, используя цикл
while.
026
027 $yield = 100
028 while $yield > 0
029 * ore
030 $aster = find asteroid: sector=[SECTOR] resourcetype=0 min.yield=$yield
flags=[Find.Nearest] refobj=$ship maxdist=3000 maxnum=null refpos=null
031 if $aster
032 $res.type = 0
033 break
034 end
035 * silicon
036 $aster = find asteroid: sector=[SECTOR] resourcetype=1 min.yield=$yield
flags=[Find.Nearest] refobj=$ship maxdist=3000 maxnum=null refpos=null
037 if $aster
038 $res.type = 1
039 break
040 end
041 * nividium
042 $aster = find asteroid: sector=[SECTOR] resourcetype=2 min.yield=$yield
flags=[Find.Nearest] refobj=$ship maxdist=3000 maxnum=null refpos=null
043 if $aster
044 $res.type = 2
045 break
046 end
047 dec $yield =
048 @ = wait 5 ms
049 end
Разберем подробно.
В строке 027 присвоим переменной $yield
значение 100 - это наша точка отсчета, максимальная жирность (для стандартной
игры). Это значение можно сделать и побольше, если существуют такие астероиды
небольшого размера. Далее организуем цикл (строки 028-049), который будет
выполняться, пока значение $yield будет больше 0. В строке 030 мы попытаемся
найти ближайший астероид (флаг поиска - Find.Nearest) с типом ресурса "руда",
минимальной жирностью $yield (в первом витке цикла равной 100), находящийся на
расстоянии не более 3000 м от корабля $ship. Результат поиска функции find
asteroid возвращается в переменную $aster. Далее в строках 031-034, если искомый
астероид обнаружен (переменная $aster не равна null), то переменой $res.type мы
присваиваем значение 0 (тип ресурса - руда), и прерываем цикл командой break. В
строках 036-040 и 042-046 мы делаем то же самое, только для ресурсов "кремний" и
"нивидиум" (типы ресурсов 1 и 2 соответственно). В строке 047 мы уменьшаем
значение $yield на единицу перед следующим витком цикла. Строка 048 - простая
задержка, чтоб интенсивные вычисления в цикле не затормаживали игру. Подитожим:
цикл выполняется либо до того, как $yield достигнет значения 0 (это значит что
мы не нашли астероид, что маловероятно), либо цикл прерывается на любом витке
при нахождении астероида. Во втором случае переменная $yield сохранит значение
жирности астероида - помним об этом!
050
051 skip if $aster == $target
052 goto label not.correct
Проверяем, совпадает ли наш найденый астероид с тем астероидом, который у нас в
прицеле. Если нет, то переходим по метке not.correct, иначе продолжаем выполнять
скрипт. Значения $aster и $target могут не совпасть лишь в двух случаях: если мы
не нашли астероид в цикле ($aster=null), или если в 3000 м от корабля были два
астероида с одинаковой жирностью, причем нецелевой астероид оказался немного
ближе к кораблю, чем целевой, что также маловероятно.
053
054 $energy = $ship -> get amount of ware
Кристаллы
in cargo bay
055 skip if $energy >= 25
056 goto label not.correct
Получаем в переменную $energy количество
кристаллов, находящихся в трюме корабля. Если их меньше 25, то переходим по
метке not.correct, иначе движемся дальше.
057
058 $aster.type = $aster -> get subtype
Получаем в переменную $aster.type подтип нашего астроида, отвечающий за его
внешний вид.
059 $aster.param = array alloc: size=3
060 $aster.param[0] = $res.type
061 $aster.param[1] = $yield
062 $aster.param[2] = $aster.type
Распределяем в памяти массив $aster.param из трех ячеек, которым присваиваем
значения ресурса, жирности и подтипа астероида.
063 $ship -> set local variable: name='asteroid'
value=$aster.param
Объявляем для корабля $ship локальную переменную 'asteroid' и присваиваем ей
значение массива $aster.param.
064
065 $ID = $aster -> get SectorObject ID
066 free sector object $ID
Получаем в переменную $ID уникальный номер астероида в секторе, и уничтожаем
его. При уничтожении он просто пропадает.
067
068 = $ship -> add 1 units of Астероид
069 = $ship -> add -25 units of Кристаллы
Добавляем в трюм корабля 1 единицу товара "Астероид", и убираем из трюма 25
кристаллов.
070
071 = speak text: page=13 id=1257 priority=0
072 = speak text: page=17 id=3721 priority=0
Заставляем борткомпьютер сказать "Теперь трюм содержит..." "Астероид".
073
074 $owner = [SECTOR] -> get owner race
Получаем в переменную $owner расу-владельца сектора, в котором находимся.
075 if $owner == Аргон OR $owner == Борон OR $owner ==
Сплит OR $owner == Паранид OR $owner == Телади
076 @ = wait 500 ms
077 $sum = $yield * -1000
078 add money to player: $sum
079 $sum = - $sum
080 player loses police licence for race $owner
081 write to player logbook: printf: pageid=511 textid=20, $owner, $sum, null,
null, null
082 = speak text: page=13 id=20 priority=0
083 end
Если раса-владелец одна их перечисленных в строке 075, то ждем полсекунды; в
строке 077 вычисляем сумму штрафа (жирность*-1000); в строке 078 снимаем эту
сумму со счета игрока (команда add money добавляет отрицательное число); в
строке 079 меняем знак у суммы штрафа; в строке 080 лишаем игрока лицензии расы
$owner; в строке 081 записываем в бортжурнал игрока матюков от расы-владельца,
подставляя в текст расу и сумму штрафа; в строке 082 тетка говорит, что
"Получено сообщение". Текст матюков берется из языкового файла пакета, который
подгружается при инициализации скрипта (здесь мы это не рассматриваем).
084
085 return null
Все, погрузка завершена, выход из скрипта.
086
087 * ---------------------- UNLOADING --------------------- Коментарий
"РАЗГРУЗКА"
088 unload.asteroid:
Это наша метка "разгрузка", на которую мы переходим из начала скрипта, когда
обнаруживаем наличие астероида на борту.
089
090 $energy = $ship -> get amount of ware Кристаллы in cargo bay
091 skip if $energy >= 25
092 goto label not.correct
Проверяем, есть ли у нас 25 кристаллов для операции разгрузки. Если их меньше,
то переходим по метке not.correct, иначе движемся дальше.
093
094 $aster.param = $ship -> get local variable: name='asteroid'
Читаем значение локальной переменной 'asteroid', и предаем его в массив
$aster.param.
095 $res.type = $aster.param[0]
096 $yield = $aster.param[1]
097 $aster.type = $aster.param[2]
Присваиваем значения ячеек массива переменным ресурса, жирности и подтипа
астероида. Мы с ними уже знакомы.
098
099 $x = $ship -> get x position
100 $y = $ship -> get y position
101 $z = $ship -> get z position
Получаем в соответствующие переменные значения координат корабля в секторе.
102 $x = $x + 2000
103 $y = $y + 2000
104 $z = $z + 2000
Увеличиваем значения координат на 2000 м каждую.
105 $aster = create asteroid: type=$aster.type
addto=[SECTOR] resource=$res.type yield=$yield x=$x y=$y z=$z
Создаем астероид в текущем секторе с необходимыми параметрами, с координатами
х,у и z, и передаем указатель на астероид пременной $aster.
106 skip if $aster
107 return null
На всякий случай проверяем, создался ли астероид. Если нет ($aster=null), то
выходим из скрипта. Это может произойти в случае, если мы не захватывали
астероид как положено, а тупо добавили его в трюм командой add ware.
Соответственно, у нас не будет нужных параметров астероида, хранящихся в
локальной переменной 'asteroid'. Но ведь мы не читеры, так делать не будем!
108
109 = $ship -> add -1 units of Астероид
110 = $ship -> add -25 units of Кристаллы
Удаляем из трюма астероид и 25 кристалов.
111
112 @ = wait 2000 ms
113 = speak text: page=17 id=3721 priority=0
114 = speak text: page=13 id=5 priority=0
Борткомпьютер говорит:
"Астероид"
"выброшен".
115
116 return null
Все, выход из разгрузки.
117
118 not.correct:
119 @ = wait 2000 ms
120 = speak text: page=13 id=135 priority=0
121 return null
А вот и махонькая подпрограмма, в которыю мы переходим при ошибках. Здесь
автопилот говорит "Команда отклонена" и происходит выход из скрипта.
Оглавление | Сообщение об ошибках | Ваше мнение о проекте | E-Mail автору |