ВНИМАНИЕ! Наша конференция посвящена космической тематике и компьютерным играм. Политические вопросы и происходящие в мире события в данный момент на нашем сайте не обсуждаются!
|
» Создание плагинов | страница 1 |
 |
Страница 1 из 1 |
|
|
|
Канал Freelancer »
МОДовый отсек: «Создание плагинов» |
|
|
Whiskas
137 EGP
  Рейтинг канала: 3(42) Репутация: 5 Сообщения: 139
Зарегистрирован: 28.04.2011
 |
|
Инфо:
1. Freelancer не DMA игра. Это значит, что значение денег или чего-либо, когда бы вы не запустили игру всегда будет по одному и тому же адресу в памяти. Повезло правда?
2. Плагины должны быть подхвачены игрой, для этого они прописываются в файле dacom.ini в секции [Libraries]. Сами плагины кидаются в папку EXE.
3. Из 2-ого следует, что в большинстве случаев не нужно искать handle игры(его окна, id и т.п.) как обычно делают некоторые виды хаков для других игр.
Cкрытый текст (кликните здесь для просмотра)
Данный элементарнейший плагин делался в Delphi. Примеров, ответов, вопросов на этот язык превышает на все остальные вместе взятые... в 6 раз! (c) Мегамозг  . Вот поэтому-то и на нём
Здесь фактически базовая заготовка. Этого пока достаточно для ознакомления с первой функцией, результат работы которой является запись 4 байт в память по заданному адресу.
В данном случае, плаг меняет скорость перемещения в трейдлэйнах с 2500 на 3440.Его исходник с комментариями, где только имеет смысл:
Cкрытый текст (кликните здесь для просмотра)
Код: |
library Project1;
uses
System.SysUtils,
System.Classes,
windows,
PsAPI,
tlhelp32;
var
WndHandle : THandle;
const //секция константных значений
AddressReload = $0639F3CC; //Это адрес в памяти где лежит скорость трейдлейнов. Если в artmoney, в реадкторе памяти перейти на этот адрес(в чистом фриле), то можно увидеть байты 00 40 1C 45 . Это float значение, на нормальный язык это 2500.
PatchReload : Array[0..3] of byte = ($00,$0A,$57,$45); //Это байты, которыми заменим оригинальные в памяти. 00 5A 57 45 (если перевести с float это 3440,625). Т.е. в игре скорость трейдлэйнов вместо 2500 станет грубо 3440
{$R *.res}
Function WriteIt(pAddress: Pointer; Bytes: Array of Byte): Boolean; //Функция записи. Просто функция и её код, мы будем обращатся к ней, чтобы пропачтить память, она знает что делать: записать там, где мы укажем, и самое главное что записать
var
OldProtect, DummyProtect: DWord;
begin
if VirtualProtect(pAddress, SizeOf(Bytes), PAGE_EXECUTE_READWRITE, @OldProtect) then
begin
Move(Bytes, pAddress^, Length(Bytes));
VirtualProtect(pAddress, SizeOf(Bytes), OldProtect, @DummyProtect);
Result := True
end
else
Result := False;
end;
procedure DllEntry(dwReason: DWORD); //Процедура загрузка библиотеки.
label again;
begin
case dwReason of //Эта варианты для нашей dll при загрузки. Что делать когда "прилепимся к игре", что делать когда "отлепимся от игры" и ещё два(мне неизвестных).
DLL_PROCESS_ATTACH: //В случае аттача к процессу
begin //начало кода наших действий
WriteIt(ptr(AddressReload),PatchReload); //Непосредственно пачтим. Мы вызываем функцию WriteIt, далее указатель на AddressReload, в который, в секции констант указан адрес, по которому пачтить. PatchReload - что именно записывать в память. В константах PatchReload равен Array[0..3] of byte = ($00,$0A,$57,$45), "пачка байтов" так сказать.
end; //завершение кода наших манипуляций
DLL_PROCESS_DETACH:
begin
end;
DLL_THREAD_ATTACH:
begin
end;
DLL_THREAD_DETACH: //В случае если игра закрывается
begin
FreeLibrary(WndHandle); //Выгрузить библиотеку из памяти. Если не будет этого кода, фрил-то вы закроете, он также будет висеть в процессах. Точнее сгусток игры и нашей инжектированной dll.
end;
end;
end;
begin
@DllProc := @DllEntry;
DllEntry(DLL_PROCESS_ATTACH);
end. |
|
Адрес, где находится скорость трейдлэйнов в памяти был взят из сорсов Адоксы. Я в этом не очень разбираюсь пока, но принципе, если ida осилил, то и артмани можно осилить.
|
Собственно говоря мое дело лишь предложить, оставить темку про запас, так, для общего развития. Изучение сам продолжу, интересно все-таки. Вообще тут есть кто на дельфине шарит? По dll...
На всякий случай: компилил в Delphi XE2. Размер, по сравнению с dll-ками Адоксы - Огромный! Это же делфи 340 Kb. Можно UPX-ом сжимать в принципе.
Project1.rar |
Описание: |
Tradelanne speed = 3440 (delphi plugin) |
|
Имя файла: |
Project1.rar |
Размер файла: |
116.54 KB |
Скачано: |
1057 раз(а) |
|
|
|
Endeavour
1015 EGP
       Рейтинг канала: 2(23) Репутация: 105 Сообщения: 7041 Откуда: guess Зарегистрирован: 26.05.2005
 |
|
dma/не dma - разделение для нубов, использующих артмани. Значения, со статической инициализацией (вроде тот термин) или подставленные прямо в коде (immediate values) равно как и сам код - доступны для легких хаков. С вещами из динамической памяти тоже есть что делать в более сложных плагинах.
Размер файла такой - потому что подцеплены стандартные делфовские SysClasses и Classes, делфи любит раздувать размер файла стандартными либами. Здесь они не нужны, можно их отцепить.
Лично для меня любые прямые операции с памятью и указателями гораздо легче пишутся в C синтаксисе.
Последний раз редактировалось: Endeavour (00:38 16-01-2012), всего редактировалось 1 раз |
|
|
Whiskas
137 EGP
  Рейтинг канала: 3(42) Репутация: 5 Сообщения: 139
Зарегистрирован: 28.04.2011
 |
|
thiscall : |
С вещами из динамической памяти тоже есть что делать в более сложных плагинах.
|
А такие участки динамической памяти есть у фрила? Думаю насчет всего этого придется гуглить...
thiscall : |
Лично для меня любые прямые операции с памятью и указателями гораздо легче пишутся в C синтаксисе.
|
Что ж ты не учишь нас?))
Я-то реально нуб, что в делфи(на 53.23% ) что в си. Тут важен сам процесс создания. Хочется ведь тоже самим уметь и понимать. Ни один си изначально не знаю, там синтаксис весьма сложноватым кажется.
зы
Удалил System.SysUtils и System.Classes, dll стала 30 Kb
|
|
|
Endeavour
1015 EGP
       Рейтинг канала: 2(23) Репутация: 105 Сообщения: 7041 Откуда: guess Зарегистрирован: 26.05.2005
 |
|
Whiskas T-Mech : |
Нужно чтобы не только процедура патчинга выполнилась бы, но и остальные какие-нибудь действия подобно как в нормальном приложении, а тут один раз выполнится при загрузке и конец Так уж трейнер легче творить
|
Создавать свой тред, либо, если нужна синхронизация с фрилом - хучить постоянно вызываемую main loop/simulation функцию, в сервер хуке в этой роли идет IServerImpl::Update.
Whiskas T-Mech : |
А такие участки динамической памяти есть у фрила?
|
Такие вещи есть везде, см. operator new.
Whiskas T-Mech : |
Ни один си изначально не знаю, там синтаксис весьма сложноватым кажется.
|
Он только кажется, на самом деле для работы с памятью удобнее, как синтаксис, так и язык.
Whiskas T-Mech : |
Что ж ты не учишь нас?))
|
Меня например никто целенаправленно не учил... Что-то спрашивал, что-то сам.
добавлено спустя 5 минут:
зы Не рекомендую учиться стилю программирования по коду Adoxa. Он может быть и способен сделать любой хак за неделю, но его код ужасен даже для C (без плюсов).
Последний раз редактировалось: Endeavour (07:07 16-01-2012), всего редактировалось 2 раз(а) |
|
|
Whiskas
137 EGP
  Рейтинг канала: 3(42) Репутация: 5 Сообщения: 139
Зарегистрирован: 28.04.2011
 |
|
Насчет IServerImpl::Update это выше моего понимания, а тред вот получилось создать все-таки.
Теперь каждые 2 секунды пока летишь по трейдлэйнам скорость меняется, то 1000 то 100, то 1000 то 100 и т.д. Шикарно!
Cкрытый текст (кликните здесь для просмотра)
Код: |
......
const
Addr_Trl_Speed = $0639F3CC;
PatchReload : Array[0..3] of byte = ($00,$00,$7A,$44); // = 1000
PatchReload2 : Array[0..3] of byte = ($00,$00,$C8,$42); // = 100
......
......
procedure set_drunk_speed; //Процедура "пьяная скорость"
begin
while 1= 1 do //До тех пор пока 1 равен 1-му(гениально! XD) делать следующее:
begin
WriteIt(ptr(Addr_Trl_Speed),PatchReload2); //Записать скорость 100
sleep(2000); //Ждать 2 секунды
WriteIt(ptr(Addr_Trl_Speed),PatchReload); //Записать скорость 1000
sleep(2000); //Ждать 2 секунды
end;
end;
procedure NewThread; //Создания потока
var
ThreadID: Cardinal;
begin
CreateThread(nil, 0, @set_drunk_speed, nil, 0, ThreadID); //Какую процедуру запихнуть в этот поток: set_drunk_speed.
end;
procedure DllEntry(dwReason: DWORD);
begin
case dwReason of
DLL_PROCESS_ATTACH: //Приатачивание плагина
begin
NewThread; //Выполнить процедуру NewThread.
end;
DLL_PROCESS_DETACH:
begin
FreeLibrary(WndHandle);
end;
DLL_THREAD_ATTACH:
begin
end;
DLL_THREAD_DETACH:
begin
FreeLibrary(WndHandle);
end;
end;
end;
begin
@DllProc := @DllEntry;
DllEntry(DLL_PROCESS_ATTACH);
end. |
|
_____________
По кусочкам из инета почти сделал чтение памяти, выходной типа integer, правда, задом наперед... Буду копать под зависимость одного значения от другого. Мол, денег 20 лимонов, лети 6890 m/s, денег нет, лети 100 m/s
|
|
|
Jeider
570 EGP
    Рейтинг канала: 5(198) Репутация: 49 Сообщения: 2804 Откуда: Пенза Зарегистрирован: 17.08.2009
 |
|
Что-то у меня не получилось у себя на Делфи запилить подобный текст... ну ладно, может он так на 7ом тупит. Завтра поновее поставлю.
По вашему - реально ли фиксировать текущее состояние трюма игрока? Есть небольшая идейка для создания плагина.
|
|
|
Whiskas
137 EGP
  Рейтинг канала: 3(42) Репутация: 5 Сообщения: 139
Зарегистрирован: 28.04.2011
 |
|
Jeider : |
Что-то у меня не получилось у себя на Делфи запилить подобный текст... ну ладно, может он так на 7ом тупит. Завтра поновее поставлю.
|
На всякий случай все же кину. В XE2:
File -> New -> Other... -> Dynamic-Link Library
Появится вкладка Unit1, весь текст в нем заменяем этим(переменчивая скорость tradelanes):
Cкрытый текст (кликните здесь для просмотра)
Код: |
library Project1;
{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
ShareMem,
windows,
PsAPI,
tlhelp32;
var
WndHandle : THandle;
const
Addr_Trl_Speed = $0639F3CC;
PatchReload : Array[0..3] of byte = ($00,$00,$7A,$44);
PatchReload2 : Array[0..3] of byte = ($00,$00,$C8,$42);
{$R *.res}
Function WriteIt(pAddress: Pointer; Bytes: Array of Byte): Boolean;
var
OldProtect, DummyProtect: DWord;
begin
if VirtualProtect(pAddress, SizeOf(Bytes), PAGE_EXECUTE_READWRITE, @OldProtect) then
begin
Move(Bytes, pAddress^, Length(Bytes));
VirtualProtect(pAddress, SizeOf(Bytes), OldProtect, @DummyProtect);
Result := True
end
else
Result := False;
end;
procedure set_drunk_speed;
begin
while 1= 1 do
begin
WriteIt(ptr(Addr_Trl_Speed),PatchReload2);
sleep(2000);
WriteIt(ptr(Addr_Trl_Speed),PatchReload);
sleep(2000);
end;
end;
procedure NewThread;
var
ThreadID: Cardinal;
begin
CreateThread(nil, 0, @set_drunk_speed, nil, 0, ThreadID);
end;
procedure DllEntry(dwReason: DWORD);
begin
case dwReason of
DLL_PROCESS_ATTACH:
begin
NewThread;
end;
DLL_PROCESS_DETACH:
begin
FreeLibrary(WndHandle);
end;
DLL_THREAD_ATTACH:
begin
end;
DLL_THREAD_DETACH:
begin
FreeLibrary(WndHandle);
end;
end;
end;
begin
@DllProc := @DllEntry;
DllEntry(DLL_PROCESS_ATTACH);
end. |
|
Правда при закрытии игры будет репорт об ошибки. Тут с FreeLibrary я пока не очень дружу.
Jeider : |
По вашему - реально ли фиксировать текущее состояние трюма игрока? Есть небольшая идейка для создания плагина.
|
Всмысле считывать сколько свободного места? Лично самому как бы найти такие вещи в памяти ума не приложу. Отсеивание через cheatengine или артмани, видимо, + сноровка. Если его найти, то факт фиксации на лицо))
____________
Наивный нубский вопрос по потокам: можно хоть 2000 потоков сделать или это от кол-ва процов зависит? Тут тонкая грань какая-то в понятиях.
|
|
|
Endeavour
1015 EGP
       Рейтинг канала: 2(23) Репутация: 105 Сообщения: 7041 Откуда: guess Зарегистрирован: 26.05.2005
 |
|
Whiskas T-Mech : |
Правда при закрытии игры будет репорт об ошибки. Тут с FreeLibrary я пока не очень дружу.
|
Нельзя вызывать FreeLibrary() из освобождаемой длл, потому что управление из функции вернется по некорректному адресу из уже освобожденной длл.
Можно создавать новый тред и использовать FreeLibraryAndExitThread(), эта функция не возвращает, но при этом может получиться race condition, когда в другом потоке еще будет выполняться код освобожденной длл. Нужна синхронизация.
Но вообще, это все здесь не нужно, потому что сразу после DLL_PROCESS_DETACH длл будет выгружена системой.
THREAD_ATTACH/DETACH же здесь вообще не интересны, а уж выгружать длл по THREAD_DETACH - вообще бессмысленно.
Желательно просто отказаться от этих нотификаций, первым делом вызывая DisableThreadLibraryCalls() и не хэндля их в последующем.
Whiskas T-Mech : |
Наивный нубский вопрос по потокам: можно хоть 2000 потоков сделать или это от кол-ва процов зависит? Тут тонкая грань какая-то в понятиях.
|
Нужно понимать, что если несколько потоков будут одновременно читать+писать или писать+писать в одну область памяти без синхронизации - будет огромное количество глюков, которые просто выжрут мозг своей непонятностью. Поэтому твой код выше - опасен. Возможно именно там ничего не случится, но это плохой легкий способ. Если действительно нужно так переписывать значения: их нужно переписывать либо (с большой вероятностью) из основного потока симуляции, либо синхронизированно с ним.
Jeider : |
По вашему - реально ли фиксировать текущее состояние трюма игрока? Есть небольшая идейка для создания плагина.
|
Реально, но потребует некоторого реверсинга.
И не на делфе, потому что читать STL list на делфе, бррр... /о\
добавлено спустя 3 минуты:
Whiskas T-Mech : |
Наивный нубский вопрос по потокам: можно хоть 2000 потоков сделать или это от кол-ва процов зависит?
|
По самому количеству:
Цитата: |
The number of threads a process can create is limited by the available virtual memory. By default, every thread has one megabyte of stack space. Therefore, you can create at most 2,048 threads. If you reduce the default stack size, you can create more threads.
|
Последний раз редактировалось: Endeavour (23:47 16-01-2012), всего редактировалось 1 раз |
|
|
Whiskas
137 EGP
  Рейтинг канала: 3(42) Репутация: 5 Сообщения: 139
Зарегистрирован: 28.04.2011
 |
|
Так, похоже все завязано на синхронизации. Я сначала думал это холодный-математический рассчет в проектирвоании потоков, погуглил немного, так там и функции какие-то есть
Сосбственно теперь стоит о ней задуматься. У меня постоянно, после того, как изменю пару раз значение кредитов(от которого по формуле меняется скорость трейдлэйнов) при закрытии игры репорт об ошибке выходит. Тестил на чистом фриле с установленным kplol.
Вообще таки написал этот плагин, есть зависимость.
Больше денег - больше скорость (кликните здесь для просмотра)
Код: |
library Project1;
uses
ShareMem,
System.SysUtils,
windows,
PsAPI,
tlhelp32;
var
WndHandle : THandle;
const
Addr_Trl_Speed = $0639F3CC; //Адрес скорости tradelanes
Addr_Money = $00673364; //Адрес кол-ва денег( визуальное представление)
{$R *.res}
///////////////////////////Functions section//////////////////////////////////////
function ByteToStr(bytes: array of byte): string; //Преобразование array of byte в строку
const
BytesHex: array[0..15] of char =
('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
var
i, len: integer;
begin
len := Length(bytes);
SetLength(Result, len * 2);
for i := 0 to len - 1 do begin
Result[i * 2 + 1] := BytesHex[bytes[i] shr 4];
Result[i * 2 + 2] := BytesHex[bytes[i] and $0F];
end;
end;
function ReadAdress(pAddress:Pointer; size:dword):string; //Чтение 4-х байт в памяти
var
HP:THandle;
wread:SIZE_T;
bb:array [0..3]of byte;
PID:cardinal;
begin
HP:=FindWindow('Freelancer',nil);
GetWindowThreadProcessId(HP, @PID);
HP := OpenProcess(PROCESS_VM_READ,False,PID);
ReadProcessMemory(HP,pAddress,@bb,4,wread);
Result:=bytetostr(bb);
end;
function ReverseFloatBytes(s:string):string; //Реверсирование результата прочитанных 4 байтов,
begin //а то в памяти все задом наперед
Result:=Result+Copy(s,7,2)+Copy(s,5,2)+Copy(s,3,2)+Copy(s,1,2);
end;
Function WriteIt(pAddress: Pointer; Bytes: Array of Byte): Boolean;
var
OldProtect, DummyProtect: DWord;
begin
if VirtualProtect(pAddress, SizeOf(Bytes), PAGE_EXECUTE_READWRITE, @OldProtect) then
begin
Move(Bytes, pAddress^, Length(Bytes));
VirtualProtect(pAddress, SizeOf(Bytes), OldProtect, @DummyProtect);
Result := True
end
else
Result := False;
end;
function ReadIt(addr:pointer):integer;
begin
Result:=StrToInt('$'+ ReverseFloatBytes(ReadAdress(addr,4)));
end;
function GetNewSpeed(addr:pointer):single; //Вычисление новой скорости на основе кол-ва кредитов
var // 2500 x (Cr/1000000)% + 2500;
j:single;
begin
j:=ReadIt(ptr(Addr_Money)); //Ложим в j кредиты
Result:=Trunc((j/100000000)*2500+2500); //Проводим операции и округляем результат до целых
end;
///////////////////////////Procedures section//////////////////////////////////////
procedure New_Speed; //Новая скорость, больше денег было насчету больше скорость
var
new_speed:array [0..3] of byte;
float_value:single;
begin
while 1=1 do
begin
float_value:=GetNewSpeed(ptr(addr_money)); //Вычисляем новую скорость
Move(float_value, new_speed[0], 4); //Превращаем в байты
WriteIt(ptr(Addr_Trl_Speed),new_speed); //Записываем
end;
end;
procedure Thread_NewSpeed; //Поток для процедуры New_Speed
var
ThreadID: Cardinal;
begin
BeginThread(nil, 0, @New_Speed, nil, 0, ThreadID);
end;
procedure DllEntry(dwReason: DWORD);
begin
case dwReason of
DLL_PROCESS_ATTACH:
begin
Thread_NewSpeed;
end;
DLL_PROCESS_DETACH:
begin
FreeLibrary(WndHandle);
end;
DLL_THREAD_ATTACH:
begin
end;
DLL_THREAD_DETACH:
begin
end;
end;
end;
begin
@DllProc := @DllEntry;
DllEntry(DLL_PROCESS_ATTACH);
end. |
|
Теперь в голову пришла мысль добавить одновременно вариацию скорости, и ведь реально мозг сломаешь: постоянно читается кол-во денег и на основе их кол-ва пишется новая скорость, и как пропихнуть же функцию, которая ещё и одновременно варьировать будет эту скорость, если она постоянно сбрасывается из-за работы предыдущей? Это реально вообще?
А если не CreateThread использовать, а BeginThread? Хотя по-моему разницы нет.
thiscall : |
Нужно понимать, что если несколько потоков будут одновременно читать+писать или писать+писать в одну область памяти без синхронизации - будет огромное количество глюков, которые просто выжрут мозг своей непонятностью. Поэтому твой код выше - опасен. Возможно именно там ничего не случится, но это плохой легкий способ. Если действительно нужно так переписывать значения: их нужно переписывать либо (с большой вероятностью) из основного потока симуляции, либо синхронизированно с ним.
|
Да я просто не умею по-другому)
---UPD---
Придумал по-моему, можно сохранять кол-во денег и вывести в отдельный поток проверку на "изменилось ли", если да записываем скорость и передаем управление "варьирующей скорости".
Последний раз редактировалось: Whiskas (23:38 17-01-2012), всего редактировалось 3 раз(а) |
|
|
HeIIoween
130 EGP
  Рейтинг канала: 3(25) Репутация: 12 Сообщения: 69
Зарегистрирован: 15.10.2012
 |
|
А как насчет плагинов на стороне сервера? И пробовали ли вы компилить сие под Lazarus - опенсурс дельфи компатибле енвиронмент?
|
|
|
Whiskas
137 EGP
  Рейтинг канала: 3(42) Репутация: 5 Сообщения: 139
Зарегистрирован: 28.04.2011
 |
|
Лично для меня сервера не судьба, я дома сингл гоняю по старинке.
Про lazarus ничего не знаю, да и вообще, все эти плагины на делфи не дело, как-то выходит, что перегоняешь код типа на NET-обертку т.к. си не знаю, увы.
Нашел тут пару глобал переменных в памяти:
[673354] - текущая система(ввиде хэша конечно)
[66873C] - текущая база, на которой находится игрок
[658A838] - кол-во систем
А в это время на родном языке просто вызывают напрямую процедуры и имеют какие-хочешь данные.
Хотя была мысль экспортирвать через declspec из console пару процедур или хотя бы конкретно переменные, а дельфин бы подхватил, и сбил бы все регистры.... Я так функции crc и хэша перекидывал на делфи, но тут уже потоки, неверное нельзя.
Последний раз редактировалось: Whiskas (13:35 21-12-2012), всего редактировалось 2 раз(а) |
|
|
HeIIoween
130 EGP
  Рейтинг канала: 3(25) Репутация: 12 Сообщения: 69
Зарегистрирован: 15.10.2012
 |
|
Многие функции используются на стороне сервера, разве что кроме полноценных сингловых скриптов. Например Адохин Dock Key прекрасно работает и так и там. Кстати твой tradelanespeed будет работать если помимо клиента, прописать его на сервере в dacomsrv.ini
Последний раз редактировалось: HeIIoween (23:03 22-12-2012), всего редактировалось 1 раз |
|
|
Whiskas
137 EGP
  Рейтинг канала: 3(42) Репутация: 5 Сообщения: 139
Зарегистрирован: 28.04.2011
 |
|
Вообщем, на старпорте я уже выложил :ссылка
И тут оставлю, правда в этом архиве ещё все исходники к core.dll, да так, для тех кто на делфи кодит и вообщем для истории.
Полагаю теперь Адокса или кто-то там другой возьмут это как референс и сделают более насыщенную версию. К тому же именно Адокса аж уже 3 года назад говорил что в будущем возможно сделает смену бэкграундов как дополнение к territory(где-то наткнулся на лэнсерс). Кстати, плагины совместимы технически, но очевидно юзать их одновременно пока нет смысла)
С Новым Годом!
Последний раз редактировалось: Whiskas (14:20 04-01-2014), всего редактировалось 2 раз(а) |
|
|
Jeider
570 EGP
    Рейтинг канала: 5(198) Репутация: 49 Сообщения: 2804 Откуда: Пенза Зарегистрирован: 17.08.2009
 |
|
Классная штука, только я думаю проще от всех текстов названий совсем избавиться. То есть оставить базовое. Честно сказать... по мне эта штука может понадобиться только для очень плохих модостроителей. Нет, я не про неумелых, я про козлов воров, которые любят тырить целые моды и впихивать к себе как "одну из реальностей". То есть сборные солянки...
добавлено спустя 36 секунд:
И вообще - лучше бы темку новую создал для этого плагина. Чтоб виднее было )
Последний раз редактировалось: Jeider (12:06 04-01-2014), всего редактировалось 1 раз |
|
|
Whiskas
137 EGP
  Рейтинг канала: 3(42) Репутация: 5 Сообщения: 139
Зарегистрирован: 28.04.2011
 |
|
Да как-то для темы он слишком прост, сделать пару секций и разбить по ним системы) Делается на ать-два, отсюда же врядли сборщики солянок уж больно рады ибо работа как была так и осталась в перелопачивании тонны инишек, а сделать мультикарту - самый-самый последний штрих, косметический по факту. Да и вообще я пока не видел ни одной солянки на паблике. Везде авторские моды.
В посте выше перезалил архив, убрал рандомное исчезание кнопки вселенной, хотя там нужна чуть более корректная синхронизация флагов.По надписям лично я ничего нового делать не буду, это да, во 1-ых сложно, во 2-ых и 4 стандартных места существенно отнимают на карте)))
|
|
|
Jeider
570 EGP
    Рейтинг канала: 5(198) Репутация: 49 Сообщения: 2804 Откуда: Пенза Зарегистрирован: 17.08.2009
 |
|
Значит ты про Rebirth не слышал? Плохо. Там еще та сборная солянка)
|
|
|
Whiskas
137 EGP
  Рейтинг канала: 3(42) Репутация: 5 Сообщения: 139
Зарегистрирован: 28.04.2011
 |
|
Не прошло и трех лет. Без потоков и таймеров.
В игре установите вторичный контрол для Tractor Beam(All Items) сочетание клавиш с Ctrl (Ctrl+C, например). В EQUIPMENT\goods.ini добавьте на нужные корабли addon = cloak_fighter, HpCloak01, 1.
Сейчас гугл по запросу cloak выдает тонну не работающих плагинов в сингле, я почти готов застрелиться, если у вас и этот не сработает. Он элементарен.
Invisibility.zip |
Описание: |
|
Имя файла: |
Invisibility.zip |
Размер файла: |
13.19 KB |
Скачано: |
674 раз(а) |
Последний раз редактировалось: Whiskas (17:08 14-03-2014), всего редактировалось 2 раз(а) |
|
|
|
|
|
Канал Freelancer ->
МОДовый отсек: «Создание плагинов» |
|
К списку каналов | Наверх страницы |
Цитата не в тему: Заранее благдарен за ваш цензурный отзыв о моих умственных дефектах (Bert RIVEN)
|
» Создание плагинов | страница 1 |
|