Объявления

Форум о Героях Меча и Магии и King's Bounty. Если Вы любите эти игры, мы будем рады видеть Вас в наших рядах. :smile2:

Как создать плагин для HD мода

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5048
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 1934 раз.

Re: Как создать плагин для HD мода

Сообщение AlexSpl » 24 фев 2021, 12:13

Цитата:
3. Ограничение на покупку количества героев (например в тхт файле вводить кол-во)

Код: Выделить всё
#define _CRT_SECURE_NO_WARNINGS
#include "..\..\HotA\homm3.h"

Patcher* _P;
PatcherInstance* _PI;

char iniPath[MAX_PATH];
char strBuffer[201] = "";

#define o_ADVEVENT (*(_TXTEX_**)0x696A68)

struct _TXTEX_ : public _TXT_ {
   inline void SetString(int index, char* str) { *(char**)(*(int*)((int)this + 32) + index * 4) = str; }
};

int __stdcall afterInit(LoHook* h, HookContext* c)
{
    GetPrivateProfileStringA("Messages", "Prison", o_ADVEVENT->GetString(103), strBuffer, 201, iniPath);
    o_ADVEVENT->SetString(103, strBuffer);
   
    return EXEC_DEFAULT;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    static _bool_ plugin_On = 0;
    if ( DLL_PROCESS_ATTACH == ul_reason_for_call )
    {
        if ( !plugin_On )
        {
           plugin_On = 1;
           _P = GetPatcher();
           _PI = _P->CreateInstance("HD.Plugin.H3.LimitMaxHeroes");
           
           GetCurrentDirectoryA(sizeof(iniPath), iniPath);
           strcat(iniPath, "\\LimitMaxHeroes.ini");
           
           char maxHeroes = GetPrivateProfileIntA("Limits", "MaxHeroes", 8, iniPath);
           _PI->WriteByte(0x431391, maxHeroes);
           _PI->WriteByte(0x4A3BE1, maxHeroes);
           _PI->WriteByte(0x52A891, maxHeroes);
           _PI->WriteByte(0x5D566F, maxHeroes);
           _PI->WriteByte(0x5D7E02, maxHeroes);
           _PI->WriteByte(0x5D7E0B, maxHeroes);
           _PI->WriteByte(0x5D860A, maxHeroes);
           _PI->WriteLoHook(0x4EE1C1, afterInit);
        }
    }

   return TRUE;
}

Файл LimitMaxHeroes.ini положить рядом с плагином:

Код: Выделить всё
[Limits]
MaxHeroes=3

[Messages]
Prison=You already have three heroes, and regretfully must leave the prisoner in this jail to languish in agony for untold days.

* * *
UPD: Добавил два пропущенных кейса (AI и сообщение о невозможности выйти из гарнизона, т.к. уже есть максимум героев на карте).
Вернуться к началу

offlineRolex  
имя: Alex
Ветеран
Ветеран
 
Сообщения: 889
Зарегистрирован: 22 сен 2020, 18:58
Откуда: УКРАИНА
Пол: Мужчина
Поблагодарили: 49 раз.

Re: Как создать плагин для HD мода

Сообщение Rolex » 25 фев 2021, 10:56

AlexSpl писал(а):

Пункт 13 (Фрешмод) частично тоже здесь. Код для учёного точно.

Вот код ученого нашелся, который Вы писали несколько лет назад:

Код: Выделить всё
        #define _CRT_SECURE_NO_WARNINGS
        #include "HotA\homm3.h"

        Patcher* _P;
        PatcherInstance* _PI;
        static _bool_ plugin_On = 0;

        char TxtBuffer[50];

        int __stdcall showScholarInfo(LoHook* h, HookContext* c)
        {
           // Учёный?
           if (c->eax == 0x51) {
              int ScholarType = (*(int*)c->ebx << 0x1D) >> 0x1D;
              switch (ScholarType) {
              case 0:
                 sprintf(TxtBuffer, "%s %s", (char*)c->edi, "(stat)");
                 break;
              case 1:
                 sprintf(TxtBuffer, "%s %s", (char*)c->edi, "(skill)");
                 break;
              case 2:
                 sprintf(TxtBuffer, "%s %s", (char*)c->edi, "(cast)");
                 break;
              }

              c->edi = (int)TxtBuffer;
           }

           return EXEC_DEFAULT;
        }

        BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
        {
           if (DLL_PROCESS_ATTACH == ul_reason_for_call)
           {
              if (!plugin_On)
              {
                 plugin_On = 1;
                 _P = GetPatcher();
                 _PI = _P->CreateInstance("HD.Plugin.Scholar");

                 _PI->WriteLoHook(0x40D059, showScholarInfo);
              }
           }

           return TRUE;
        }


AlexSpl, а не подскажите, как этот код подправить так, чтобы выводился не тип (первичный, вторичный, заклинание), а именно фактически, что он даст: название самого навыка или заклинания?
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5048
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 1934 раз.

Re: Как создать плагин для HD мода

Сообщение AlexSpl » 25 фев 2021, 14:19

Думаю, вся информация об Учёном хранится в *(int*)c->ebx. Например, тип Учёного получается следующим образом:

11111111 11111111 11111111 11111111 (исходное число)
11100000 00000000 00000000 00000000 (побитово сдвинули (<<) влево на 29)
00000000 00000000 00000000 00000111 (побитово сдвинули вправо (>>) на 29)
11111111 11111111 11111111 11111111 (т.е. три младших бита хранят тип Учёного; используется два: 00, 01, 10)

Посмотрите, что находится в остальных.

* * *
UPD: Исправил. Конечно же, младших :smile14:
Последний раз редактировалось AlexSpl 26 фев 2021, 06:14, всего редактировалось 3 раз(а).
Вернуться к началу

offlineRolex  
имя: Alex
Ветеран
Ветеран
 
Сообщения: 889
Зарегистрирован: 22 сен 2020, 18:58
Откуда: УКРАИНА
Пол: Мужчина
Поблагодарили: 49 раз.

Re: Как создать плагин для HD мода

Сообщение Rolex » 25 фев 2021, 16:18

AlexSpl, а подскажите, пжл, как посмотреть, что находится в остальных?

Свича у нас уже быть не должно по идеи, так как нам уже не нужно делить вывод на типы, а нужно получить то, что храниться. Хотя там, вероятно, будет хранится число, возможно айди навыка/заклинания. В таком случае свич с типом можно оставить, и уже уже по полученному айди и типу применять нужную функцию получения названия навыка/заклинания по его айди. Это конечно, если все так, как я думаю. Но если попытаться вывести то, что там хранится, то вот так, например, у меня вылетает при наведении курсора на Ученого:
Код: Выделить всё
int ScholarType = (*(int*)c->ebx << 26) >> 26;
sprintf(TxtBuffer, "%s %s", (char*)c->edi, to_string(ScholarType));
c->edi = (int)TxtBuffer;
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5048
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 1934 раз.

Re: Как создать плагин для HD мода

Сообщение AlexSpl » 26 фев 2021, 05:51

Попробуйте выводить на экран значение *(int*)c->ebx. Состояние Учёного Вам заранее известно: тип - три младших* бита, теперь попробуйте разглядеть в остальных битах ID заклинания/первичного/вторичного навыка (который Вам тоже известен, если Вы загружаете один и тот же сейв).

* См. мой пост выше.
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5048
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 1934 раз.

Re: Как создать плагин для HD мода

Сообщение AlexSpl » 26 фев 2021, 10:35

В Героях Меча и Магии (и не только в третьей части) практикуется упаковка свойств объектов в двойное слово (DWORD, 32 бита), слово (WORD, 16 бит) или даже байт (BYTE, 8 бит). Например, состояние нейтральных монстров (количество и лояльность) не хранятся по отдельности и запакованы в 32-х битное число. То же самое и с обсуждаемым выше Учёным. Давайте посмотрим, как работать с такими запакованными данными: как их распаковывать и как запаковывать.

1. Распаковка

Чтобы не увязнуть в общей теории, давайте рассмотрим, как игра запаковывает свойства Учёного в 32-х битное число. Для начала определим, какие свойства есть у Учёного. Он может:

0) повышать один из 4-х первичных навыков;
1) давать или повышать ступень развития одного из 28-ми (29-ти в HotA) вторичных навыков;
2) учить одному из 69-ти заклинаний (70 минус Titan's Lightning Bolt).

Здесь нас не будет интересовать, в каких случаях срабатывает каждый из этих вариантов, или есть ли ограничения на получаемые заклинания, т.к. к теме упаковки это не относится.

Видим, что для хранения номера заклинания, а также номеров первичного и вторичного навыков будет хватать 3-х байтов + 1 байт на хранение самого типа награды (1 байт = 8 бит и может хранить в себе 2^8 = 256 состояний). Хорошо, можно хранить эту информацию в 2-х байтах: первый байт - тип награды, второй байт - ID награды (заклинание/первичный/вторичный навык), но программисты NWC решили "заморочиться" и запаковали всё это - внимание! - в 4 байта, причём - внимание! - используя битовые поля. Не будем сейчас рассуждать на тему, почему они так сделали (возможно, ради универсальности: у всех тайлов карты _MapItem_ есть 32-битное поле setup, но по-прежнему непонятно, почему бы не обойтись 2-мя младшими байтами этого поля и не "заморачиваться" с упаковкой/распаковкой). Но есть то, что есть. Поэтому далее.

Пронумеруем биты двойного слова:

Код: Выделить всё
HEX 1F 1E 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
DEC 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
     X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X

Биты справа (X, может принимать два значения: 0 или 1) называются младшими, биты слева - старшими.

Посчитаем, сколько бит потребуется для упаковки ID в каждом из трёх вышеупомянутых случаев:

0) 4 первичных навыка. Хватит 2-х бит. Например, Атаку можно закодировать последовательностью бит 00, Защиту - 01, Силу Магии - 10 и Знания - 11;
1) 28 (29 в HotA) вторичных навыка. Хватит 5-ти бит. Pathfinding - 00000, Archery - 00001, ..., First Aid - 11011 (Interference - 11100);
2) 70 заклинаний. Хватит 7-ми бит. Summon Boat - 0000000, Scuttle Boat - 0000001, ..., Air Elemental - 1000101 (здесь 7 бит хватает даже на заклинания существ, если что).
А ещё потребуется 2 бита на хранение типа награды: 00 - первичный навык, 01 - вторичный навык, 10 - заклинание.

Для тех кто не знает, как подобрать минимальное количество бит, способных сохранить N состояний: Вам следует подобрать такую степень двойки, чтобы она была не меньше числа состояний, а предыдущая степень - меньше. Например, для 70-ти заклинаний: 2^6 = 64 меньше, чем 70, а 2^7 = 128 уже больше. Поэтому для хранения всех состояний потребуется 7 бит.

Итого нам потребуется 2 + 5 + 7 + 2 = 16 бит. Однако следует учесть, что по умолчанию арифметические и логические операции проводятся над целыми числами со знаком, и на хранение этого знака нужен ещё 1 бит: 0 - знака нет, 1 - знак есть. Можно, конечно, обойтись и без знака, занимающего лишний бит, но тогда придётся работать с беззнаковыми типами: unsigned char, unsigned int и т.п., что есть прямой путь к возникновению различных багов. Программисты NWC знали это, поэтому просто примите: для каждого числа нужен ещё один бит под знак. Итого: 3 + 6 + 8 + 3 = 20 бит, которые отлично помещаются в двойное слово setup.

Давайте теперь посмотрим, как награды Учёного реально хранятся в этом двойном слове (32-х битах) и как их оттуда достать:

Код: Выделить всё
HEX 1F 1E 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
DEC 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
     X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  R  R  R

Три младших бита (R) занимает тип награды (см. выше). Чтобы получить это значение, применяют две операции побитого сдвига (shl - логический сдвиг влево и sar - арифметический сдвиг вправо; разница между логическим и арифметическим сдвигом в том, что второй сохраняет знак числа). В C++ для shl есть оператор <<, а для shr/sar - >> (про нюансы использования и отличия shr и sar почитайте сами, ибо уже лезем в джунгли).

Нас будет интересовать формула, позволяющая получить значение последовательности бит длиной L, начиная с бита с номером N. Например, чтобы достать тип награды (см. три бита R выше), нам потребуется извлечь последовательность бит длиной L = 3, начиная с бита с номером N = 0. Это можно сделать двумя сдвигами: влево до тех пор, пока левый бит R не упрётся в левую стенку (позиция 31), и вправо до тех пор, пока правый бит R не упрётся в правую стенку (позиция 0). Немного смекнув, понимаем, что двойное слово нужно сдвинуть влево на 32 (размер двойного слова) - 3 (длина последовательности бит) = 29 бит, а потом на столько же вправо. Отсюда и получается код (см. пост с кодом выше):

Код: Выделить всё
int ScholarType = *(int*)c->ebx << 29 >> 29;

Аналогично можно извлечь и остальные значения (кто не умеет читать дизассемблированный/декомпилированный листинг, может легко догадаться после серии экспериментов, в каких именно битах эти значения хранятся):

0) Первичный навык (буквами "P" отмечена битовая последовательность, хранящая ID навыка):

Код: Выделить всё
HEX 1F 1E 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
DEC 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
     X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  P  P  P  R  R  R

Мы видим, что на хранение ID первичного навыка отводится 3 бита (2 бита на сам ID + 1 бит знаковый). Нам нужно извлечь последовательность бит длиной L = 3, начиная с бита с номером N = 3. Очевидно, что нужно подвинуть крайний левый бит "до упора" влево: 32 - (N + L) = 32 - (3 + 3) = 26 бит, а потом вправо на 32 - L = 32 - 3 = 29 бит. Итого код:

Код: Выделить всё
int ScholarPrimarySkill = *(int*)c->ebx << 26 >> 29;

1) Вторичный навык (буквами "S" отмечена битовая последовательность, хранящая ID навыка):

Код: Выделить всё
HEX 1F 1E 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
DEC 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
     X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  X  S  S  S  S  S  S  S  P  P  P  R  R  R

На хранение номера вторичного навыка отводится 7 бит (6 бит + 1 знаковый). С запасом. Нам нужно извлечь последовательность бит длиной L = 7*, начиная с бита с номером N = 6. Двигаем крайний левый бит "до упора" влево: 32 - (N + L) = 32 - (6 + 7) = 19 бит, а потом вправо на 32 - L = 32 - 7 = 25 бит. Код:

Код: Выделить всё
int ScholarSecondarySkill = *(int*)c->ebx << 19 >> 25;

* Вы не можете знать об избытке, но это не играет никакой роли, потому что в избыточных битах всё равно будут нули.

2) Заклинание (буквами "M" отмечена битовая последовательность, хранящая ID заклинания):

Код: Выделить всё
HEX 1F 1E 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
DEC 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
     X  X  X  X  X  X  X  X  X  M  M  M  M  M  M  M  M  M  M  S  S  S  S  S  S  S  P  P  P  R  R  R

На хранение ID заклинания отведено целых 9 бит + 1 бит знаковый, т.е. с порядочным избытком. Нам нужно извлечь последовательность бит длиной L = 10*, начиная с бита с номером N = 13. Подвинем крайний левый бит "до упора" влево: 32 - (N + L) = 32 - 23 = 9 бит, а потом вправо на 32 - L = 32 - 10 = 22 бита. Код:

Код: Выделить всё
int ScholarSpell = *(int*)c->ebx << 9 >> 22;

* Вы не можете знать об избытке, но это не играет никакой роли, потому что в избыточных битах всё равно будут нули.

2. Запаковка

Здесь всё элементарно. Обнуляем двойное слово. Двигаем значение влево в нужное место приёмника (обычно приёмник - двойное слово DWORD) и логически складываем полученное значение с текущим значением приёмника. Например, пусть Учёный даёт заклинание Titan's Lightning Bolt (ID = 57):

Код: Выделить всё
*(int*)c->ebx |= 57 << 13; // 13 - номер битовой позиции, с которой начинается ID заклинания


Если же требуется не инициализировать битовое поле, а перезаписать его, то проще всего использовать подходящую структуру:

Код: Выделить всё
struct Scholar {
   int Reward : 3;
   int PSkill : 3;
   int SSkill : 7;
   int Spell  : 10;
};
...
Scholar* scholar = (Scholar*)c->ebx;
scholar->Spell = 57;
Последний раз редактировалось AlexSpl 26 фев 2021, 12:37, всего редактировалось 2 раз(а).
Вернуться к началу

offlineRolex  
имя: Alex
Ветеран
Ветеран
 
Сообщения: 889
Зарегистрирован: 22 сен 2020, 18:58
Откуда: УКРАИНА
Пол: Мужчина
Поблагодарили: 49 раз.

Re: Как создать плагин для HD мода

Сообщение Rolex » 26 фев 2021, 11:28

Спасибо. Круто, целая статья вышла. AlexSpl, вам преподавать нужно. Очень грамотно, подробно и толково все расписываете. :smile2:

И такой вопрос. Теперь у нас есть айди первичного/вторичного навыка/заклинания. А как теперь по этому айди получить название навыка/заклинания, чтобы в коде ручками каждый айди и его название не прописывать?
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5048
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 1934 раз.

Re: Как создать плагин для HD мода

Сообщение AlexSpl » 26 фев 2021, 11:43

Названия заклинаний легко получить через o_Spell: o_Spell[ID].name и o_Spell[ID].short_name. Для первичных и вторичных навыков должны быть свои таблицы (в homm3.h нет, но можно найти в коде).
Вернуться к началу

offlineRolex  
имя: Alex
Ветеран
Ветеран
 
Сообщения: 889
Зарегистрирован: 22 сен 2020, 18:58
Откуда: УКРАИНА
Пол: Мужчина
Поблагодарили: 49 раз.

Re: Как создать плагин для HD мода

Сообщение Rolex » 26 фев 2021, 11:56

AlexSpl писал(а):

Для первичных и вторичных навыков должны быть свои таблицы (в homm3.h нет, но можно найти в коде).

По идеи можно же как-то доработать homm3.h (вероятно, нужно найти и прописать адрес на таблицу с названием навыков), чтобы получать названия навыков, например, через:
o_PrimarySkills[ID].name / o_SecondarySkills[ID].name
Последний раз редактировалось Rolex 26 фев 2021, 12:11, всего редактировалось 2 раз(а).
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5048
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 1934 раз.

Re: Как создать плагин для HD мода

Сообщение AlexSpl » 26 фев 2021, 12:06

Сейчас подумал, что

Код: Выделить всё
*(int*)c->ebx |= 57 << 13;

сгодится только для инициализации заклинания Учёного, т.е. когда состояние Учёного обнуляется и последовательно заполняются битовые поля (в любом порядке):

Код: Выделить всё
*(int*)c->ebx = 0;
*(int*)c->ebx |= RewardType;
*(int*)c->ebx |= PrimarySkill << 3;
*(int*)c->ebx |= SecondarySkill << 6;
*(int*)c->ebx |= Spell << 13;

Но если нам нужно именно перезаписать битовое поле, то простое логическое сложение (|=) уже не прокатит.

Интересно, как сделать перезапись битовых полей проще всего? :smile5: Наверное, использовать подходящую структуру:

Код: Выделить всё
struct Scholar {
   int Reward : 3;
   int PSkill : 3;
   int SSkill : 7;
   int Spell  : 10;
};
...
Scholar* scholar = (Scholar*)c->ebx;
scholar->Spell = 57;
Последний раз редактировалось AlexSpl 26 фев 2021, 12:31, всего редактировалось 1 раз.
Вернуться к началу

Пред.След.

Вернуться в Общий раздел

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

cron