Объявления

Друзья, если не получается зарегистрироваться, напишите на почту vdv_forever@bk.ru.
Я оторву свою задницу от всех дел и обязательно Вас активирую! :smile10:
Добро пожаловать на геройский форум! :smile25:

Герои 2 (разные версии) с плагинами

Не запускается игра? Проблемы со звуком? Где, в конце концов, взять игру, скачать патчи, приложения и карты? Как установить все это? Все проблемы обсуждаем в этом разделе
offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5587
Зарегистрирован: 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)
Поблагодарили: 2185 раз.

Re: Герои 2 (разные версии) с плагинами

Сообщение AlexSpl » 18 июн 2022, 23:45

Насколько я помню, AI умеет пользоваться Town Gate и Town Portal, а раз так, то ему нужно просто подсказать, что он знает, как телепортироваться домой. Другое дело, если я ошибаюсь (давно не играл в Двойку). Тогда эта задача может быть сложной.

Тут ещё вопрос: не может с артефактом в собранном виде? Или не может собрать артефакт?
Вернуться к началу

offlineАватара пользователя
Maximus  
имя: Maximus
Новичок
Новичок
 
Сообщения: 20
Зарегистрирован: 24 фев 2020, 10:56
Пол: Мужчина
Поблагодарили: 9 раз.

Re: Герои 2 (разные версии) с плагинами

Сообщение Maximus » 19 июн 2022, 20:40

Добрый вечер.
Артефакт собрать AI может. Порой даже по 3-4 таскает с собой, но Town Portal при этом не использует.
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5587
Зарегистрирован: 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)
Поблагодарили: 2185 раз.

Re: Герои 2 (разные версии) с плагинами

Сообщение AlexSpl » 19 июн 2022, 21:22

А в книге Town Portal появляется? Если нет, то решение - дело 5 мин (условно).
Вернуться к началу

offlineАватара пользователя
Maximus  
имя: Maximus
Новичок
Новичок
 
Сообщения: 20
Зарегистрирован: 24 фев 2020, 10:56
Пол: Мужчина
Поблагодарили: 9 раз.

Re: Герои 2 (разные версии) с плагинами

Сообщение Maximus » 20 июн 2022, 04:15

Появляется.
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5587
Зарегистрирован: 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)
Поблагодарили: 2185 раз.

Re: Герои 2 (разные версии) с плагинами

Сообщение AlexSpl » 20 июн 2022, 06:05

Думаю, из-за этой строчки в philAI::DoAnywhereDDoorTownGate():

Код: Выделить всё
if ( !hero::HasSpell(gpCurAIHero, 56) || *gpCurAIHero < 30 )
    return 0;

И вообще, я что-то не вижу, что AI умеет пользоваться Town Gate/Town Portal. Вот DD умеет. В этой функции нет логики, связанной с городами.
Вернуться к началу

offlineАватара пользователя
Maximus  
имя: Maximus
Новичок
Новичок
 
Сообщения: 20
Зарегистрирован: 24 фев 2020, 10:56
Пол: Мужчина
Поблагодарили: 9 раз.

Re: Герои 2 (разные версии) с плагинами

Сообщение Maximus » 20 июн 2022, 20:36

Вот-вот.
Настало время рукастых парней )))))
Да еще сделать логику так, чтобы он умел по замкам перемещаться в течение хода и собирать войско в один кулак )))))))
Вернуться к началу

offlineАватара пользователя
Maximus  
имя: Maximus
Новичок
Новичок
 
Сообщения: 20
Зарегистрирован: 24 фев 2020, 10:56
Пол: Мужчина
Поблагодарили: 9 раз.

Re: Герои 2 (разные версии) с плагинами

Сообщение Maximus » 12 авг 2022, 21:15

Напишите кто-нибудь плагин, отключающий PLAGUE!!!!!
Пожалуйста )))
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5587
Зарегистрирован: 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)
Поблагодарили: 2185 раз.

Re: Герои 2 (разные версии) с плагинами

Сообщение AlexSpl » 13 авг 2022, 01:10

Я видел ваш редактор сейвов. Значит, кодить умеете. Отчего не научиться тогда писать плагины? :smile2: Как раз таки Ваша задача отлично подходит для тренировочного плагина.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

Re: Герои 2 (разные версии) с плагинами

Сообщение Ben80 » 09 авг 2023, 13:26

Плагин, корректирующий изменение очков движения героев.
(только для английской версии 2.1)

В оригинальной игре очки движения (MP) рассчитываются только в начале хода (лишь при взаимодействии с некоторыми объектами они изменяются, например, благодаря Оазису). Плагин немедленно (а не в начале следующего хода) уменьшает количество MP героя, если ему передаются существа более медленные, чем самое медленное из существ, уже имевшихся у героя. Передача существ может быть от другого героя, от любого объекта карты, при взаимодействии героя с городом. Уменьшение количества MP пропорционально количеству MP героя на данный момент. Например, если у армия героя состоит из Эльфов и в начале хода ему передают гномов, то уменьшение MP составит 200. А если этому же герою передаются Гномы после того, как он прошел половину своего дневного максимума движения, то уменьшение составит всего 100.

Зачем это нужно ? Оригинальная механика игры заставляет совершать игроков всяческие ритуальные телодвижения по "возгонке" MP основных героев. Например, в конце хода к главному герою подходит вспомогательный герой и забирает у него наиболее медленных существ. А в начале следующего хода он уже отдает ему этих существ. Или, например, привычка забегать героем в город только для того, чтобы оставить в гарнизоне наиболее медленных существ, с тем, чтобы забрать их в следующий ход. Короче, имеется в виду весь этот бессмысленный и беспощадный "микроменеджмент", от которого хотелось бы избавиться. Знакомо то, что ниже ?
Изображение

Интересно было бы изучить последствия для игры использования предлагаемой механики. Стало ли меньше микроменеджмента ? Появились ли значительные дополнительные неудобства ? Увеличилось ли разнообразие стратегий ? (например, главному герою стали реже доставляться медленные существа по цепочкам и эти существа стали чаще использоваться в составе самостоятельных вспомогательных армий)

H2_HeroesMobilityChange.zip
(4.59 КБ) Скачиваний: 133


 Код
Код: Выделить всё


#include "../../include2023/patcher_x86.hpp"
#include "../../include2023/gui.h"
#include "../../include2023/managers.h"
#include "../../include2023/map.h"
#include "../../include2023/game.h"
#include "../../include2023/combat.h"

#include <math.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>

Patcher* _P;
PatcherInstance* _PI;

static _bool_ plugin_On = 0;

int aTag_monsterInfo;

int gpGame;
int gpCurPlayer;
int gpTownManager;
int giCurPlayer;

void __stdcall HH_advM_DoEvent(HiHook* h, advManager* advM, mapCell* cell, int cellX, int cellY)
{
   
    hero* hero_1 = &(*(game**)gpGame)->heroes[(*(playerData**)gpCurPlayer)->curHeroIdx];
    hero* hero_2;
    int location = cell->objType & 0x7F;

    if(!(hero_1->flags & HERO_AT_SEA))
    {
        int minSpeedBefore_1 = hero_1->field_43;
        int minSpeedBefore_2;

        if(location == LOCATION_HERO)
        {
            hero_2 = &(*(game**)gpGame)->heroes[(unsigned char)cell->extraInfo];
            if(!(hero_2->flags & HERO_AT_SEA))
                minSpeedBefore_2 = hero_2->field_43;
        }

        CALL_4(void, __thiscall, h->GetDefaultFunc(), advM, cell, cellX, cellY);

        int minSpeedAfter_1 = 7;
        for ( int i = 0; i < 5; ++i )
        {
          if ( hero_1->army.creatureTypes[i] != -1 && ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed < minSpeedAfter_1 )
            minSpeedAfter_1 = ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed;
        }

        if(minSpeedAfter_1 < minSpeedBefore_1)
        {
          hero_1->remainingMobility *= (float)(1000 + (minSpeedAfter_1 - 2) * 100)
            / (float)(1000 + (minSpeedBefore_1 - 2) * 100);
          hero_1->field_43 = minSpeedAfter_1;
        }

        if(location == LOCATION_HERO)
            if(!(hero_2->flags & HERO_AT_SEA))
            {
                int minSpeedAfter_2 = 7;
                for ( int i = 0; i < 5; ++i )
                {
                  if ( hero_2->army.creatureTypes[i] != -1 && ((tag_monsterInfo*)aTag_monsterInfo)[hero_2->army.creatureTypes[i]].speed < minSpeedAfter_2 )
                    minSpeedAfter_2 = ((tag_monsterInfo*)aTag_monsterInfo)[hero_2->army.creatureTypes[i]].speed;
                }

                if(minSpeedAfter_2 < minSpeedBefore_2)
                {
                  hero_2->remainingMobility *= (float)(1000 + (minSpeedAfter_2 - 2) * 100)
                    / (float)(1000 + (minSpeedBefore_2 - 2) * 100);
                  hero_2->field_43 = minSpeedAfter_2;
                }
            }
    }
    else
    {
        CALL_4(void, __thiscall, h->GetDefaultFunc(), advM, cell, cellX, cellY);
    }

    hero_1->mobility = CALL_1(int, __thiscall, 0x494BB0, hero_1);
    if(location == LOCATION_HERO)
    {
        hero_2->mobility = CALL_1(int, __thiscall, 0x494BB0, hero_2);
    }

}

void __stdcall HH_townManager_DoCommand(HiHook* h, townManager* tM, int command)
{
    hero* hero_1;
    int minSpeedBefore_1;

    if(tM->castle->visitingHeroIdx != -1)
    {
        hero_1  = &(*(game**)gpGame)->heroes[tM->castle->visitingHeroIdx];
        minSpeedBefore_1 = hero_1->field_43;
    }

    CALL_2(void, __thiscall, h->GetDefaultFunc(), tM, command);

    if(tM->castle->visitingHeroIdx != -1)
    {
        int minSpeedAfter_1 = 7;
        for ( int i = 0; i < 5; ++i )
        {
          if ( hero_1->army.creatureTypes[i] != -1 && ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed < minSpeedAfter_1 )
            minSpeedAfter_1 = ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed;
        }

        if(minSpeedAfter_1 < minSpeedBefore_1)
        {
          hero_1->remainingMobility *= (float)(1000 + (minSpeedAfter_1 - 2) * 100)
            / (float)(1000 + (minSpeedBefore_1 - 2) * 100);
          hero_1->field_43 = minSpeedAfter_1;
        }
    }
}

void __stdcall HH_advM_DoAIEvent(HiHook* h, advManager* advM, mapCell* cell, hero* hero_1, int cellX, int cellY)
{
   
    hero* hero_2;
    int location = cell->objType & 0x7F;

    if(!(hero_1->flags & HERO_AT_SEA))
    {
        int minSpeedBefore_1 = hero_1->field_43;
        int minSpeedBefore_2;

        if(location == LOCATION_HERO)
        {
            hero_2 = &(*(game**)gpGame)->heroes[(unsigned char)cell->extraInfo];
            if(!(hero_2->flags & HERO_AT_SEA))
                minSpeedBefore_2 = hero_2->field_43;
        }

        CALL_5(void, __thiscall, h->GetDefaultFunc(), advM, cell, hero_1, cellX, cellY);

        int minSpeedAfter_1 = 7;
        for ( int i = 0; i < 5; ++i )
        {
          if ( hero_1->army.creatureTypes[i] != -1 && ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed < minSpeedAfter_1 )
            minSpeedAfter_1 = ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed;
        }

        if(minSpeedAfter_1 < minSpeedBefore_1)
        {
          hero_1->remainingMobility *= (float)(1000 + (minSpeedAfter_1 - 2) * 100)
            / (float)(1000 + (minSpeedBefore_1 - 2) * 100);
          hero_1->field_43 = minSpeedAfter_1;
        }

        if(location == LOCATION_HERO)
            if(!(hero_2->flags & HERO_AT_SEA))
            {
                int minSpeedAfter_2 = 7;
                for ( int i = 0; i < 5; ++i )
                {
                  if ( hero_2->army.creatureTypes[i] != -1 && ((tag_monsterInfo*)aTag_monsterInfo)[hero_2->army.creatureTypes[i]].speed < minSpeedAfter_2 )
                    minSpeedAfter_2 = ((tag_monsterInfo*)aTag_monsterInfo)[hero_2->army.creatureTypes[i]].speed;
                }

                if(minSpeedAfter_2 < minSpeedBefore_2)
                {
                  hero_2->remainingMobility *= (float)(1000 + (minSpeedAfter_2 - 2) * 100)
                    / (float)(1000 + (minSpeedBefore_2 - 2) * 100);
                  hero_2->field_43 = minSpeedAfter_2;
                }
            }
    }
    else
    {
        CALL_5(void, __thiscall, h->GetDefaultFunc(), advM, cell, hero_1, cellX, cellY);
    }

    hero_1->mobility = CALL_1(int, __thiscall, 0x494BB0, hero_1);
    if(location == LOCATION_HERO)
    {
        hero_2->mobility = CALL_1(int, __thiscall, 0x494BB0, hero_2);
    }

}

int __stdcall setSlowestSpeedStartDay(LoHook* h, HookContext* c)
{
  hero* hero_1;
  int minSpeed;
  for ( int j = 0;  j < (*(game**)gpGame)->players[*(int*)giCurPlayer].numHeroes; ++j )
  {
    hero_1 = &(*(game**)gpGame)->heroes[(*(game**)gpGame)->players[*(int*)giCurPlayer].heroesOwned[j]];
    minSpeed = 7;
    for ( int i = 0; i < 5; ++i )
    {
      if ( hero_1->army.creatureTypes[i] != -1 && ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed < minSpeed )
        minSpeed = ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed;
    }
    hero_1->field_43 = minSpeed;
  }

  return EXEC_DEFAULT;

}

int __stdcall setSlowestSpeedStartGame(LoHook* h, HookContext* c)
{
  hero* hero_1;
  int minSpeed;
  for ( int j = 0;  j < MAX_HEROES; ++j )
  {
    hero_1 = &(*(game**)gpGame)->heroes[j];
    minSpeed = 7;
    for ( int i = 0; i < 5; ++i )
    {
      if ( hero_1->army.creatureTypes[i] != -1 && ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed < minSpeed )
        minSpeed = ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed;
    }
    hero_1->field_43 = minSpeed;
  }

  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("H2_HeroesMobilityChange");

            int check;

            // H2 Eng PoL 2.1
            check = *(int*)(0x484DC1+6);
            if(check == 0x14000000)
            {
                aTag_monsterInfo = 0x4F21F8;

                gpGame = 0x52477C;
                gpCurPlayer = 0x5306D0;
                gpTownManager = 0x5247C4;
                giCurPlayer = 0x5305D0;

                _PI->WriteHiHook(0x485EA0, SPLICE_, EXTENDED_, THISCALL_, HH_advM_DoEvent);
                _PI->WriteHiHook(0x413F80, SPLICE_, EXTENDED_, THISCALL_, HH_townManager_DoCommand);
                _PI->WriteHiHook(0x48F940, SPLICE_, EXTENDED_, THISCALL_, HH_advM_DoAIEvent);

                _PI->WriteLoHook(0x4240EA, setSlowestSpeedStartDay);
                _PI->WriteLoHook(0x4281D5, setSlowestSpeedStartGame);
            }

        }
    }

   return TRUE;
}
Последний раз редактировалось Ben80 10 авг 2023, 05:09, всего редактировалось 2 раз(а).
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5587
Зарегистрирован: 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)
Поблагодарили: 2185 раз.

Re: Герои 2 (разные версии) с плагинами

Сообщение AlexSpl » 09 авг 2023, 13:51

Цитата:
Плагин немедленно (а не в начале следующего хода) уменьшает количество MP героя, если ему передаются существа более медленные, чем самое медленное из существ, уже имевшихся у героя.

Ноги пересчёта MP после передачи войск герою растут из Героев 1. Так, вручив герою на горгулье гнома, получим скорость гнома. Это считалось багом, т.к. в следующих частях Героев расчёт уже идёт только в начале дня, и исправлено в TE, однако в оригинальной игре (от той же "Буки") его можно "пощупать".

Цитата:
Уменьшение количества MP пропорционально количеству MP героя на данный момент.

Считаю, что пропорциональное уменьшение - это лишнее. Каждый воин может преодолеть определённое расстояние в день, зависящее от его скорости, т.е. если передать герою с 2000 MP полного сил гнома, гном пройдёт 1000 MP и дальше его не заставишь идти: придётся устроить привал. Но то же самое случится и с героем, у которого 1100 MP: герой сможет пройти те же самые 1000 MP. Пропорциональное снижение в этом плане логически не обосновано.

По-хорошему, нужно делать, как в 4-ке: у каждого отряда должен быть свой запас хода. Например, подвезли герою с 2000 MP гнома, потратив 700 MP, всё, герой с гномом теперь только 300 MP пройти сможет (именно столько у гнома осталось MP после подвоза). Механика сложная, конечно. Например, если нам уставший гном мешает двигаться, мы можем ведь его уволить и продолжать движение с отрядами, которые ещё не устали. Логично? Вполне, но всё равно от микроменеджмента не убежать: в оригинале становишься на разгон, здесь - тупо не будешь брать с собой медленных юнитов вообще (или передавать/увольнять их после того, как у них закончились MP).
Вернуться к началу

Пред.След.

Вернуться в Техническая часть

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

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