Изменение параметров тренировки десанта и абордажа с помощью HEX-редак...
X3 Terran Conflict / X3 Земной конфликт
 
X3 Terran conflict  
 

На сайте онлайн (человек): 78



 



Изменение параметров тренировки десанта и абордажа с помощью HEX-редак...

Terran Conflict (X3TC) / Форум / Скрипты и моды для X3 Terran Conflict / Гайд-Парк

Автор: denissaha
(19.02.2012 02:37:55)

Изменение параметров тренировки десанта и абордажа с помощью HEX-редактора. Модификация obj-файла.



Инструментарий:
1. Дизассемблер obj-файлов.
2. X3 Editor 2. Качайте версию поновее - не ошибетесь.
3. Любой HEX-редактор. HxD, UltraEdit, Hiew - в общем любой.

Необходимые знания: 
1. X3Editor - нужно!
2. Программирование - не больно то и нужно , но если есть базовые познания в ассемблере, будет проще разобраться.

Причина возникновения данного урока: Весьма частый и весьма справедливый вопрос:
почему десант тренируется дольше, чем длится сюжетка + все побочные + миссии корпораций + "та када ж они там натренируются?" + "надоело уже ждать" + "та я уже на хаб натаскал всего, а они еще трениру...".
В общем, надеюсь, понятно.

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

Дополнительно добавлю, что здесь рассматривается как-раз "грубая" модификация obj (я бы даже сказал "взлом"), а не через дизассемблер - ассемблер.

Урок будет делаться на чистой Х3ТС v 3.2.

Итак, подготовка.

1. Выдираем X3Editor-ом файл x3story.obj, который находится в 13.cat (справедливо для чистой Х3ТС 3.2)
2. Создаем где вам удобно папку и называем ее, к примеру, "asm". В этой папке мы будем держать исходный + декомпилированный x3story.obj.
3. Помещаем в вашу папку "asm" все файлы из архива с декомпилятором, в эту же папку закидываем свежевыдранный x3story.obj
4. В папке "asm" находим файл "dobj.exe", жмем правой мышей и выбираем пункт "создать ярлык". Потом выбираем только что созданный ярлык, жмем его правой мышей, выбираем "свойства" и в самом конце дописываем x3story.obj после пробела (!!!)
5. Запускаем сей ярлык. После непродолжительного черного окошка с бегущими буквами/цифрами видим в папке "asm" кучу файлов. Нас интересует один - "x3story.out" - в этом файле приведен листинг на ассемблере, а слева вид в машинном коде, самое то, что доктор прописал.

Собственно, подготовка закончена, теперь немного матчасти.

Прежде всего следует прочитать этот материал, чтобы хоть немного понять, почему мы будем менять те или иные коды в нашем подопытном x3story.obj.

Сразу выделю основные данные из вышеприведенной статьи, а именно:
1. Время (одного быстрого курса)
 
Продолжительность (в минутах) быстрого обучения по одной дисциплине составляет:
5 + (<текущий уровень> / 5 + 1)2
 

2. Бабос (за один быстрый курс)
 
Стоимость быстрого обучения по одной дисциплине составляет:
5000 + 2000 x (<текущий уровень> / 5 + 1)
 


По логике вещей, чем выше уже натренированный уровень, тем дольше/дороже будет тот самый быстрый курс.

Давайте вычислим.

Задача: имеем двух десов, дес1 и дес2.
Необходимо рассчитать время/сумму быстрого обучения хакерству при следующих условиях:
дес1 - текущее хакерство = 5
дес2 - текущее хакерство = 87

Ответ:
1.а) время быстрого курса для дес1 = 5 + ( 5 / 5 + 1) * (5 / 5 + 1) = 6 минут, ясен пень, игровых
1.б) бабос быстрого курса для дес1 = 5т + 2т * (5 / 5 + 1) = 5т + 2т * 2 = 9т, что, в общем, недорого
2.а) время быстрого курса для дес2 = 5 + ( 87 / 5 + 1) * (87 / 5 + 1) = 5 + 18,4 * 18,4 = 343,56 минут, то есть примерно 6 часов
2.б) бабос быстрого курса для дес2 = 5т + 2т * (87 / 5 + 1) = 5т + 2т * 18,4 = 41800, что, в общем, опять недорого

Немного отвлекусь.
Для более-менее успешного захвата М6 вам необходимы как минимум 8 хорошо прокачанных десов, минимум 2 из которых должны быть "мега-механикусами", 2 - "кулхацкерами", остальные какие-никакие "технари", иначе они развялят жертву так и не добравшись до заветного статуса "взлом ядра".
Предположим вы долго играете и поэтому богаче, чем генеральный директор "Плутарх майнинг". Потратиться на обучение вы себе позволить можете.
Но есть одно но - покупая на станции хакера, вы замечаете, что он не драчун, так сказать. То же с механиками и технарями. Поэтому, когда вся эта разнорасовая банда ломится по кораблю, логика программы расчитана так, чтобы на каждой палубе дохли слабейшие по характеристикам боя. Справедливо, ничего не попишешь. А кто у нас слабейшие по бою? Как раз они, кулхацкеры. У тренированных hacker-only шанс добраться до последней палубы катастрофически приближается к нулю с каждой палубой, а там то они как раз и нужны.
Итог: для сколачивания команды вы должны найти 8 нихрена себе бойцов, 2 из которых потом натренируете на хак, 2 других на пробой корпуса (механики), а остальных натаскаете на технику.

Приведу цитату из статьи про захват ракетного фрегата, которая описывает создание деса "на продажу":
 
Создание десантника:
 Создается десантник с навыком боя от 1 до 40 и остальными навыками от 1 до 15.
 С вероятностью 20% на этом процесс создания заканчивается.
 В остальных 80% случаев случайно выбирается один навык и он повышается на 20-49 единиц.

Последствия:
 У хороших бойцов все прочие навыки не дотягивают даже до одной звезды.
 Максимальный боевой уровень десанта, доступного в продаже - 89 (пять звезд).
 Максимальный уровень небоевых навыков - 64 (три звезды).
 Максимальный боевой уровень хорошего хакера, механика или инженера - 40 (две звезды).
 


Итого, покупая деса-бойца, вы получаете никакого хакера/технаря/механика, с небоевым навыком максимум 15. Предоставлю вам самостоятельно посчитать, сколько по времени займет тренировка от 15 до заветных 98-100 одного деса.

Итак, с матчастью закончили, "начинаем хак системы".

Для целей урока я установил себе x3_tc_cheats и начал новую "свою игру" (без сюжета). Потом я через чит меню создал себе корабль TM, установил в него биосканер, добавил бабоса, открыл все сектора и стыковался с военным аванпостом в секторе "Черное солнце". Да простят меня все "античитеры", но мне хочется объяснить как это сделать, но не хочется летать туда-сюда.

В списке "продажных" десов был некий Элисон Дана с такими характеристиками: бой - 65, техника - 5, механика - 6, хакерство - 13. Я его купил нанял и решил замерить сколько времени займет тренировка одного подробного курса по хакерству.

Сохранив игру прямо перед тренировкой, я запустил тренировку Элисона на хакерство - подробно (95000 кредитов)

Тренировка начата в "00:11:58" по игровому времени. Я не стал дожидаться окончания тренировки, а остановил замеры на 20% тренировки. Игровое время было "01:24:10". Итого разница примерно 1 час 12 минут. Если умножить на 5 - то на полную тренировку нужно было бы почти 6 часов игрового времени. При этом дес добрался бы до уровня хакерства от 38 до 58. Последующая тренировка заняла бы еще большее время. Нас это не устраивает.

В полученном нами раньше x3story.out находится двойной листинг почти всей логики Х3ТС. За время/стоимость подготовки десанта отвечает класс "SHIP_SPEAKER", а именно два метода этого класса "GetNextTrainingCost" и "GetNextTrainingDuration". За сам процесс подготовки, отвечеат метод "RunTraining", класса "STATION". Этот метод вызывается из метода "StartTraining" того-же класса.

Давайте сначала разберем код метода "RunTraining".

Открываем x3story.out любым редактором, к примеру, блокнотом и ищем в нем следующий текст "RunTraining" до тех пор, пока не найдем следующий код:
Листинг 1.

 Код:
  1. ;
  2. ; === RunTraining ===============================================
  3. ; function  STATION.RunTraining();
  4. ;
  5.                                |      STATION.RunTraining:
  6. 0008B44A: 6E 0006              |    0            enter      0, 6
  7. 0008B44D: 0F 0027              |    0 L0008B44D: read       STATION.var_2016_29 ; [39d ; 27h]
  8. 0008B450: 34 0008B469          |    1            if SP[0]=0 then jump L0008B469
  9. 0008B455: 0F 0027              |    0            read       STATION.var_2016_29 ; [39d ; 27h]
  10. 0008B458: 02                   |    1            push       1
  11. 0008B459: 82 0000057A          |    2            callasm    SE_ArraySize
  12. 0008B45E: 34 0008B469          |    1            if SP[0]=0 then jump L0008B469
  13. 0008B463: 02                   |    0            push       1
  14. 0008B464: 32 0008B46A          |    1            jump       L0008B46A
  15. 0008B469: 01                   |    0 L0008B469: push       0
  16. 0008B46A: 34 0008B4F8          |    1 L0008B46A: if SP[0]=0 then jump L0008B4F8
  17. [color=yellow]0008B46F: 06 03E8              |    0            pushw      1000d ; 03E8h[/color]
  18. 0008B472: 02                   |    1            push       1
  19. [color=yellow]0008B473: 82 00002561          |    2            callasm    TI_Delay[/color]
  20. 0008B478: 24                   |    1            pop
  21. 0008B479: 01                   |    0            push       0
  22. 0008B47A: 0F 0027              |    1            read       STATION.var_2016_29 ; [39d ; 27h]
  23. 0008B47D: 02                   |    2            push       1
  24. 0008B47E: 82 0000057A          |    3            callasm    SE_ArraySize
  25. 0008B483: 02                   |    2            push       1
  26. 0008B484: 4B                   |    3            sub        SP[0],SP[1]
 


Процесс начала и хода тренировки выглядит так:
1. При начале тренировки система запрашивает сколько времени "GetNextTrainingDuration" и бабоса "GetNextTrainigCost" необходимо для повышения выбранных навыка(-ов) текущего деса.
2. Если у игрока хватает кредитов, бабос снимается со счета, данные о времени заносятся в специальный внутренний массив, который потом использует функция "RunTraining"
3. Функция "RunTraining" ежесекундно отнимает от оставшегося на тренировку времени по секунде и, когда оставшихся на тренировку секунд = 0, передает управление на метод "FinishedTraining", который увеличивает тренируемый навык на 5 + SE_Random(5) и маячит игроку о том, что "тут чувак, накачался, ждет тебя там-то"

Как мы можем это использовать:
Вариант 1. "Заставить" систему чаще отнимать одну секунду.
Обратите внимание на две желтых строчки кода, которые я выделил.
Переводя на понятный нам, гуманоидам, язык - в первой желтой строчке устанавливается время задержки в миллисекундах, во второй желтой строчке, вызывается сама задержка (TI_Delay), после которой уже и идет отнимание секунд и прочая программистская дрянь, которая нам сейчес не суть важна.

Давайте вместо 1000d сделаем задержку в 0001d. По логике, метод "RunTraining" будет задерживаться на тысячу раз меньше, соответственно система будет вызывать его в тысячу раз чаще, что приведет к тысячекратному увеличению скорости тренировки.

Приступим. Внутри папки, в которую вы установили игру, есть папка "L". Если нет создайте ее. Внутрь этой папки необходимо поместить файл x3story.obj, который раньше мы выдрали из 13.cat. Теперь откройте этот файл любым HEX-редактором. Я использовал HxD.
Теперь вернемся к листингу программы. В первой желтой строчке указано 16-ричное смещение от начала файла, в котором находится необходимый нам машинный код, а именно помещение в вершину стека значения задержки - 1000. В НЕХ-редакторе нам нужно перейти/прокрутить до тех пор, пока мы не встретим данный адрес. В HxD я нажал CTRL+G и ввел туда адрес 0008B46F. Сразу оговорюсь, что декомпилятор не всегда точно определяет смещение внутри obj-файла. Но именно здесь нам поможет то, что в файле x3story.out слева указаны машинные коды необходимых нам команд. Поэтому мы начинаем искать ту последовательность цифр, которая указана сразу после адреса, а именно 06 03E8. Я обнаружил эти цифры чуть дальше по ходу, в адресе 0008B483.
Если вы не хотите искать или не можете найти, тогда просто переходите в НЕХ-редакторе по найденному мной адресу. Теперь мы должны заменить 06 03E8 на 06 0001 и сохранить изменения.

Запускаем Х3ТС и повторно пытаемся тренировать того-же Элисона Дану. Тренировка начата "00:11:53", закончена в "00:16:26" - итог примерно 4,5 минуты. Проверяем данные Элисона - все ОК, хакерство 53.

Подведем итоговую черту под Вариантом №1.
Плюсы: 
1. Мы добились увеличения скорости тренировки.
А теперь минусы: тут поболее будет
1. Мы не уменьшили время тренировки, а увеличили частоту вызова функции
2. Исходя из п.1 мы "нагрузили" систему, заставив ее 1000 раз в секунду исполнять то, что расчитано на 1 раз в секунду
3. Если у вас установлен мод, который показывает время тренировки, то вы обнаружите, что время идет не посекудно, а скачками по несколько секунд
4. СУВ (SETA) может слабо влиять на время тренировки, т.к. компьютер просто не будет успевать выделять необходимые 1000 вызовов процессорного времени на нашу функцию "RunTraining"
5. Мы не добились снижения стоимости тренировки

Результат: данный вариант можно использовать как "ленивый", или когда мы хотим увеличить скорость например в 2-3 раза, то есть подставлять вместо 1000, 500 или к, примеру 300. При всем при этом нам не важно, что моды типа "время тренировки десанта" будут врать.

Вариант 2. Действительно уменьшить время/стоимость тренировки одного быстрого курса.

Прежде всего, в папку "L" внутри папки с игрой заново скопируем исходный x3story.obj, так как там находится "исковерканный" вариантом 1.

Давайте снова вернемся к вышеприведенным цитатам:
 
Продолжительность (в минутах) быстрого обучения по одной дисциплине составляет:
5 + (<текущий уровень> / 5 + 1)2
Стоимость быстрого обучения по одной дисциплине составляет:
5000 + 2000 x (<текущий уровень> / 5 + 1)
 


Сначала попробуем "выделить" числа, которые, скажем так, "константны".

В формуле расчета времени - это исходные 5 минут, делитель на 5 и, как видим, возведение в квадрат.
Заменим исходные "5 + (<..." на "0 + (<...". Что это нам дает?
Возьмем навык 87 и рассчитаем быстрый курс по навыку: 0 + (87 / 5 + 1) * (87 / 5 + 1) = (17,4 + 1) * (17,4 + 1) = 338,56 = 5 часов 64 минуты. М-да. Не фонтан!
Теперь давайте заменим делитель (т.е. "<текущий уровень> / 5")
Возьмем навык 87 и рассчитаем быстрый курс по навыку при делителе 50: 5 + (87 / 50 + 1) * (87 / 50 + 1) = 5 + 2,74 * 2,74 = примерно 13 минут. Вот это уже похоже на "оно".
Если же мы еще и возведение в квадрат заменим сложением, тогда вообще десант будет тренироваться за считанные минуты.

То же с денюжкой:
5000 + 2000 * (<текущий уровень> / 5 + 1)
Например заменив "2000 * (<..." на "500 * (<..." мы заметим резкое снижение стоимости тренировки. Причем это будет заметно на более высоких уровнях тренировки.

Давайте перейдем к делу.

Сначала найдем в нашем декомпилированном x3sotry.out необходимые функции. Как мы уже выяснили это функции "GetNextTrainingCost" и "GetNextTrainingDuration"

Листинг 2. (GetNextTrainingCost)

 Код:
  1. ;
  2. ; === GetNextTrainingCost =======================================
  3. ; function  SHIP_SPEAKER.GetNextTrainingCost(arg1, arg2);
  4. ;
  5.                                |      SHIP_SPEAKER.GetNextTrainingCost:
  6. 000C628B: 6E 0008              |    0            enter      2, 8
  7. 000C628E: 01                   |    0            push       0
  8. ... тут коды-коды-коды и вот то, что нам нужно...
  9. 000C6312: 0D 0002              |    3 L000C6312: push       SP[1] ; loc2
  10. 000C6315: 05 05                |    4            pushb      5
  11. 000C6317: 51                   |    5            div        SP[0],SP[1]
  12. 000C6318: 02                   |    4            push       1
  13. 000C6319: 46                   |    5            add        SP[0],SP[1]
  14. 000C631A: 0D 0004              |    4            push       SP[3] ; loc1
  15. [color=yellow]000C631D: 06 1388              |    5            pushw      5000d ; 1388h[/color]
  16. 000C6320: 0D 0003              |    6            push       SP[2] ; loc4
  17. [color=yellow]000C6323: 06 07D0              |    7            pushw      2000d ; 07D0h[/color]
  18. 000C6326: 50                   |    8            mul        SP[0],SP[1]
  19. 000C6327: 46                   |    7            add        SP[0],SP[1]
  20. 000C6328: 46                   |    6            add        SP[0],SP[1]
  21. 000C6329: 14 0005              |    5            mov        SP[4],SP[0] ; loc1
  22. 000C632C: 24                   |    5            pop
  23. 000C632D: 0D 0003              |    4            push       SP[2] ; loc2
 


В листинге 2 мы снова обнаруживаем наши "константные числа", поменяв которые мы сможем уменьшить стоимость тренировки. Итак, по накатанной, в НЕХ-редакторе открываем x3stroy.obj, переходим по адресу 000C6323, чуть "дальше" ищем 06 07D0 и меняем на 06 01F4, что в "переводе" на ассемблер будет значить "pushw      500d ; 01F4h".

Запускаем Х3ТС, пытаемся тренировать нашего многострадального Элисона Дану - стоимость вместо 95000 равна 42500.

В итог, мы безболезненно для системы уменьшили стоимость тренировки.

Сразу пойдем дальше, ведь еще необходимо уменьшить и время тренировки. Находим функцию "GetNextTrainingDuration".

Листинг 3. (GetNextTrainingDuration)

 Код:
  1. ;
  2. ; === GetNextTrainingDuration ===================================
  3. ; function  SHIP_SPEAKER.GetNextTrainingDuration(arg1, arg2);
  4. ;
  5.                                |      SHIP_SPEAKER.GetNextTrainingDuration:
  6. 000C634B: 6E 0008              |    0            enter      2, 8
  7. 000C634E: 01                   |    0            push       0
  8. ... коды-коды-коды, стоп, кажется нашли...
  9. 000C63D2: 0D 0002              |    3 L000C63D2: push       SP[1] ; loc2
  10. 000C63D5: 05 05                |    4            pushb      5 ; ДЕЛИТЕЛЬ
  11. 000C63D7: 51                   |    5            div        SP[0],SP[1]
  12. 000C63D8: 02                   |    4            push       1
  13. 000C63D9: 46                   |    5            add        SP[0],SP[1]
  14. 000C63DA: 0D 0004              |    4            push       SP[3] ; loc1
  15. 000C63DD: 06 012C              |    5            pushw      300d ; 012Ch исходные 5 минут * 60 сек
  16. 000C63E0: 0D 0003              |    6            push       SP[2] ; loc4
  17. 000C63E3: 0D 0004              |    7            push       SP[3] ; loc4
  18. 000C63E6: 50                   |    8            mul        SP[0],SP[1] ; возведение в квадрат
  19. 000C63E7: 05 3C                |    7            pushb      60d ; 3Ch
  20. 000C63E9: 50                   |    8            mul        SP[0],SP[1] ; умножение результата в минутах на 60 сек
  21. 000C63EA: 46                   |    7            add        SP[0],SP[1]
  22. 000C63EB: 46                   |    6            add        SP[0],SP[1]
  23. 000C63EC: 14 0005              |    5            mov        SP[4],SP[0] ; loc1
  24. 000C63EF: 24                   |    5            pop
 


Ну, здесь я уже не буду в подробностях расписывать как заменить.
Возможностей - куча:
Если по адресу 000C63D5 (не забудьте, что в НЕХ-е искать надо чуть "дальше")
000C63D5: 05 05                |    4            pushb      5 ;
заменить 0505 на 0532 - получим делитель не 5 а 50
000C63D5: 05 32                |    4            pushb      50d ; 32h

Если по адресу 000C63DD
000C63DD: 06 012C              |    5            pushw      300d ; 012Ch ; // исходные 5 минут * 60 сек
заменить 06012C на 060000 - исходные 5 минут станут 0
000C63DD: 06 0000              |    5            pushw      0d ; 0000h ; // исходные 5 минут * 60 сек

Если по адресу 000C63E6
000C63E6: 50                   |    8            mul        SP[0],SP[1] ; возведение в квадрат
заменить 50 на 46 - вместо квадрата получим просто сложение двух результатов
000C63E6: 46                   |    8            add        SP[0],SP[1] ; сложение!!!

Ну и на закуску:
Если по адресу 000C63E7
000C63E7: 05 3C                |    7            pushb      60d ; 3Ch
заменить 053C на 0501 - вместо (Х минут * 60 сек) получим (Х минут * 1 сек.)
000C63E7: 05 01                |    7            pushb      1

Фух, устал!
Ладно, вроде изменить время/стоимость тренировок мы умеем. А что же по поводу абордажа.
Вернее по поводу уничтожения оборудования.
Давайте рассмотрим такую ситуацию с абордажем:
Летит себе такой не спеша М1. А куда ему торопиться? У него 2ГДж щитов пара-тройка, десятки больших пух, да и сам по себе он не какой-то там М5. Мы его закидали ракетами, сняли щиты, позагоняли на него кучу десантников, которые "Есть! Входим в корабль... Пошли!", "Смотреть, куда стреляете", "Санитар! Здесь раненый!" и "Мы в центре управления...". Наконец слышим заветное "Передача управления кораблем завершена". Классно, короче.
И вот, после взлома компьютера, начинается самое, я бы сказал, фееричное. Исчезает практически все! Куда оно все девается? Если, по замыслу разрабов, десы воруют, тогда почему не слышно фраз типа "Ребята, тащите эту фотонку на капсулу, столкнем на торговой станции". Или, может, десы все переломали. Ну, например, 8 выживших десантников от счастья забухали и давай пинать "берцами" щиты. Огромные такие, которые могут держать мощные выстрелы фотонок. А щиты же не приспособлены, чтобы их ногами пинали. Вот и ломаются. Так десам этого мало, они еще и пухи все давай пинать. А потом идет пятизвездочный Мули Ха по второй палубе, а там к корме прыжковый двигатель прикручен. И рядом пара тысяч DURACELL сложена. Он такой, типа "А эт чё за ...?!?!". И давай это все добро пинать "берцами".
В общем не понравилась мне эта задумка разрабов. Конечно, кто-нибудь скажет, что так интереснее, надо сначала захватить, потом по новой оснастить, и т.д. Но, не нравится мне такая задумка и все. Хоть ты трескни!
Решил я это дело подправить, заодно и вам расскажу как уменьшить потери оборудования от неумеренного  злоупотребления десантников.

Итак, вернемся к нашему файлу x3story.out. В нем описан класс "SHIP", у которого есть метод "DowngradeTakeOver". Метод этот вызывается в двух случаях: когда вражеский пилот сливается с мелкого корабля и когда наши развеселые десы захватывают бигшип. А в самом методе описывается алгоритм исчезновения оборудования. Давайте взглянем на листинг:
Листинг 4.

 Код:
  1. ;
  2. ; === DowngradeTakeOver =========================================
  3. ; function  SHIP.DowngradeTakeOver();
  4. ;
  5.                                |      SHIP.DowngradeTakeOver:
  6. 000BB93C: 6E 0009              |    0            enter      0, 9
  7. 000BB93F: 06 03E8              |    0            pushw      1000d ; 03E8h
  8. 000BB942: 02                   |    1            push       1
  9. 000BB943: 82 00002561          |    2            callasm    TI_Delay
  10. 000BB948: 24                   |    1            pop
  11. 000BB949: 01                   |    0            push       0
  12. 000BB94A: 01                   |    1            push       0
  13. 000BB94B: 14 0002              |    2            mov        SP[1],SP[0] ; loc1
  14. 000BB94E: 24                   |    2            pop
  15. 000BB94F: 0D 0001              |    1 L000BB94F: push       SP[0] ; loc1
  16. 000BB952: 05 08                |    2            pushb      8
  17. 000BB954: 02                   |    3            push       1
  18. 000BB955: 82 000002E2          |    4            callasm    SA_GetNumSubTypes
  19. 000BB95A: 5C                   |    3            if SP[0]<=SP[1] then push 0 else push 1
  20. 000BB95B: 34 000BB9CE          |    2            if SP[0]=0 then jump L000BB9CE
  21. 000BB960: 32 000BB973          |    1            jump       L000BB973
  22. 000BB965: 0D 0001              |    1 L000BB965: push       SP[0] ; loc1
  23. 000BB968: 02                   |    2            push       1
  24. 000BB969: 46                   |    3            add        SP[0],SP[1]
  25. 000BB96A: 14 0002              |    2            mov        SP[1],SP[0] ; loc1
  26. 000BB96D: 24                   |    2            pop
  27. 000BB96E: 32 000BB94F          |    1            jump       L000BB94F
  28. 000BB973: 01                   |    1 L000BB973: push       0
  29. 000BB974: 0D 0002              |    2            push       SP[1] ; loc1
  30. 000BB977: 05 08                |    3            pushb      8
  31. 000BB979: 03                   |    4            push       2
  32. 000BB97A: 88 000A8CB9          |    5            call88     SHIP.GetWareTypeCount
  33. 000BB97F: 14 0002              |    3            mov        SP[1],SP[0] ; loc2
  34. 000BB982: 34 000BB9C8          |    3            if SP[0]=0 then jump L000BB9C8
  35. 000BB987: 0F 000C              |    2            read       SHIP.var_2004_2 ; [12d ; 0Ch]
  36. 000BB98A: 05 07                |    3            pushb      7
  37. 000BB98C: 03                   |    4            push       2
  38. 000BB98D: 82 00000E2C          |    5            callasm    SA_GetTypeDefaultRace
  39. 000BB992: 05 07                |    3            pushb      7
  40. 000BB994: 5B                   |    4            if SP[0]<>SP[1] then push 0 else push 1
  41. 000BB995: 0D 0001              |    3            push       SP[0] ; loc3
  42. 000BB998: 34 000BB9A4          |    4            if SP[0]=0 then jump L000BB9A4
  43. [color=yellow]000BB99D: 05 32                |    3            pushb      50d ; 32h[/color]
  44. 000BB99F: 32 000BB9A6          |    4            jump       L000BB9A6
  45. [color=yellow]000BB9A4: 05 5A                |    3 L000BB9A4: pushb      90d ; 5Ah[/color]
  46. 000BB9A6: 05 64                |    4 L000BB9A6: pushb      100d ; 64h
  47. 000BB9A8: 02                   |    5            push       1
  48. 000BB9A9: 82 000002C4          |    6            callasm    SE_Random
  49. 000BB9AE: 0D 0002              |    5            push       SP[1] ; loc4
  50. 000BB9B1: 5C                   |    6            if SP[0]<=SP[1] then push 0 else push 1
  51. 000BB9B2: 34 000BB9C5          |    5            if SP[0]=0 then jump L000BB9C5
  52. 000BB9B7: 0D 0003              |    4            push       SP[2] ; loc2
  53. 000BB9BA: 65                   |    5            neg        SP[0]
  54. 000BB9BB: 0D 0005              |    5            push       SP[4] ; loc1
  55. 000BB9BE: 03                   |    6            push       2
  56. 000BB9BF: 88 000A4A76          |    7            call88     SHIP.AddLaser
  57. 000BB9C4: 24                   |    5            pop
  58. 000BB9C5: 23 0002              |    4 L000BB9C5: popx       2
  59. 000BB9C8: 24                   |    2 L000BB9C8: pop
  60. 000BB9C9: 32 000BB965          |    1            jump       L000BB965
  61. 000BB9CE: 01                   |    1 L000BB9CE: push       0
  62. 000BB9CF: 14 0002              |    2            mov        SP[1],SP[0] ; loc1
  63. 000BB9D2: 24                   |    2            pop
  64. 000BB9D3: 0D 0001              |    1 L000BB9D3: push       SP[0] ; loc1
  65. 000BB9D6: 05 09                |    2            pushb      9
  66. 000BB9D8: 02                   |    3            push       1
  67. 000BB9D9: 82 000002E2          |    4            callasm    SA_GetNumSubTypes
  68. 000BB9DE: 5C                   |    3            if SP[0]<=SP[1] then push 0 else push 1
  69. 000BB9DF: 34 000BBA2F          |    2            if SP[0]=0 then jump L000BBA2F
  70. 000BB9E4: 32 000BB9F7          |    1            jump       L000BB9F7
  71. 000BB9E9: 0D 0001              |    1 L000BB9E9: push       SP[0] ; loc1
  72. 000BB9EC: 02                   |    2            push       1
  73. 000BB9ED: 46                   |    3            add        SP[0],SP[1]
  74. 000BB9EE: 14 0002              |    2            mov        SP[1],SP[0] ; loc1
  75. 000BB9F1: 24                   |    2            pop
  76. 000BB9F2: 32 000BB9D3          |    1            jump       L000BB9D3
  77. 000BB9F7: 01                   |    1 L000BB9F7: push       0
  78. 000BB9F8: 0D 0002              |    2            push       SP[1] ; loc1
  79. 000BB9FB: 05 09                |    3            pushb      9
  80. 000BB9FD: 03                   |    4            push       2
  81. 000BB9FE: 88 000A8CB9          |    5            call88     SHIP.GetWareTypeCount
  82. 000BBA03: 14 0002              |    3            mov        SP[1],SP[0] ; loc2
  83. 000BBA06: 34 000BBA29          |    3            if SP[0]=0 then jump L000BBA29
  84. 000BBA0B: 05 64                |    2            pushb      100d ; 64h
  85. 000BBA0D: 02                   |    3            push       1
  86. 000BBA0E: 82 000002C4          |    4            callasm    SE_Random
  87. [color=yellow]000BBA13: 05 5A                |    3            pushb      90d ; 5Ah[/color]
  88. 000BBA15: 5C                   |    4            if SP[0]<=SP[1] then push 0 else push 1
  89. 000BBA16: 34 000BBA29          |    3            if SP[0]=0 then jump L000BBA29
  90. 000BBA1B: 0D 0001              |    2            push       SP[0] ; loc2
  91. 000BBA1E: 65                   |    3            neg        SP[0]
  92. 000BBA1F: 0D 0003              |    3            push       SP[2] ; loc1
  93. 000BBA22: 03                   |    4            push       2
  94. 000BBA23: 88 000A48AC          |    5            call88     SHIP.AddShield
  95. 000BBA28: 24                   |    3            pop
  96. 000BBA29: 24                   |    2 L000BBA29: pop
  97. 000BBA2A: 32 000BB9E9          |    1            jump       L000BB9E9
  98. 000BBA2F: 01                   |    1 L000BBA2F: push       0
  99. 000BBA30: 14 0002              |    2            mov        SP[1],SP[0] ; loc1
  100. 000BBA33: 24                   |    2            pop
  101. 000BBA34: 0D 0001              |    1 L000BBA34: push       SP[0] ; loc1
  102. 000BBA37: 05 0A                |    2            pushb      10d ; 0Ah
  103. 000BBA39: 02                   |    3            push       1
  104. 000BBA3A: 82 000002E2          |    4            callasm    SA_GetNumSubTypes
  105. 000BBA3F: 5C                   |    3            if SP[0]<=SP[1] then push 0 else push 1
  106. 000BBA40: 34 000BBA90          |    2            if SP[0]=0 then jump L000BBA90
  107. 000BBA45: 32 000BBA58          |    1            jump       L000BBA58
  108. 000BBA4A: 0D 0001              |    1 L000BBA4A: push       SP[0] ; loc1
  109. 000BBA4D: 02                   |    2            push       1
  110. 000BBA4E: 46                   |    3            add        SP[0],SP[1]
  111. 000BBA4F: 14 0002              |    2            mov        SP[1],SP[0] ; loc1
  112. 000BBA52: 24                   |    2            pop
  113. 000BBA53: 32 000BBA34          |    1            jump       L000BBA34
  114. 000BBA58: 01                   |    1 L000BBA58: push       0
  115. 000BBA59: 0D 0002              |    2            push       SP[1] ; loc1
  116. 000BBA5C: 05 0A                |    3            pushb      10d ; 0Ah
  117. 000BBA5E: 03                   |    4            push       2
  118. 000BBA5F: 88 000A8CB9          |    5            call88     SHIP.GetWareTypeCount
  119. 000BBA64: 14 0002              |    3            mov        SP[1],SP[0] ; loc2
  120. 000BBA67: 34 000BBA8A          |    3            if SP[0]=0 then jump L000BBA8A
  121. 000BBA6C: 05 64                |    2            pushb      100d ; 64h
  122. 000BBA6E: 02                   |    3            push       1
  123. 000BBA6F: 82 000002C4          |    4            callasm    SE_Random
  124. [color=yellow]000BBA74: 05 5A                |    3            pushb      90d ; 5Ah[/color]
  125. 000BBA76: 5C                   |    4            if SP[0]<=SP[1] then push 0 else push 1
  126. 000BBA77: 34 000BBA8A          |    3            if SP[0]=0 then jump L000BBA8A
  127. 000BBA7C: 0D 0001              |    2            push       SP[0] ; loc2
  128. 000BBA7F: 65                   |    3            neg        SP[0]
  129. 000BBA80: 0D 0003              |    3            push       SP[2] ; loc1
  130. 000BBA83: 03                   |    4            push       2
  131. 000BBA84: 88 000A61DC          |    5            call88     SHIP.AddMissile
  132. 000BBA89: 24                   |    3            pop
  133. 000BBA8A: 24                   |    2 L000BBA8A: pop
  134. 000BBA8B: 32 000BBA4A          |    1            jump       L000BBA4A
  135. 000BBA90: 05 0B                |    1 L000BBA90: pushb      11d ; 0Bh
  136. 000BBA92: 14 0002              |    2            mov        SP[1],SP[0] ; loc1
  137. 000BBA95: 24                   |    2            pop
  138. 000BBA96: 0D 0001              |    1 L000BBA96: push       SP[0] ; loc1
  139. 000BBA99: 05 10                |    2            pushb      16d ; 10h
  140. 000BBA9B: 5E                   |    3            if SP[0]<SP[1] then push 0 else push 1
  141. 000BBA9C: 34 000BBB28          |    2            if SP[0]=0 then jump L000BBB28
  142. 000BBAA1: 32 000BBAB4          |    1            jump       L000BBAB4
  143. 000BBAA6: 0D 0001              |    1 L000BBAA6: push       SP[0] ; loc1
  144. 000BBAA9: 02                   |    2            push       1
  145. 000BBAAA: 46                   |    3            add        SP[0],SP[1]
  146. 000BBAAB: 14 0002              |    2            mov        SP[1],SP[0] ; loc1
  147. 000BBAAE: 24                   |    2            pop
  148. 000BBAAF: 32 000BBA96          |    1            jump       L000BBA96
  149. 000BBAB4: 01                   |    1 L000BBAB4: push       0
  150. 000BBAB5: 01                   |    2            push       0
  151. 000BBAB6: 14 0002              |    3            mov        SP[1],SP[0] ; loc2
  152. 000BBAB9: 24                   |    3            pop
  153. 000BBABA: 0D 0001              |    2 L000BBABA: push       SP[0] ; loc2
  154. 000BBABD: 0D 0003              |    3            push       SP[2] ; loc1
  155. 000BBAC0: 02                   |    4            push       1
  156. 000BBAC1: 82 000002E2          |    5            callasm    SA_GetNumSubTypes
  157. 000BBAC6: 5C                   |    4            if SP[0]<=SP[1] then push 0 else push 1
  158. 000BBAC7: 34 000BBB22          |    3            if SP[0]=0 then jump L000BBB22
  159. 000BBACC: 32 000BBADF          |    2            jump       L000BBADF
  160. 000BBAD1: 0D 0001              |    2 L000BBAD1: push       SP[0] ; loc2
  161. 000BBAD4: 02                   |    3            push       1
  162. 000BBAD5: 46                   |    4            add        SP[0],SP[1]
  163. 000BBAD6: 14 0002              |    3            mov        SP[1],SP[0] ; loc2
  164. 000BBAD9: 24                   |    3            pop
  165. 000BBADA: 32 000BBABA          |    2            jump       L000BBABA
  166. 000BBADF: 0D 0001              |    2 L000BBADF: push       SP[0] ; loc2
  167. 000BBAE2: 0D 0003              |    3            push       SP[2] ; loc1
  168. 000BBAE5: 03                   |    4            push       2
  169. 000BBAE6: 88 000A8CB9          |    5            call88     SHIP.GetWareTypeCount
  170. 000BBAEB: 0D 0001              |    3            push       SP[0] ; loc3
  171. 000BBAEE: 34 000BBB1C          |    4            if SP[0]=0 then jump L000BBB1C
  172. 000BBAF3: 02                   |    3            push       1
  173. 000BBAF4: 02                   |    4            push       1
  174. 000BBAF5: 0D 0003              |    5            push       SP[2] ; loc3
  175. 000BBAF8: 46                   |    6            add        SP[0],SP[1]
  176. 000BBAF9: 02                   |    5            push       1
  177. 000BBAFA: 82 000002C4          |    6            callasm    SE_Random
  178. 000BBAFF: 46                   |    5            add        SP[0],SP[1]
  179. 000BBB00: 02                   |    4            push       1
  180. 000BBB01: 82 000002C4          |    5            callasm    SE_Random
  181. 000BBB06: 0D 0002              |    4            push       SP[1] ; loc3
  182. 000BBB09: 65                   |    5            neg        SP[0]
  183. 000BBB0A: 0D 0002              |    5            push       SP[1] ; loc4
  184. 000BBB0D: 46                   |    6            add        SP[0],SP[1]
  185. 000BBB0E: 0D 0004              |    5            push       SP[3] ; loc2
  186. 000BBB11: 0D 0006              |    6            push       SP[5] ; loc1
  187. 000BBB14: 04                   |    7            push       3
  188. 000BBB15: 87 0000000C          |    8            call87     AddWare
  189. 000BBB1A: 24                   |    5            pop
  190. 000BBB1B: 24                   |    4            pop
  191. 000BBB1C: 24                   |    3 L000BBB1C: pop
  192. 000BBB1D: 32 000BBAD1          |    2            jump       L000BBAD1
  193. 000BBB22: 24                   |    2 L000BBB22: pop
  194. 000BBB23: 32 000BBAA6          |    1            jump       L000BBAA6
  195. 000BBB28: 0F 0003              |    1 L000BBB28: read       GBODY.var_1000_3 ; [3]
  196. 000BBB2B: 34 000BBB58          |    2            if SP[0]=0 then jump L000BBB58
  197. 000BBB30: 05 11                |    1            pushb      17d ; 11h
  198. 000BBB32: 05 10                |    2            pushb      16d ; 10h
  199. 000BBB34: 03                   |    3            push       2
  200. 000BBB35: 88 000A8E67          |    4            call88     SHIP.GetWareTypeCountWithPredefined
  201. 000BBB3A: 0F 0003              |    2            read       GBODY.var_1000_3 ; [3]
  202. 000BBB3D: 03                   |    3            push       2
  203. 000BBB3E: 82 0000E253          |    4            callasm    SA_SetExtraSpeed
  204. 000BBB43: 24                   |    2            pop
  205. 000BBB44: 05 12                |    1            pushb      18d ; 12h
  206. 000BBB46: 05 10                |    2            pushb      16d ; 10h
  207. 000BBB48: 03                   |    3            push       2
  208. 000BBB49: 88 000A8E67          |    4            call88     SHIP.GetWareTypeCountWithPredefined
  209. 000BBB4E: 0F 0003              |    2            read       GBODY.var_1000_3 ; [3]
  210. 000BBB51: 03                   |    3            push       2
  211. 000BBB52: 82 0000E264          |    4            callasm    SA_SetExtraRotSpeed
  212. 000BBB57: 24                   |    2            pop
  213. 000BBB58: 24                   |    1 L000BBB58: pop
  214. 000BBB59: 01                   |    0            push       0
  215. 000BBB5A: 83                   |    1            ret
 


Вкратце, суть алгоритма такая. Программа запрашивает количество лазеров на борту. Потом проверяет - если они хаакские, значит устанвливается нижняя планка шанса на 50
 Код:
  1. 000BB99D: 05 32                |    3            pushb      50d ; 32h
 

иначе - на 90
 Код:
  1. 000BB9A4: 05 5A                |    3 L000BB9A4: pushb      90d ; 5Ah
 

Если шаровое число до 100 меньше, чем нижняя планка шанса, то все, нет больше лазеров.
Потом то же со щитами, но там уже побоку чьи, наши, ваши, любой щит исчезает с 90% вероятностью.
Потом - ракеты.
Затем по замысловатой формуле все оборудование и груз. Формула, кстати, хорошо описана  здесь

Так вот, чтобы долго не заморачиваться, я пометил желтым цветом те строки, в котроых назначаются минимальные границы шансов. Образно говоря, если все эти числа установить в 0, то при захвате любого корабля, хоть мелкого, хоть бигшипа, щиты, пухи, ракеты всегда будут целыми. Ну, а как поменять эти значения, я думаю, вы уже поймете.

дерево темы → Гайд-Парк Гайд-Парк »
Список игр