Сделал опрятный ini-файл. На примере Poison:
- Код: Выделить всё
; Spell #71
[Poison]
<Enabled> = 1
<Type> = -1
<Sound.FileName> = "Poison.wav"
<Animation.ID> = 67
<Attributes> = 266261
<AbbreviatedName> = "Poison"
<Name> = "Poison"
<Level> = 4
<School.Earth> = 1
<School.Water> = 0
<School.Fire> = 0
<School.Air> = 0
<Cost.None> = 20
<Cost.Basic> = 16
<Cost.Advanced> = 16
<Cost.Expert> = 16
<Effect.Power> = 0
<Effect.None> = 5
<Effect.Basic> = 5
<Effect.Advanced> = 4
<Effect.Expert> = 3
<ChanceToGain.Castle> = 0
<ChanceToGain.Rampart> = 5
<ChanceToGain.Tower> = 5
<ChanceToGain.Inferno> = 5
<ChanceToGain.Necropolis> = 10
<ChanceToGain.Dungeon> = 5
<ChanceToGain.Stronghold> = 0
<ChanceToGain.Fortress> = 0
<ChanceToGain.Conflux> = 5
<AIValue.None> = 50
<AIValue.Basic> = 50
<AIValue.Advanced> = 100
<AIValue.Expert> = 150
<RightClickText.Normal> = "{Poison}\n\nPoisons an enemy unit, reducing its health at once and then at the beginning of the next two rounds.\n"
<RightClickText.Basic> = "{Basic Poison}\n\nPoisons an enemy unit, reducing its health at once and then at the beginning of the next two rounds.\n"
<RightClickText.Advanced> = "{Advanced Poison}\n\nPoisons an enemy unit, reducing its health at once and then at the beginning of the next two rounds.\n\nEffect is greater than that of Basic Poison.\n"
<RightClickText.Expert> = "{Expert Poison}\n\nPoisons an enemy unit, reducing its health at once and then at the beginning of the next two rounds.\n\nEffect is greater than that of Advanced Poison.\n"
Теперь нужно провернуть ту же схему, что и с магической гильдией, для RMG (у нас максимум 128 заклинаний, а RMG использует только 96-битовое поле).
* * *
С RMG придётся повозиться
Как Вам такое?
Безопасно можно только до 96 заклинаний, если играть на рандомных картах. Чтобы разогнать до 128, сначала нужно понять, что делает этот код
Похоже, код считает контрольную сумму* различных структур. Так, для битового массива запрещённых заклинаний проход идёт по 9 байтам, т.е. 72 битам: 32 + 32 + 8. 9 - минимальное кол-во байт, вмещающих битовый массив запрещённых заклинаний: 64 <= 70 <= 72. В оригинале этот битовый массив RMG заполняет нулями, поэтому для карт RMG не действует глобальный запрет заклинаний. Плагин NewSpells уже поддерживает глобальный запрет, теперь ещё и правильная контрольная сумма будет генерироваться. Мелочь, а приятно
* В коде Героев 3 для Dreamcast есть функция adler32(). Возможно, это она.
* * *
К сожалению, малой кровью не отделаться. Чтобы полноценно поддерживать битовый массив запрещённых заклинаний, нужно менять формат карты (или ставить костыль на этапе её загрузки). Например, смотрите следующий код из функции начала новой игры (и таких участков много):
- Код: Выделить всё
.text:004C240E mov ecx, [ebp+a2]
.text:004C2411 lea eax, [ebp+var_30] ; Load Effective Address
.text:004C2414 push 9
.text:004C2416 push eax
.text:004C2417 mov edx, [ecx]
.text:004C2419 call dword ptr [edx+4] ; Indirect Call Near Procedure
.text:004C241C xor esi, esi ; Logical Exclusive OR
.text:004C241E lea edi, [ebp+var_1C] ; Load Effective Address
.text:004C2421
.text:004C2421 loc_004C2421: ; CODE XREF: NewGame1+33E↓j
.text:004C2421 mov ecx, esi
.text:004C2423 mov edx, 1
.text:004C2428 and ecx, 7 ; Logical AND
.text:004C242B mov eax, esi
.text:004C242D shl edx, cl ; Shift Logical Left
.text:004C242F shr eax, 3 ; Shift Logical Right
.text:004C2432 mov [ebp+var_3C], edi
.text:004C2435 mov [ebp+var_38], esi
.text:004C2438 mov cl, [ebp+eax+var_30]
.text:004C243C test cl, dl ; Logical Compare
.text:004C243E setnz dl ; Set Byte if Not Zero (ZF=0)
.text:004C2441 push edx
.text:004C2442 lea ecx, [ebp+var_3C] ; Load Effective Address
.text:004C2445 call sub_004CEC40 ; Call Procedure
.text:004C244A inc esi ; Increment by 1
.text:004C244B cmp esi, 70 ; Compare Two Operands
.text:004C244E jb short loc_004C2421
Здесь push 9 - это как раз те самые 9 байтов, отводимые под битовый массив запрещённых заклинаний. Битовый массив читается из файла карты. Т.е. мы никак не можем прочесть больше, потому что прочитаем данные, которые в файле карты следуют за этим битовым массивом. Но это некритично, т.к. в плагине мы расширяем этот битовый массив, а все объекты в Героях 3 инициализируются только при старте карты, т.е. при загрузке сейва заклинания в магических гильдиях/свитках/святилищах/пирамидах и т.п. не меняются (к нашей радости). Ноги у того "мусора", о котором я писал ранее и который приходилось "выбрасывать", растут отсюда. Поэтому следующие патчи не нужны (я оставил на всякий, вдруг реально до редактора карт дойдём):
- Код: Выделить всё
// ===============================================================
// -------------------------- New Game ---------------------------
// ---------------------------------------------------------------
// Don't need these patches yet, as we read a standard map
// Will work only if we change map format
//_PI->WriteByte (0x4C2415, CeilDiv(SPELLS_NUM, 8));
//_PI->WriteByte (0x4C244D, SPELLS_NUM);
//_PI->WriteByte (0x4C246F, SPELLS_NUM);
//_PI->WriteDword (0x4C24C9, SPELLS_NUM * sizeof(_Spell_));
//_PI->WriteByte (0x4C250E, SPELLS_NUM);
//_PI->WriteDword (0x4C2557, SPELLS_NUM * sizeof(_Spell_));
//_PI->WriteDword (0x4C260D, SPELLS_NUM * sizeof(_Spell_));
// ===============================================================
Запрещённые заклинания будут браться прямиком из NewSpells.ini. В отличие от оригинальной игры, RMG с плагином будет поддерживать запрет заклинаний, включая новые.