Wake of Gods Forum | Форум Во Имя Богов

Full Version: Вопросы по моддингу
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
RoseKavalier, thanks. But these 2 artifacts are 127/128, a bit of a distance to reach the 140 limit. Unsure
I see, probably done so because they were meant to be campaign specials only.
RoseKavalier, probably. Limiting them from spawning makes them very unique in the game.

________


Another question about modding.

Is there a way to check whether a scenario is from a campaign and is resumed from another scenario?

I'm trying to make a feature that saves my henchman stats over campaigns, just like heroes and commanders. But it looks impossible without this check.
Archer30, I don't understand the ide quite well. How to resume savegame from another scenario?
Berserker, by using campaign format of savegame?

For example, check this video. This guy wined the first scenario and saved his game as Campaign.cgm. In the next episode, he resumed from the same savegame with keeping his heroes (skills + level). You can check by yourself with the cheat "wogonering" to quickly win a game.
There is no built-in way except the following:
Quote:Initializing Variables
Like flags, all variables begin the game with an initial value of 0. However, also like flags, certain variable ranges will NOT be reset between maps without restarting the Heroes game. Again, this is to allow those variables to "carry over" their values to another map as part of a multi-map campaign. When you start a new map, the following variables will be reset to zero (0) or a void string "" for z variables: f...t, v1...v500, v1001-v10000, z1...z300, z501-z1000, w1-w50. The following variables will retain their current values between games (unless you quit and restart Heroes): v501-v1000, z301-z500, w51-w100.
Thanks. That could help. But still, it's important to check whether a scenario is part of a campaign or just a normal one. Currently, this has to be pointed out by users (to decide whether used the save vars). 102
Archer30, scenario maker can store unique special value in transitional variable like v501 to mark game as campaign. Like: 1944734709.
Such magic constant may be checked and if found, variables are reused, not cleared.
Berserker, mind-blowing 132
(20.01.2021 19:29)Raistlin Wrote: [ -> ]Пораскинул я мозгами и придумал иной, менее замороченный вариант. К сожалению, он тоже не работает, хотя вроде должен...

Code:
Magic->WriteLoHook(0x4C8FBB, (void*)FixRandomMonasterGenerator);

Code:
int __stdcall FixRandomMonasterGenerator(LoHook* h, HookContext* c)
{
    if (*(char*)(c->ebp - 4) == 145)
        *(char*)(c->ebp - 4) = 164;
    if (*(char*)(c->ebp - 4) == 174)
        *(char*)(c->ebp - 4) = 145;

    return EXEC_DEFAULT;
}

Подскажите пожалуйста, почему не работает правка генератора случайных монстров?
P.S. В теме, посвящённой обсуждению плагинов, есть больше информации. Я, например, ещё кое-что кое-где пропатчил, но в данное сообщение цитату на взял.
(20.01.2021 22:14)Raistlin Wrote: [ -> ]Подскажите пожалуйста, почему не работает правка генератора случайных монстров?

Лично я тоже не понял, что делают твои хуки. EBP-4 - счётчик запрещающихся монстров (например память там выделена максимум под 160 монстров, ты зачем-то записываешь туда *(char*)(c->ebp - 4) = 164, что уже будет ошибкой, ну потом зачем-то проверяешь на *(char*)(c->ebp - 4) == 174), что тоже будет на грани утечки памяти).

Место, на которое ты ставишь хук - код, запрещающий монстров AB и SoD после проверки версии карты. Чисто теоретически, его трогать вообще не нужно.

Рекомендую написать собственный генератор случайных монстров, отправив оригинальный СоДовский на заслуженную пенсию (к примеру, в MoP давно присутствует собственный генератор случайного монстра, когда-нибудь и на Тифон его, по слухам, завезут).
Боже моой 858585
Я все неправильно понял и подумал, что это массив не ЗАПРЕЩЕННЫХ, а РАЗРЕШЕННЫХ монстров Dash1

XEPOMAHT, спасибо Вам! Я, пожалуй, и вправду напишу собственный генератор, а об этой попытке забуду как о страшном сне...
Raistlin, так чем тебя этот генератор не устроил?
Code:
_int_ __stdcall GameMgr_GetRandMonster_ByLevel(HiHook* hook, _GameMgr_* gm, int mon_lvl_Lo, int mon_lvl_Hi)
{
    // проверка на дурака 1
    if ( mon_lvl_Lo < 0 || mon_lvl_Lo > 6) {
        b_MsgBox("Please use the monster level 0-6", 1);
        return 0;
    }

    // проверка на дурака 2
    if ( mon_lvl_Hi < 0 || mon_lvl_Hi > 6) {
        b_MsgBox("Please use the monster level 0-6", 1);
        return 0;
    }

    // проверка на дурака 3
    if ( mon_lvl_Lo > mon_lvl_Hi ) {
        b_MsgBox("Are you kidding?!", 1);
        return 0;
    }

    // количество монстров в игре
    // тут нужно учесть и Тифон, и Аметист,
    // но и не гонять циклы в пустую (поэтому откуда бы считать?)
    int count = 196;

    // инициализируем массив (в Аметисте 1024)
    char monArray[1024];
    
    // заполняем массив нулями (запрещяем всех монстров)
    for(int i = 0; i < 1024; i++)
        monArray[i] = 0;

    // собираем массив монстров нужного уровня (разрешаем только этих монстров)
    for(int i = 0; i <= count; i++) {
        int lvl = o_CreatureInfo[i].level;

        if (lvl >= mon_lvl_Lo && lvl <= mon_lvl_Hi)
            monArray[i] = 1; // монстр нужного уровня
    }

    // исключаем несуществующих монстров
    monArray[122] = 0;
    monArray[124] = 0;
    monArray[126] = 0;
    monArray[128] = 0;

    // исключаем Драколича
    monArray[196] = 0;

    // исключаем Супер Драконов (так делает SOD)
    for(int i = 132; i <= 135; i++)
        monArray[i] = 0;

    // исключаем Боевые Машины
    for(int i = 145; i <= 149; i++)
        monArray[i] = 0;

    // исключаем Богов
    for(int i = 160; i <= 163; i++)
        monArray[i] = 0;

    // исключаем Командиров
    for(int i = 174; i <= 191; i++)
        monArray[i] = 0;

    // инициализация переменной
    int result;

    do { // ищем доступного монстра из разрешённых
        result = Randint(0, count);        
    } while ( !monArray[result] );

    // возвращаем id найденного монстра
    return result;
}



void StartPlugin()
{
    _PI->WriteHiHook(0x4C8F80, SPLICE_, EXTENDED_, THISCALL_, GameMgr_GetRandMonster_ByLevel);
    return;
}
Забыл о его существовании, хотя точно где-то видел... Спасибо Вам, igrik! 132
А мне походу тоже пора на пенсию вслед за СоДовским генератором...
Кстати, это ведь код из game bug fixes extended.dll? Я чувствую, мне определенно стоит ознакомиться с исходниками.
P.S. Я работаю в девятнадцатой студии, и мне потребовалось сделать приведение типов при вызове функции b_MsgBox. Это, ясное дело, не проблема, но на всякий случай я Вас уведомляю.
Reference URL's