Разработка и ромхакинг > Ромхакинг и программирование
[SMD] хакинг Dune: The Battle for Arrakis
<< < (96/447) > >>
serj320:

--- Цитата: topos84 от 14 Август 2011, 00:54:14 ---А остальные идеи - это по поводу? Новые юниты заместо старых? Ну это наверно лишь в отношении изменения характеристик дальности и урона стрельбы (плюс, может быть, новые спрайты заместо старых)? А скорость перезарядки можно менять?

--- Конец цитаты ---

Дальность, урон, скорость перезарядки вроде в DuneUnitEditor менять можно, а новых спрайтов валом




--- Цитата: Segaman от 11 Август 2011, 10:52:05 ---давайт еставим титульник как есть.
нинадо его переводить. :)

--- Конец цитаты ---

пока норм не появится  :)

P.S.
Такими темпами хак выйдет...
                                         хз когда он выйдет :)
Ti_:

--- Цитата: topos84 от 14 Август 2011, 00:54:14 ---Ну про идеи, собственно говоря, говорить наверно пока рано, если код - темный лес.

--- Конец цитаты ---
Не так понял, вообще-то сейчас уже изученного достаточно чтобы делать очень много каких наворотов (получше чем в dunehackv7); а начинать не хочется именного из-за того что разобрано не всё (хотя бы больше половины надо).
Lipetsk:
Итак, все ресурсы, включая спрайты юнитов, извлечены из рома. Графика в основном сжатая.
Чтобы её изменять и вставлять в ром нужен нормальный запаковщик.
Анпакер Марата сжимает не все архивы.
Нужно сделать новый желательно с поддержкой массового анпака.
Покопавшись на форуме "Шедевра", нашёл исходники упаковки/распаковки:

--- Цитата ---В туториалке используется дважды упакованная карта тайлов. Сначала используется "свой" алгоритм, а потом общий.
После двух распаковок у тебя должен получиться набор "экранов".
--- Конец цитаты ---

--- Цитата ---Распаковка "обычная".
--- Конец цитаты ---

--- Код: ---   .386
   .model   flat

public   unpack
public   mod_name

   .data
modstring   db   "Dune: The Battle for Arrakis",0

   .data?
out_buf      dd   ?
in_buf      dd   ?
opt      dd   ?
read_len   dd   ?

   .code
_start@12:
   mov   al,1
   ret   12

;int unpack(char* pIn, char* pOut, int option, int* rLen);
unpack      proc
   pop   eax
   pop   in_buf
   pop   out_buf
   pop   opt
   pop   read_len
   push   eax
   push   ebx
   push   ebp
   push   esi
   push   edi
   mov   ebx,in_buf
   mov   edi,out_buf

main_loop:
   xor   ecx,ecx
   xor   edx,edx

   mov   cl,byte ptr [ebx]
   inc   ebx
   cmp   cl,0
   jns   cl_positive

   test   cl,40h
   jz   sixth_bit_clear

   cmp   cl,-2
   je   cl_eq_FE

   cmp   cl,-1
   je   cl_eq_FF

   and   cl,3Fh
   mov   dx,word ptr [ebx]
   add   ebx,2

   add   cx,3

   mov   esi,out_buf
   add   esi,edx
   jmp   loc_0_C96

cl_eq_FF:
   mov   cx,word ptr [ebx]
   mov   dx,word ptr [ebx+2]
   add   ebx,4
   mov   esi,out_buf
   add   esi,edx
   jmp   loc_0_C96

cl_positive:
   mov   dh,cl
   mov   dl,byte ptr [ebx]
   and   dx,0FFFh
   inc   ebx

   shr   cx,4
   add   cx,3

   mov   esi,edi
   sub   esi,edx

loc_0_C96:
   rep   movsb
   jmp   main_loop

sixth_bit_clear:
   cmp   cl,80h
   je   exit_sub

   and   cl,3Fh
   mov   esi,ebx
   add   ebx,ecx
   jmp   loc_0_C96

cl_eq_FE:
   mov   cx,word ptr [ebx]
   mov   al,byte ptr [ebx+2]
   add   ebx,3

   rep   stosb
   jmp   main_loop

exit_sub:

   sub   ebx,in_buf
   mov   ebp,read_len
   mov   [ebp],ebx

   mov   eax,edi
   sub   eax,out_buf
   pop   edi
   pop   esi
   pop   ebp
   pop   ebx
   ret
unpack      endp

mod_name   proc
   mov   eax,offset modstring
   ret
mod_name   endp

end   _start@12
--- Конец кода ---

--- Цитата ---Распаковка для туториала
--- Конец цитаты ---

--- Код: ---   .386
   .model   flat

public   unpack
public   mod_name

   .data
modstring   db   "Dune Tutorial Text",0

   .data?
out_buf      dd   ?
in_buf      dd   ?
opt      dd   ?
read_len   dd   ?

out_buf2   dd   ?
in_buf2      dd   ?
opt2      dd   ?
read_len2   dd   ?

buf_temp   dd   20000h dup(?)

   .code
_start@12:
   mov   al,1
   ret   12

;int unpack(char* pIn, char* pOut, int option, int* rLen);
unpack      proc
   pop   eax
   pop   in_buf
   pop   out_buf
   pop   opt
   pop   read_len
   push   eax
   push   ebx
   push   ebp
   push   esi
   push   edi

;---------------------------------------
   push   read_len
   push   0
   push   offset buf_temp
   push   in_buf
   call   preprocess
;---------------------------------------

   mov   esi,offset buf_temp
   mov   edi,out_buf

   xor   eax,eax
   lodsw

begin:
   cmp   ax,-1
   jz   exit
   xchg   ah,al
   mov   bx,ax

mmain_loop:
   xor   ecx,ecx
   mov   cl,[esi]
   inc   esi
   cmp   cl,80h
   jz   cl_eq_80
   jns   cl_gt_80
   sub   bx,2
   lodsw
   rep   stosw
   jmp   next_screen

cl_gt_80:
   and   cl,7Fh
   sub   bx,cx
   sub   bx,cx
   rep   movsw
   jmp   next_screen

cl_eq_80:
   xor   eax,eax
   lodsb
   shl   ax,1
   mov   cx,ax
   push   esi
   mov   esi,edi
   sub   esi,8C0h
   rep   movsb
   pop   esi
   dec   bx

next_screen:
   dec   bx
   jnz   mmain_loop

   lodsw
   cmp   ax,-1
   jnz   begin

exit:

   mov   eax,edi
   sub   eax,out_buf
   pop   edi
   pop   esi
   pop   ebp
   pop   ebx
   ret
unpack      endp

;int preprocess(char* pIn, char* pOut, int option, int* rLen);
preprocess   proc
   pop   eax
   pop   in_buf2
   pop   out_buf2
   pop   opt2
   pop   read_len2
   push   eax
   push   ebx
   push   ebp
   push   esi
   push   edi
   mov   ebx,in_buf2
   mov   edi,out_buf2

main_loop:
   xor   ecx,ecx
   xor   edx,edx

   mov   cl,byte ptr [ebx]
   inc   ebx
   cmp   cl,0
   jns   cl_positive

   test   cl,40h
   jz   sixth_bit_clear

   cmp   cl,-2
   je   cl_eq_FE

   cmp   cl,-1
   je   cl_eq_FF

   and   cl,3Fh
   mov   dx,word ptr [ebx]

   add   ebx,2
   add   cx,3

   mov   esi,out_buf2
   add   esi,edx
   jmp   loc_0_C96

cl_eq_FF:
   mov   cx,word ptr [ebx]
   mov   dx,word ptr [ebx+2]
   add   ebx,4
   mov   esi,out_buf2
   add   esi,edx
   jmp   loc_0_C96

cl_positive:
   mov   dh,cl
   mov   dl,byte ptr [ebx]
   and   dx,0FFFh
   inc   ebx

   shr   cx,4
   add   cx,3

   mov   esi,edi
   sub   esi,edx

loc_0_C96:
   rep   movsb
   jmp   main_loop

sixth_bit_clear:
   cmp   cl,80h
   je   exit_sub

   and   cl,3Fh
   mov   esi,ebx
   add   ebx,ecx
   jmp   loc_0_C96

cl_eq_FE:
   mov   cx,word ptr [ebx]
   mov   al,byte ptr [ebx+2]
   add   ebx,3

   rep   stosb
   jmp   main_loop

exit_sub:

   sub   ebx,in_buf
   mov   ebp,read_len2
   mov   [ebp],ebx

   mov   eax,edi
   sub   eax,out_buf2
   pop   edi
   pop   esi
   pop   ebp
   pop   ebx
   ret
preprocess   endp

mod_name   proc
   mov   eax,offset modstring
   ret
mod_name   endp

end   _start@12

--- Конец кода ---

--- Цитата ---А это чисто посмеяцца. Упаковка "обычная".
--- Конец цитаты ---

--- Код: ---//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop
//---------------------------------------------------------------------------
char nun[0x3F];
int obytes;
int out;
//---------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE, DWORD, LPVOID)
{
   return true;
}
//---------------------------------------------------------------------------
char* __stdcall __export mod_name()
{
   return "Dune: The Battle for Arrakis";
}
//---------------------------------------------------------------------------
void Flush(char* pO)
{
   if(!obytes) return;
   pO[out] = obytes | 0x80;
   out++;
   for(int j = 0; j < obytes; j++)
      pO[out + j] = nun[j];
   out += obytes;
   obytes = 0;
}
//---------------------------------------------------------------------------
int __stdcall __export pack(char* pIn, char* pOut, int option, int* rLen)
{
   int in = 0;
   int n;
   int n2;
   int maxN;
   int maxN2;
   int maxIn;
   int in2;
   obytes = 0;
   out = 0;
   while(in < option)
   {
      maxN = 0;
      maxN2 = 0;
      maxIn = 0;
      for(in2 = 0; in2 < in; in2++)
      {
         for(n = 0; pIn[in2 + n] == pIn[in + n] && in + n < option; n++);
         if(in - in2 < 0x1000 && n < 0xB) n2 = n - 2;
         else if(n < 0x43) n2 = n - 3;
         else n2 = n - 5;
         if(n2 > maxN2) { maxN2 = n2; maxN = n; maxIn = in2; }
      }
      for(n = 1; pIn[in + n - 1] == pIn[in + n] && in + n - 1 < option; n++);
      n2 = n - 4;
      if(n2 > maxN2) { maxN2 = n2; maxN = n; maxIn = in; }

      if(maxN2 >= 0 && maxN > 2)
      {
         if(in == maxIn)
         {
            Flush(pOut);
            pOut[out] = 0xFE;
            *(WORD*)(pOut + out + 1) = maxN;
            pOut[out + 3] = pIn[in];
            out += 4;
            in += maxN;
         }
         else if(in - maxIn < 0x1000 && maxN < 0xB)
         {
            Flush(pOut);
            pOut[out] = (maxN - 3) << 4 | (in - maxIn) >> 8;
            pOut[out + 1] = (BYTE)(in - maxIn);
            out += 2;
            in += maxN;
         }
         else if(maxN < 0x43)
         {
            Flush(pOut);
            pOut[out] = 0xC0 | (maxN - 3);
            *(WORD*)(pOut + out + 1) = maxIn;
            out += 3;
            in += maxN;
         }
         else
         {
            Flush(pOut);
            pOut[out] = 0xFF;
            *(WORD*)(pOut + out + 1) = maxN;
            *(WORD*)(pOut + out + 3) = maxIn;
            out += 5;
            in += maxN;
         }
      }
      else
      {
         nun[obytes] = pIn[in];
         obytes++;
         if(obytes == 0x3F) Flush(pOut);
         in++;
      }
   }
   Flush(pOut);
   pOut[out] = 0x80;
   out++;
   *rLen = option;
   return out;
}
//---------------------------------------------------------------------------

--- Конец кода ---

--- Цитата ---Упаковка для туториала. Файл первый.
--- Конец цитаты ---

--- Код: ---//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop
USEUNIT("p_dttext2.cpp"); // Тут должно быть имя второго файла
//---------------------------------------------------------------------------
int i;
int n;
int n2;
int in;
int out;
int size;
WORD* locIn;
char* locOut;
WORD nun[0x7F];
int owords;
int final(char* pIn, char* pOut, int option, int* rLen);
//---------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE, DWORD, LPVOID)
{
   return true;
}
//---------------------------------------------------------------------------
char* __stdcall __export mod_name()
{
   return "Dune Tutorial Text";
}
//---------------------------------------------------------------------------
void Flush()
{
   if(!owords) return;
   locOut[out] = owords | 0x80;
   out++;
   for(int j = 0; j < owords; j++)
      *(WORD*)(locOut + out + j * 2) = nun[j];
   out += owords * 2;
   owords = 0;
}
//---------------------------------------------------------------------------
int __stdcall __export pack(char* pIn, char* pOut, int option, int* rLen)
{
   out = 0;
   owords = 0;
   locIn = (WORD*)pIn;
   locOut = new char[0x10000];
   for(i = 0; i < option / 0x8C0; i++)
   {
      size = out;
      out += 2;
      in = 0;
      while(in < 0x460)
      {
         n2 = 0;
         for(n = 1; (locIn[in + n - 1] == locIn[in + n]) && ((in + n) < 0x460); n++);
         if(i) for(n2 = 0; locIn[in + n2] == locIn[in + n2 - 0x460] && in + n2 < 0x460; n2++);
         if(n > 1 || n2 > 1)
         {
            if(n > 0x7F) n = 0x7F;
            if(n2 > 0xFF) n2 = 0xFF;
            if(n > n2)
            {
               Flush();
               locOut[out] = n;
               *(WORD*)(locOut + out + 1) = locIn[in];
               out += 3;
               in += n;
            }
            else
            {
               Flush();
               locOut[out] = 0x80;
               locOut[out + 1] = n2;
               out += 2;
               in += n2;
            }
         }
         else
         {
            nun[owords] = locIn[in];
            owords++;
            if(owords == 0x7F) Flush();
            in++;
         }
      }
      Flush();
      locIn += 0x460;
      *(WORD*)(locOut + size) = (WORD)(out - size - 2) << 8 | (WORD)(out - size - 2) >> 8;
   }
   *(WORD*)(locOut + out) = -1;
   out += 2;
   out = final(locOut, pOut, out, rLen);
   *rLen = option;
   delete[] locOut;
   return out;
}
//---------------------------------------------------------------------------

--- Конец кода ---

--- Цитата ---Файл второй (у меня назывался p_dttext2.cpp).
--- Конец цитаты ---

--- Код: ---//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop
//---------------------------------------------------------------------------
char nun2[0x3F];
int obytes;
int out2;
//---------------------------------------------------------------------------
void Flush(char* pO)
{
   if(!obytes) return;
   pO[out2] = obytes | 0x80;
   out2++;
   for(int j = 0; j < obytes; j++)
      pO[out2 + j] = nun2[j];
   out2 += obytes;
   obytes = 0;
}
//---------------------------------------------------------------------------
int final(char* pIn, char* pOut, int option, int* rLen)
{
   int in = 0;
   int n;
   int n2;
   int maxN;
   int maxN2;
   int maxIn;
   int in2;
   obytes = 0;
   out2 = 0;
   while(in < option)
   {
      maxN = 0;
      maxN2 = 0;
      maxIn = 0;
      for(in2 = 0; in2 < in; in2++)
      {
         for(n = 0; pIn[in2 + n] == pIn[in + n] && in + n < option; n++);
         if(in - in2 < 0x1000 && n < 0xB) n2 = n - 2;
         else if(n < 0x43) n2 = n - 3;
         else n2 = n - 5;
         if(n2 > maxN2) { maxN2 = n2; maxN = n; maxIn = in2; }
      }
      for(n = 1; pIn[in + n - 1] == pIn[in + n] && in + n - 1 < option; n++);
      n2 = n - 4;
      if(n2 > maxN2) { maxN2 = n2; maxN = n; maxIn = in; }

      if(maxN2 >= 0 && maxN > 2)
      {
         if(in == maxIn)
         {
            Flush(pOut);
            pOut[out2] = 0xFE;
            *(WORD*)(pOut + out2 + 1) = maxN;
            pOut[out2 + 3] = pIn[in];
            out2 += 4;
            in += maxN;
         }
         else if(in - maxIn < 0x1000 && maxN < 0xB)
         {
            Flush(pOut);
            pOut[out2] = (maxN - 3) << 4 | (in - maxIn) >> 8;
            pOut[out2 + 1] = (BYTE)(in - maxIn);
            out2 += 2;
            in += maxN;
         }
         else if(maxN < 0x43)
         {
            Flush(pOut);
            pOut[out2] = 0xC0 | (maxN - 3);
            *(WORD*)(pOut + out2 + 1) = maxIn;
            out2 += 3;
            in += maxN;
         }
         else
         {
            Flush(pOut);
            pOut[out2] = 0xFF;
            *(WORD*)(pOut + out2 + 1) = maxN;
            *(WORD*)(pOut + out2 + 3) = maxIn;
            out2 += 5;
            in += maxN;
         }
      }
      else
      {
         nun2[obytes] = pIn[in];
         obytes++;
         if(obytes == 0x3F) Flush(pOut);
         in++;
      }
   }
   Flush(pOut);
   pOut[out2] = 0x80;
   out2++;
   *rLen = option;
   return out2;
}
//---------------------------------------------------------------------------

--- Конец кода ---

--- Цитата ---Компилилось все это в виде дээлэльки-плагина к моей проге. Тебе это нафик не надо, переделаешь в экзешники.
Если, конечно, поймешь хоть что-нибудь в этой писанине. Особенно в сишной.
--- Конец цитаты ---
Есть желающие сделать полноценную прогу?
ghola:
Всем привет!
Скажите, а сложно добавить в игру новый юнит? И возможно ли это сейчас?
serj320:

--- Цитата: ghola от 16 Август 2011, 16:05:19 ---Всем привет!
Скажите, а сложно добавить в игру новый юнит? И возможно ли это сейчас?

--- Конец цитаты ---

В принципе возможно, но это недостаточно легко.

И лень всем  :D (ну, может кроме Lipetsk'а )
TrickZter:
А какой смысл делать хак именно сегавской версии?  :? На комповской можно сделать куда более полноценных хак.
serj320:

--- Цитата: TrickZter от 16 Август 2011, 21:17:15 ---А какой смысл делать хак именно сегавской версии?  :? На комповской можно сделать куда более полноценных хак.

--- Конец цитаты ---

http://www.cncseries.ru/forums/lofiversion/index.php/t6099.html здесь посмотри. тебе понравится ;)

Добавлено позже:
в спойлере неплохой спрайт танка



Добавлено позже:
здесь делают свою дюну
http://www.cncseries.ru/forums/index.php?act=ST&f=97&t=6099&st=0#entry219614

это тоже форум по этому же проэкту
http://www.cncseries.ru/forums/lofiversion/index.php/t6099-0.html

Добавлено позже:
нашел изображение на тему дюны

а возможно эти иконки в дюну вставить?
Vivi the Black Mage:
serj320, только переведя в соответствующий тип графики. А так нехиленько смотрится.
serj320:
Vivi the Black Mage это я знаю (битность тоесть кол-во цветов)
ghola:
serj320, главное, что возможно!
Вот бы ещё информацию получить, какие-то проги что ли.

Интересно, есть проекты Дюны, где воюют дома из дюны2, дюны2000 и эмперор  :lol:

TrickZter, просто у меня мечта такая))
serj320:

--- Цитата: ghola от 16 Август 2011, 23:31:45 ---Интересно, есть проекты Дюны, где воюют дома из дюны2, дюны2000 и эмперор  :lol:

--- Конец цитаты ---

есть! я ссылку выкладывал в посте #1906
Jinaya:
Скажите, будет ли версия хака Дюны с миссиями за Сардуакаров, но без атаки врагов группами. Слишком осложняется игра. Хотя с исправленной ошибкой с атаками групп играть интересно. 
ghola:

--- Цитата: serj320 от 16 Август 2011, 23:33:54 ---есть! я ссылку выкладывал в посте #1906

--- Конец цитаты ---
Там три ссылки на одну тему о "симуляторе червя"... в целом, не важно.
Есть скриншоты этой игры?

Хотел узнать, как относитесь к тому, что бы в игре было больше домов, каждый со своим цветом и особенностями?
Lipetsk:

--- Цитата: Jinaya от 17 Август 2011, 11:03:50 ---Скажите, будет ли версия хака Дюны с миссиями за Сардуакаров, но без атаки врагов группами. Слишком осложняется игра. Хотя с исправленной ошибкой с атаками групп играть интересно. 

--- Конец цитаты ---
Так в хаке частично починены TEAMS (командный AI). То есть работает не всегда. Я ещё хотел патч поставить, который бы активизировал этот алгоритм чаще. Но пока не решил, т.к может повлиять на баланс. Если будут какие-либо изменения (а они будут) то только в сторону усложнения.

--- Цитата: ghola от 17 Август 2011, 11:49:44 ---Хотел узнать, как относитесь к тому, что бы в игре было больше домов, каждый со своим цветом и особенностями?

--- Конец цитаты ---
А вы как думаете?
serj320:
ghola весь смысл в том что по этим ссылкам много чего интересного для развития проэкта найти

P.S.
Мне этот "симулятор червя" ненужен
ghola:
Lipetsk, ну, например, что скажете про такую идею.

Дому Моритани (союзники Д. Коррино) решил нарисовать герб в виде японского дракона, держащегося за две звезды, и, с катаной в лапе, пронизывающей планету с кольцами.
Из особенных юнитов выступают самураи, которые обучены ценой своей жизни защищать здания от посягательств захватчиков и саботажников. Следовательно, их можно сажать в здание, при каждой попытке проникнуть, враги будут гибнуть вместе с одним самураем.
Segaman:
респект за идею :D, но сие невыполнимо во всех планах. дюна не на гейм-мейкере сделана
serj320:
ghola дело в том что ром имеет весьма ограниченый размер, а новый дом это множество дополнительной информации.
Ti_:

--- Цитата: Segaman от 17 Август 2011, 16:53:41 ---респект за идею :D, но сие невыполнимо во всех планах. дюна не на гейм-мейкере сделана

--- Конец цитаты ---
Нашли тут код взрыва спайсовый пипки:


--- Код: ---ROM:0001ACB6                 move.w  #5,-(sp)        ; radius
ROM:0001ACBA                 move.w  d3,-(sp)
ROM:0001ACBC                 jsr     sub_1ACC8
ROM:0001ACC2                 addq.l  #4,sp
ROM:0001ACC4                 move.l  (sp)+,d3
ROM:0001ACC6                 rts
ROM:0001ACC6 ; End of function extra_hit
ROM:0001ACC6
ROM:0001ACC8
ROM:0001ACC8 ; =============== S U B R O U T I N E =======================================
ROM:0001ACC8
ROM:0001ACC8
ROM:0001ACC8 sub_1ACC8:                              ; ...
ROM:0001ACC8                 movem.l d3-d7/a2-a5,-(sp)
--- Конец кода ---



--- Код: ---ROM:0001AD44                 move.w  #1,(sp)         ; 1 (create spice)
ROM:0001AD48                 move.w  d5,-(sp)        ; where create
ROM:0001AD4A                 jsr     spice_del_or_cr

--- Конец кода ---

Может попробуешь переписать его в редактор для генерации карт?
1ACC8 - определяет блоки где создавать спайс.
 jsr     spice_del_or_cr  (1A51С)  - для каждого блока запускает создание спайса.

Как-то вот так от центра строится.

Добавлено позже:

--- Цитата: serj320 от 17 Август 2011, 17:14:12 ---ghola дело в том что ром имеет весьма ограниченый размер, а новый дом это множество дополнительной информации.

--- Конец цитаты ---
Размер рома не особо ограничен. Можно напихать хоть 1000 уровней.
Для дома нужна только память ram, да и то не слишком много (да и можно просто заменить мерценаров).
А вот в палитрах ограничение есть, например только 4 палитры доступно.
Поэтому больше 4 разных цветов для юнитов и мигалок одновременно не сделать.

А основная сложность добавления нового дома в модификации кода и устранении всяких багов. Делали фрименов но не доделали) Что-то ИИ глючить начинал.
А с юнитами еще сложнее. Заменить - реально. А добавлять лучше не начинать даже (придется перебирать весь код). Кроме того под новый юнит все равно места в видеопамяти не будет.
ghola:

--- Цитата: Segaman от 17 Август 2011, 16:53:41 ---респект за идею :D, но сие невыполнимо во всех планах. дюна не на гейм-мейкере сделана

--- Конец цитаты ---

Вот спасибо! Эта идея из другого проекта, но основывается он на дизайне Дюны 2.
А в ромхаке думал добавить отряды пехоты численностью 5, 7 и 9, а раз шипко сложно, то ну и чёрт с ними))
Навигация
Главная страница сообщений
Следующая страница
Предыдущая страница

Перейти к полной версии