ВНИМАНИЕ! Наша конференция посвящена космической тематике и компьютерным играм. Политические вопросы и происходящие в мире события в данный момент на нашем сайте не обсуждаются!
|
» Раскопки обжа на предмет юзабельных вещей | страница 5 |
|
|
|
Канал X-Tension/X-BTF: «Раскопки обжа на предмет юзабельных вещей» |
|
|
Non
802 EGP
       Рейтинг канала: 6(383) Репутация: 239 Сообщения: 801
Зарегистрирован: 27.06.2006
 |
|
Нашёл наконец-то хотя бы такой способ увеличения ускорения разворота для корабля игрока. Вместе с разворотом увеличивается конечно и максимальная скорость разворота, но хотя бы корабль теперь не такая колымага в сравнении с прогрейджеными M5.
Побочные эффекты - на значения из этой функции exe'шника реагируют все крутящиеся объекты (планеты, торговые станции).
Для экзешника версии 2.2.
Чем меньше значение - тем быстрее разворот.
Три адреса с одинаковым значением для кручения по оси, вверх вниз и право лево.
По смещениям 00415BE1, 00415BFD, 00415C19 есть конструкции B9 E8 03 00 00.
Означают они запихнуть в один из регистров процессора значение 3E8. Первый байт это команда, следующие 4 байта - DWORD со значением.
Чтобы правильно запихнуть нужное нам число на место того что там есть, нужно у DWORD'а поменять байты задом наперёд вот так:
Код: |
E8 03 00 00
00 00 03 E8 |
Неплохое значение для этой конструкции выглядит вот так:
Корабль будет уже разворачиваться существенно быстрее, неписи будут разворачиваться так же, а торговки и планетки еще не настолько быстро, чтобы бросалось в глаза.
Я всё-таки надеюсь когда-нибудь найти как exe-шник понимает, что рулит автопилот / непись и пропорционально увеличивает ускорение разворота, а не только макс. скорость, как в XBTF.
Пока искал развороты, нашёл так же где можно отключить тряску корабля со смещением курса при разгоне, стрельбе и попаданиях по нему.
Один компонент шатает корабль, другой просто потрясывает модельку кокпита.
По смещению 004283F7 меняем байт 74 (Jump if equal, условный прыжок) на безусловный EB. Это отключит шатание корабля со сменой курса во всех ситуациях.
По смещению 00428348 меняем байт 7E (Jump if less, условный прыжок) на безусловный EB. Это отключит микротряску модельки кокпита.
Пока так.
Последний раз редактировалось: Non (05:28 29-03-2019), всего редактировалось 2 раз(а) |
|
|
Non
802 EGP
       Рейтинг канала: 6(383) Репутация: 239 Сообщения: 801
Зарегистрирован: 27.06.2006
 |
|
Чегой-т не додумался в прошлый раз IsDisabled при пересборке обжа пометить .extern'ом. Сейчас собрал обж XT с нуля и он вроде как работает.
Потестируем-с?
rebuilt-obj.7z |
Описание: |
|
Имя файла: |
rebuilt-obj.7z |
Размер файла: |
419.42 KB |
Скачано: |
488 раз(а) |
|
|
|
Non
802 EGP
       Рейтинг канала: 6(383) Репутация: 239 Сообщения: 801
Зарегистрирован: 27.06.2006
 |
|
Прикладываю патчики для ленивых делающих описанное в посте выше.
Только для версии 2.2.
Можно применять вместе.
|
|
|
Non
802 EGP
       Рейтинг канала: 6(383) Репутация: 239 Сообщения: 801
Зарегистрирован: 27.06.2006
 |
|
KWON : |
Напишите, пожалуйста, отличия и преимущества новосозданного обжа
|
При сборке обжа с нуля есть возможность добавить в существующие классы вроде TSHIP, TMENU новые переменные, необходимые для работы новых функций.
В теории можно:
- переписать функции меню на XC полностью с добавлением расширенного функционала по примеру X2
- выкидывать классы и функции целиком, квесты, функции дубли TRACE.LOGIC_(P3/P2) и другие
- перенести парсер XML из X2, дабы уже не редактировать карту в обже
- сделать сильно урезанную версию обжа с упрощенной процедурой инициализации для тестирования своих функций, поведение той же расовой логики улучшить, но без тестирования на живую это муторно
Насколько я понимаю, редактор карт меняет функцию TGALAXY.BuildFromEditor, так что проще на мой взгляд редактировать карту на оригинальном обже а потом переносить эту функцию целиком.
Возможно всё, что не требует правки по конкретным адресам, ибо они сместились.
Функционально этот обж должен быть идентичен обычному.
Естественно, если никто не будет ничего переписывать (максимальная вероятность) и добавлять функционал, то смысла в пересобранном обже немного.
Наверное больше смысла есть при совместимости с существующими сохранениями.
Но тут упираешься в ограничение - никаких новых переменных в классах с классами потомками. Т.е. захочешь новый переключатель с переменной культурно в менюшке - фигвам - исследуй возможности битовой логики и храни пятьдесят переключателей в одной неиспользуемой переменной вроде ga_ServerID или ga_ClientID.
Хочешь для своей логики поведения расовых кораблей какие-то новые переменные - тоже фигвам.
|
|
|
Non
802 EGP
       Рейтинг канала: 6(383) Репутация: 239 Сообщения: 801
Зарегистрирован: 27.06.2006
 |
|
Подумал, а чего в asm'е мозг шатать, если можно в XC функции менять без пересборки обжа. Всё равно семикратно патченый обж XT свалка. А так и мне проще, и народу будет понятнее. Многое по-прежнему с сейвами совместимо. Если не работает во время подмены обжа на патченый.
Разбираю интересующие меня функции, оставляю комментарии, обзываю переменные, причёсываю и в таком духе.
Функция TSHIP.AttackedBy, обработчик сигнала "корабль атакован".
По хорошему можно изрядно поднять читаемость этой функции, если использовать ранний возврат, вместо тонны вложенностей.
TSHIP.AttackedBy (кликните здесь для просмотра)
Код: |
// Оптимизаций почти нет, код старался оставить похожим на исходник
function TSHIP.AttackedBy(AttackedShip)
{
this->___SetVar(0, P_GetAbsTime());
// Похоже на проверку активен ли атакуемый корабль, т.е. находится ли он
// в секторе с игроком
if(AttackedShip)
{
// Существует ли атакующий корабль
var Attacker = SA_GetEventObject(AttackedShip);
if(Attacker)
{
// Если атакующий корабль станция или авианосец и действие атакуемого -
// приземлиться, то ничего не делать
if(Attacker->IsClass(TSTATION) || Attacker->IsClass(TSHIP_CARRIER) && Attacker == TSHIP.sh_ActionTarget)
{
if(TSHIP.sh_IsLanding)
{TSHIP.sh_IsLanding = -1;}
if(TSHIP.sh_IsStarting)
{TSHIP.sh_IsStarting = -1;}
SA_StopObject(TSHIP.sh_ObjectID, 2);
return(0);
}
THITLIST.Add(Attacker, this);
// Если у атакуемого и атакующего есть владельцы, при этом они не
// не одна и та же раса и атакующий - корабль игрока
// Перейти к коду обеспечивающему захват корабля
if(TSHIP.sh_Owner && Attacker->GetOwner() && Attacker->GetOwner() != TSHIP.sh_Owner && Attacker == TCLIENT.GetPlayerShip())
{
// Измерить текущую и максимальную ёмкость щитов
var ShieldLevel = SA_GetShield(TSHIP.sh_ObjectID);
var MaxShieldLevel = SA_GetMaxShield(TSHIP.sh_ObjectID);
// Лишить игрока лицензии
TCLIENT.GetPlayer()->LoseLicense(TSHIP.sh_Owner);
// Если у атакуемого есть кокпит и это не корабль игрока и нету флага
// невозможности захвата
if(SA_GetShipTypeCockpitBody(TSHIP.sh_SubType) && TSHIP.sh_Owner->GetID() != 9 && !this->___GetVar(5))
{
// Если текущая ёмкость щитов < 5%
if(ShieldLevel > 0 && (ShieldLevel < MaxShieldLevel / 20))
{
// Если последняя попытка захватить корабль делалась больше минуты назад
if(P_CmpTime(P_GetAbsTime(), TSHIP.sh_LastTakeoverChanceTime) > 60000)
{
// Запишем время текущей попытки
TSHIP.sh_LastTakeoverChanceTime = P_GetAbsTime();
// Изначальная вероятность захвата 20%
var CaptureProbability = 20;
// Если корабль игрока слабее вражеского, то 30%
if(Attacker->GetStrength() < this->GetStrength())
{CaptureProbability = 30;}
// Если корабль игрока называется EGOSOFT, то 35%
if(!SE_strcmp(Attacker->GetYourName(), "EGOSOFT"))
{CaptureProbability = 35;}
if(P_Random(1) < CaptureProbability)
{
// Получим имя пилота
var PilotName = this->GetPilotName();
// Если получили ничего то напишем просто Pilot
if(!PilotName) {PilotName = SE_MakeString("Pilot");}
// Сформируем строчку для лога о том, что пилот отдал корабль
var PilotLeftShipStr = SE_StringSPrintf(SE_ReadText(1100055), PilotName, this->GetName());
// Напишем в лог
TCLIENT.GetPlayer()->LogString(PilotLeftShipStr);
// Очистим созданные строки
SE_FreeString(PilotName);
SE_FreeString(PilotLeftShipStr);
// Выкидываем скафандр, отдаём корабль и выходим из функции
this->LeaveShip();
return(0);
}
}
}
}
}
// Узнать максимальный лазер
var AttackerMaxLaser = Attacker->GetMaxLaser() + 10;
// Запустить функцию повреждения оборудования
this->MakeDamage(P_Random(AttackerMaxLaser) + 10);
// Если атакуемый и атакующий разных рас и атакующий - корабль игрока -
// снять репутацию
if(TSHIP.sh_Owner && Attacker->GetOwner() && Attacker->GetOwner() != TSHIP.sh_Owner && Attacker->GetOwner() == TCLIENT.GetPlayer())
{
var LastNotorietyHit = TCLIENT.GetPlayer()->GetLastNotorietyHitTime();
if(P_CmpTime(P_GetAbsTime(), LastNotorietyHit) > 60000)
{
TSHIP.sh_Owner->AddNotoriety(Attacker->GetOwner(), -1);
TCLIENT.GetPlayer()->SetLastNotorietyHitTime(P_GetAbsTime());
}
}
}
// Если это не корабль игрока, но игрок владелец и это не боевой дрон -
// уведомить о том что корабль атакован
if(!TSHIP.sh_IsPlayer && TSHIP.sh_Owner && TSHIP.sh_Owner->GetID() == 9 && !this->IsClass(TFIGHTDRONE)) {
TCLIENT.NotifyAttacked(this);
}
// Если это корабль игрока мигать красным на карте что он атакован
if(TSHIP.sh_IsPlayer && AttackedShip && Attacker) {
TSHIP.sh_LastAttackTime = P_GetAbsTime();
TSHIP.sh_Attacker = Attacker;
}
}
} |
|
Модифицируя эту функцию по своему усмотрению можно научить корабли скидывать мины на игрока, можно поменять логику захвата, опускать репу при атаке мирных кораблей гораздо сильнее, что на мой взгляд было бы логично.
И самое главное - поменять условия, при которых повреждается оборудование.
К примеру я бы сделал повреждение оборудования только если текущая ёмкость щита < 10%, а не всегда, что даёт дрону с AIRE уничтожать оборудование на корабле с 2х25МВт щитами.
Также было бы неплохо писать в лог, какое оборудование было уничтожено. В принципе повреждение оборудования штука интересная, только реализована уж больно топорно и нелогично.
PS: Сорри если комментарии к коду слишком надмозговые.
PS2: Обновил xt-obj-patching в начале темы.
Добавлен старт на шаттле, старт в фиксированном секторе (указываете в файлике самостоятельно), средние апгрейды NPC (ровно наполовину), оставить только СЕТУ на старте, количество денег на старте и самое главное - турбо двигатель для шаттла с тру-тряской кокпита.
В X2 это невозможно, т.к. из exe ампутирована функция-трясучка SA_SetHitRappelDelay. Наслаждаемся почти аутентичностью совместимость с сейвами присутствует. Использует две неиспользуемые переменные ga_ServerID и ga_ClientID.
Последний раз редактировалось: Non (04:03 17-04-2019), всего редактировалось 2 раз(а) |
|
|
KWON
409 EGP
    Рейтинг канала: 8(857) Репутация: -12 Сообщения: 171 Откуда: Україна. Чигирин. Зарегистрирован: 24.11.2014
 |
|
Non : |
Обновил xt-obj-patching в начале темы.
|
Клас! Спасибо. Будем потихоньку разбираться.
Всё таки выложу Ваш новый патч для ХТ.ехе в.2.2
в виде делфи-прожки.
(Честно признаюсь сам в игре не проверял, поскольку нужно переустановить весь виндовс, что бы все программы опять заработали нормально.)
Patch XT-2.2.7z |
Описание: |
Патч модератора Non для X-Tension.exe |
|
Имя файла: |
Patch XT-2.2.7z |
Размер файла: |
646.27 KB |
Скачано: |
555 раз(а) |
Последний раз редактировалось: KWON (20:18 17-04-2019), всего редактировалось 1 раз |
|
|
Non
802 EGP
       Рейтинг канала: 6(383) Репутация: 239 Сообщения: 801
Зарегистрирован: 27.06.2006
 |
|
Хорошие новости.
Велосипедисты из ES сами столкнулись с необходимостью добавлять новые переменные в своих патчах, поэтому в обже уже есть переменные, сменившие своё назначение.
К примеру:
Код: |
function TMENU.___NewVarInit()
{
TMENU.me_LastKeyR = SE_ArrayAlloc(32);
return(0);
}
function TMENU.___SetVar(arg1, arg2)
{
global.IntToArray(TMENU.me_LastKeyR)[arg1 + 1] = arg2;
return(0);
}
function TMENU.___GetVar(arg1)
{
return(global.IntToArray(TMENU.me_LastKeyR)[arg1 + 1]);
}
function TMENU.GetNewVarArray()
{
return(global.IntToArray(TMENU.me_LastKeyR));
} |
Что это значит? Можно запилить крутой функционал, совместимый с сохранёнками не пересобирая обж.
Ковыряю пока AttackedBy, повысил штрафы репутации за атаку расовых кораблей и думаю переработать алгоритм работы захвата.
Он должен учитывать боевой рейтинг и скорость падения щита. Тут то мне как раз и нужна была переменная класса. Чтобы сохранить для атакуемого корабля начальное значение щита, игровое время (функция запускается на каждое попадание по кораблю) и сравнить время и новое значение щита.
А раз можно использовать массив в переменной, в котором свободны слоты с 7 по 32, то при довольно солидной модификации алгоритма будет совместимо с сохранёнками.
Так то получается побитовая логика-то и не нужна. Можно хранить массив переменных в одной.
|
|
|
Non
802 EGP
       Рейтинг канала: 6(383) Репутация: 239 Сообщения: 801
Зарегистрирован: 27.06.2006
 |
|
Небольшое, но очень приятное обновление xt-obj-patching
Переназначение кнопок
Удалось наконец-то соорудить изящный хук для переопределения кнопок,
обрабатываемых в обже (те что не A Z Space Q W E T B ALT CTRL Стрелки)
Работает с сохранениями.
К примеру меня давно раздражало, что так неудобно игрокам-клавишникам
выравнивать скорость под цель. Теперь нажатием кнопки v курсор скорости
устанавливается на скорость цели.
Кнопка x сбрасывает скорость в 0. Тянуться к backspace неудобно.
Также можно и ракеты позапускать кнопками которые ближе и удобнее, но это уже на
ваше усмотрение.
Для поиграть кнопка ~ меняет скайбокс текущего сектора и выводит его
номер на экранчик в корабле, где пишется ID цели. Имейте ввиду, что изменение
запишется в сохранение.
Код: |
if(btn != 434) {
SA_DisplayStaticText(SE_SPrintf("%d", btn));
} |
Функция exe выше будет выводить на экранчик в корабле код нажатой
кнопки, или комбинации кнопок (SHIFT+V например), для простоты эксперимента и
назначения кнопок на интересующие действия. Почему-то не все комбинации кнопок и
просто кнопки выдают свой код. Так что в переназначении игрок слегка ограничен.
См. xc/TCLIENT.InputOverrides.c
Хранение массива на 100 элементов в переменной ga_ServerID
Теперь можно относительно удобно предотвращать повторный запуск своего кода там,
где он уже отработал. К примеру нулевой слот используется для турбо режима шаттла.
Работает с сохранениями.
Пользуйтесь global.SetVar(слот, что_записать) и global.GetVar(слот). Они вернут
0 при запросе через GetVar если массив не существует и тут же его создадут.
См. xc/ServerID-array.c
Упрощённая инициализация игры для тестирования своего кода (полигон)
Разобрался как игруха стартует и что запускает, обрезал лишнее, а именно:
- Создание карты из TGALAXY.BuildFromEditor
- Старт всех квестов
- Создание расы гонеров и запуск их логики, которая вешает игру если на карте
нету храма
Теперь создавать объекты для своего полигона нужно программно, но преимущество
перевешивает - ALT+Tab, поменял немного код, откомпилировал через patch.cmd,
развернул игруху, вышел SHIFT+Q, нажал новую игру, меньше чем за секунду уже
тестируешь новый код.
В первую очередь открываем patch.c и внимательно изучаем комментарии в нём и в
остальных вкладываемых файлах (#include)
PS: Кому не понятно сидеть и читать код с комментариями - скачайте нормальный
редактор с подсветкой синтаксиса, например Notepad++ и вникайте удобно
PS2: Специально для работы подсветки синтаксиса в различных редакторах
переименовал все *.xc файлы в *.c, а *.inc файлы в *.asm.
Т.к. возможно только мне не лень настроить подсветку синтаксиса для произвольных
расширений файлов.
|
|
|
Shaddie
556 EGP
      Рейтинг канала: 6(438) Репутация: 118 Сообщения: 261 Откуда: Томск Зарегистрирован: 09.09.2004
 |
|
Слегка допилил трансляцию asm кода в более читабельный вид.
Транслированы не все функции.
Ошибки точно есть.
В функции TGALAXY.BuildFromEditor обрезан массив по которому создается галактика:
loc2 = array(1,2,3,4,5,6,7,8,9,10)
code_xt_20240112.zip |
Описание: |
Код XT cpp версия 2024-01-12 |
|
Имя файла: |
code_xt_20240112.zip |
Размер файла: |
205.26 KB |
Скачано: |
62 раз(а) |
_________________ Быстро едешь, тихо понесут... |
|
|
glorsh66
50 EGP Репутация: 0 Сообщения: 48
Зарегистрирован: 29.10.2023
 |
|
Народ а как вы такие изыскания проводите просто интересно?
Через декомпиляцию или методом проб и ошибок?)
|
|
|
|
|
|
Канал X-Tension/X-BTF: «Раскопки обжа на предмет юзабельных вещей» |
|
К списку каналов | Наверх страницы |
Цитата не в тему: Качусь я по крыше, качусь, и молчу - чего же орать-то, еще ж не лечу! (сочинил Harley)
|
» Раскопки обжа на предмет юзабельных вещей | страница 5 |
|