Объявления

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

Улучшение ИИ

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

Re: Улучшение ИИ

Сообщение Ben80 » 21 май 2021, 14:20

Я, конечно, тоже жалею, что юность не вернуть, как и все люди. Но мне интересно вспоминать и переосмысливать. Да, это другое. Но тогда вы не могли многое из того, что вы можете сейчас (в том числе, понимать какие-то вещи). Так что все не так уж плохо :smile1:
Вернуться к началу

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: Улучшение ИИ

Сообщение AlexSpl » 21 май 2021, 14:29

Да... Эх, а когда-то не догонял, как строить цепочки. Казалось каким-то недостижимым искусством :smile14: Есть, конечно, определённый фан в том, когда стараешься, чтобы всё срослось, и вот у тебя получилось. Это радость победы. Но оффлайн - это не совсем развлечение, это, можно сказать, работа. А хочется вернуть именно развлекающую составляющую :smile1: Поэтому мне так зашла серия KB: я за микс TBS и RPG.
Вернуться к началу

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: Улучшение ИИ

Сообщение AlexSpl » 21 май 2021, 15:10

Цитата:
Мне вот интересно, может кто в курсе: убрать накопление существ во внешних жилищах - это осознанное решение разрабов Тройки или может баг? Хотя багом это все же сложно назвать, но самое интересное, что ведь в Двойке и даже в Пятерке накопление существ во внешних жилищах то прекрасно работает. Зачем его в Тройке тогда убрали?

Самый ценный ресурс (в целом) - это армия. Обычно игрок ограничен приростом, а в двеллинге с накоплением можно получить 2-3 (а то и больше) прироста существ, что определённо склонит чашу весов в пользу игрока, который найдёт такой двеллинг раньше противника. Работает, как Дипломатия: заджойнив отряд существ (особенно бесплатно), можно быстро получить преимущество в развитии. А при ранней встрече это вообще критично. Так что, я думаю, это осознанное решение.

В Двойке нельзя ставить флаг над внешним жилищем. Кто первым нашёл, того и войска.
Вернуться к началу

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

Re: Улучшение ИИ

Сообщение Rolex » 21 май 2021, 18:07

AlexSpl писал(а):

Самый ценный ресурс (в целом) - это армия. Обычно игрок ограничен приростом, а в двеллинге с накоплением можно получить 2-3 (а то и больше) прироста существ, что определённо склонит чашу весов в пользу игрока, который найдёт такой двеллинг раньше противника.

Если копить существ всегда, даже в жилищах никому не принадлежащих, то я полностью с вами согласен. Но что мешало сделать, например, как в HotA, накопление только после захвата игроком жилища?
Вернуться к началу

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

Re: Улучшение ИИ

Сообщение Ben80 » 25 май 2021, 07:31

Поисследовал код для битв-симуляций ИИ. Уточнения структур выложил здесь viewtopic.php?f=56&t=532&start=23

Штука в том, что нет возможности постоянно использовать для ИИ автобитвы, поскольку ИИ также нужно оценивать последствия боя перед самим боем (и поскольку такие оценки делаются очень часто - автобитвы будут слишком накладны). Более того, если использовать для оценки слабый алгоритм, а затем применять в действительном бою более реалистичный, то возникает очень нехорошая разница (между желаемым для ИИ и действительным). Поэтому независимо от того, собираемся мы задействовать для ИИ автобитвы или не собираемся - все равно нам нужны качественные теоретические битвы (как в Двойке) или битвы-симуляции (как в Тройке).

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

Попозже выложу код на С++ для процедур, которые исследовал.

***

Код написал в виде гипотетических Хайхуков, способных заменить оригинальный код, правда, неполных, носящих чисто учебный характер. Наиболее интересна и сложна функция 0x4267C0 (AI_AICalcBattleSide_CheckIfNeedGoToMeeleeAttackNow) Я так понимаю, что там существа делают несколько шагов, чтобы подойти для схватки в рукопашную. Правда, есть ощущение, что пока они подходят, вражеские лучники не стреляют (единственное преимущество, что подходят то существа частями так сказать, поскольку скорость разная). Так что на память пришел текст из чэнджлогов HD мода, по поводу битв-симуляций - "неправдоподобно низкие потери в битве со стрелками" (а, нет, путаю, это из быстрых битв, тот багфикс я знаю). Все-таки, надо будет глянуть, было ли что-нибудь сделано в HD моде на этот счет. Если что-то и было сделано, то наверняка Савом. Эх, их бы энергию (а также знания и способности), да в благих целях... Но они захотели быть владельцами, а не хранителями...
Если у кого есть время/желание поисследовать функцию 0x4267C0, то велкам - это как раз недостающее звено. Можно было бы написать автору Физмиг или даже здесь статью.

Код: Выделить всё
int __stdcall HH_AI_CalcCreaturesDamaged(HiHook* h, _AI_SimulationBattle_Side_* battleSide, int damageValue, int a3)
{
   battleSide->armyStrength -= damageValue;
   if(battleSide->armyStrength > 0)
   {
      int result = CALL_4(int, __thiscall, 0x426170, battleSide, damageValue, 1, a3);
      if(result)
         result = CALL_4(int, __thiscall, 0x426170, battleSide, result, 0, 4);
   }
        else
        {
            // если армии нет - то дальше что-то там происходит
        }
   
   return 1;
}

double __stdcall HH_AI_CalcSummDamageVal(HiHook* h, _AI_SimulationBattle_Side_* battleSide, int turnsToEnemyActual, char noShooting)
{
   int stacksCount = CALL_1(int, __thiscall, 0x427750, battleSide);
      if(stacksCount <= 0)
         return 0;

   double damageValue = 0;

   for(int i=1; i<stacksCount; i++)
   {
      if(battleSide->creature[i].turnsToEnemy <= turnsToEnemyActual)
      {
         if(noShooting || battleSide->creature[i].turnsToEnemy)
            damageValue += battleSide->creature[i].creaturePower *
            battleSide->creature[i].count * battleSide->creature[i].meleePowerCoef;
         else
            damageValue += battleSide->creature[i].creaturePower *
            battleSide->creature[i].count * battleSide->creature[i].archeryPowerCoef;

      }

   }

   return (int)damageValue;
}

int __stdcall HH_AI_CheckNeedMeleeAttack(HiHook* h, _AI_SimulationBattle_Side_* battleSideActive, _AI_SimulationBattle_Side_* battleSidePassive, int someInt)
{
   int stacksCountActive = CALL_1(int, __thiscall, 0x427750, battleSideActive);
   if(stacksCountActive <= 0)
      stacksCountActive = someInt;
   else
   {
      for(int i=1; i<stacksCountActive; i++)
      {
         int turnsToEnemy = battleSideActive->creature[i].turnsToEnemy;
         if(turnsToEnemy != 0 && turnsToEnemy <= someInt && battleSideActive->creature[i].count > 0)
            break;
      }
   }

   if(stacksCountActive < 0)
      return 0;

   int someCrit = 4;
   if(someInt <= 4)
   {
      do
      {
         // копируем активную сторону в a2a
         
         // копируем пассивную сторону в Mon2Way

         if(someInt < someCrit)
         do
         {
            if(battleSideActive->armyStrength <= 0 || battleSidePassive->armyStrength <= 0)
               break;
            // далее вызываем процедуру для поиска макс. скорости стека актив. стороны
            //int maxSpeedActive = 10;
            // далее вызываем процедуру для поиска макс. скорости стека пассив. стороны
            //int maxSpeedPassive = 9;

            // Далее следует "непереводимая игра слов"
         }
         while(true);

      }
      while(true);
   }

   return 1;
}

int __stdcall HH_AI_VirtualBattle_Main(HiHook* h, _AI_SimulationBattle_Side_* battleSideA, _AI_SimulationBattle_Side_* battleSideD)
{
   bool isNeedMeleeAttack_A;
   bool isNeedMeleeAttack_D;
   int stacksCount_A;
   int maxCrSpeed_A;
   int maxCrSpeed_B;

   int someInt = 1;
   int someInt2 = 1;

   while(battleSideA->armyStrength > 0 && battleSideD->armyStrength > 0)
   {
      isNeedMeleeAttack_A = CALL_3(bool, __thiscall, 0x4267C0, battleSideA, battleSideD, someInt);
      isNeedMeleeAttack_D = CALL_3(bool, __thiscall, 0x4267C0, battleSideD, battleSideA, someInt);

      stacksCount_A = CALL_1(int, __thiscall, 0x427750, battleSideA);
      if(stacksCount_A > 0)
      {
         maxCrSpeed_A = battleSideA->creature[stacksCount_A - 1].speed;
         for(int i=1; i<stacksCount_A; i++)
         {
            if(battleSideA->creature[i].count > 0)
            if(battleSideA->creature[i].speed > maxCrSpeed_A)
               maxCrSpeed_A = battleSideA->creature[i].speed;
         }
      }

      // далее вызываем процедуру для поиска макс. скорости стека защищ. стороны

      if(maxCrSpeed_B > maxCrSpeed_A)
      {

      }
      else
      {

      }

   }

        // далее - код
   // на самом деле заканчивается вызовом процедуры, завершающей бой
   // она и возвращает что-то
    return 1;
}

int __stdcall HH_AI_VirtualBattleSide_Set_Stacks(HiHook* h, _AI_SimulationBattle_Side_* battleSide, float randomMult, _Hero_* heroEnemy)
{
   _Hero_* hero = battleSide->hero;
   battleSide->tactics = 0;
   if(hero)
      battleSide->tactics = hero->second_skill[HSS_TACTICS];

   int attack;
   int defense;
   int enemyAttack;
   int enemyDefense;
   int attackDelta;
   int defenseDelta;
   double heroPower = randomMult;
   double archeryPower;
   int speedArts;

   if(heroEnemy)
   {
      battleSide->tactics = hero->second_skill[HSS_TACTICS] - heroEnemy->second_skill[HSS_TACTICS];
      if(battleSide->tactics < 0)
         battleSide->tactics = 0;
   }

   if(hero)
   {
      attack = hero->attack;
      defense = hero->defence;
      attackDelta = attack;
      defenseDelta = defense;

      if(heroEnemy)
      {
         int attackDelta = attack - enemyDefense;
         if(attackDelta < 0)
            attackDelta = 0;

         int defenseDelta = enemyAttack - defense;
         if(defenseDelta < 0)
            defenseDelta = 0;

         heroPower *= sqrt(1.0 + 0.05 * defenseDelta) * sqrt(1.0 + 0.05 * attackDelta);
      }
   }

   if(hero)
      archeryPower = CALL_1(double, __thiscall, 0x4E43D0, hero) / 5.0;
   else
      archeryPower = 0.2;

   if(hero)
      speedArts = CALL_1(int, __thiscall, 0x4E5D10, hero);
   else
      speedArts = 0;

   int armyStrength = 0;

   for(int i=0; i<7; i++)
   {
      int crId = battleSide->army->type[i];

      if(crId != -1)
      {
         int crHP;
         int crSpeed;
         int turnsToEnemy;
         crHP = o_pCreatureInfo[crId].hit_points;
         if(hero)
         {
            crHP += CALL_2(int, __thiscall, 0x4E5DF0, hero, crId);
         }

         crSpeed = speedArts + o_pCreatureInfo[crId].speed;
         int crFlags = o_pCreatureInfo[crId].flags;
         int crNumber = battleSide->army->count[i];
         double hpMult = sqrt((double)crHP / (double)o_pCreatureInfo[crId].hit_points);
         int crPower = heroPower * hpMult * o_pCreatureInfo[crId].fight_value;
         int stackPower = crPower * crNumber;

         if(!(crFlags & BCF_CAN_SHOOT))
         {
            turnsToEnemy = (crSpeed + 2 * (7 - battleSide->tactics)) / crSpeed;
            if(turnsToEnemy > 4)
               turnsToEnemy = 4;
            if(battleSide->restrictionMovementLevel > turnsToEnemy)
            {
               if(!(crFlags & BCF_CAN_FLY))
                  turnsToEnemy = battleSide->restrictionMovementLevel;
            }
         }
         else
         {
            turnsToEnemy = 0;
         }

         double coef_1 = 0.2;
         double coef_2 = 1.0;
         double power_per_hp = (double)crPower / (double)crHP;

         if(turnsToEnemy == 0)
         {
            if(!(crFlags & BCF_NO_MELEE_PENALTY))
            {
               coef_1 = 0.1;
               coef_2 = 0.7;
            }

            if(!(crFlags & BCF_ATTACK_TWICE))
            {
               archeryPower *= 2;
            }

            if(battleSide->isRestrictedMovement)
               if (crId != CID_ARCH_MAGE)
                  archeryPower /= 2;
         }

         int crEndMem = (int)battleSide->creature.EndData;
         //void* p1 =
         //void* p0 =
         battleSide->armyStrength += crPower * crNumber;

         // заполняются параметры существа _AISimulationCreature_
         // Вызов функции для выделения памяти под список существ
         // _List_<_AISimulationCreature_> creature

         // Сортировка стеков
      }
   }

    return 1;
}

void __stdcall HH_AI_VirtualBattleSide_SetTownInfo(HiHook* h, _AI_SimulationBattle_Side_* battleSide, _Town_* town)
{
   battleSide->isRestrictedMovement = 0;
   battleSide->restrictionMovementLevel = 0;

   bool isFortBuilt;
   bool isCitadelBuilt;
   bool isCastleBuilt;

   // заполняем значения
   // isFortBuilt;
   // isCitadelBuilt;
   // isCastleBuilt;

   if(town)
   {
      if(isFortBuilt)
      {
         battleSide->isRestrictedMovement = 1;
         battleSide->restrictionMovementLevel = 4;
      }

      if(isCitadelBuilt)
      {
         battleSide->isRestrictedMovement = 1;
         battleSide->restrictionMovementLevel = 5;
      }

      if(isCastleBuilt)
      {
         battleSide->isRestrictedMovement = 1;
         battleSide->restrictionMovementLevel = 6;
      }

      _Hero_* hero = battleSide->hero;
      if(hero)
      {
         if(hero->spell_level[SPL_EARTHQUAKE])
         {
            battleSide->isRestrictedMovement = 0;
            battleSide->restrictionMovementLevel = 0;
         }

         if(battleSide->restrictionMovementLevel > 0)
         {
            battleSide->restrictionMovementLevel -= hero->second_skill[HSS_BALLISTICS];
            if(battleSide->restrictionMovementLevel > 2)
               battleSide->restrictionMovementLevel = 2;
         }
      }

      if(battleSide->restrictionMovementLevel > 4)
         battleSide->restrictionMovementLevel = 4;
   }
}

_AI_SimulationBattle_Side_* __stdcall HH_AI_VirtualBattleSide_Create(HiHook* h, _AI_SimulationBattle_Side_* battleSide, _Hero_* hero, _Army_* army, float randomMult, _Hero_* heroEnemy, _Town_* town, _MapItem_* mi)
{
   battleSide->army = army;
   battleSide->hero = hero;

   // AI_VirtualBattleSide_SetTownInfo
   CALL_2(void, __thiscall, 0x424790, battleSide, town);

   battleSide->heroEnemy = heroEnemy;

   if(battleSide->hero)
      battleSide->spellPoints = hero->spell_points;

   battleSide->canCastSpells = 1;

   if(!hero || !hero->DoesWearArtifact(AID_SPELL_BOOK) || hero->DoesWearArtifact(AID_ORB_OF_INHIBITION))
      battleSide->canCastSpells = 0;

   battleSide->specialTerrain = -1;

   // Код устанавливающий specialTerrain и canCastSpell

   if(battleSide->heroEnemy->DoesWearArtifact(AID_ORB_OF_INHIBITION))
      battleSide->canCastSpells = 0;

   // AI_VirtualBattleSide_Set_Stacks
   CALL_3(int, __thiscall, 0x426BC0, battleSide, randomMult, heroEnemy);

    return battleSide;
}

...

_PI->WriteHiHook(0x423EE0, SPLICE_, EXTENDED_, THISCALL_, HH_AI_VirtualBattleSide_Create);
_PI->WriteHiHook(0x424120, SPLICE_, EXTENDED_, THISCALL_, HH_AI_VirtualBattleSide_Set_Stacks);
_PI->WriteHiHook(0x424790, SPLICE_, EXTENDED_, THISCALL_, HH_AI_VirtualBattleSide_SetTownInfo);

_PI->WriteHiHook(0x426300, SPLICE_, EXTENDED_, THISCALL_, HH_AI_CalcCreaturesDamaged);   
_PI->WriteHiHook(0x426390, SPLICE_, EXTENDED_, THISCALL_, HH_AI_CalcSummDamageVal);
_PI->WriteHiHook(0x4267C0, SPLICE_, EXTENDED_, THISCALL_, HH_AI_CheckNeedMeleeAttack);
_PI->WriteHiHook(0x426BC0, SPLICE_, EXTENDED_, THISCALL_, HH_AI_VirtualBattle_Main);

Последний раз редактировалось Ben80 25 май 2021, 19:13, всего редактировалось 1 раз.
Вернуться к началу

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

Re: Улучшение ИИ

Сообщение Ben80 » 25 май 2021, 16:52

Одной из самых дизбалансных штуковин в игре справедливо считается экспертное Замедление. Это заклинание в большинстве случаев сильнее любого боевого заклинания 5-го уровня.
К сожалению, разработчики не учли, что существа под Замедлением теряют не только в скорости, но и в интеллекте, и это, возможно, даже критичнее, чем потеря скорости. Поэтому идеи на этот счет, возникающие в различных модах, можно только приветствовать. Одной из лучших идей на этот счет является идея с округлением вверх, а не вниз (как в оригинале) для продвинутого и экспертного Замедления. Вот, кстати, код для этого:

Код: Выделить всё
int __stdcall correctSlow_1(LoHook* h, HookContext* c)
{
   if(*(float*)(c->esi + 0x4C8) < 0.5001)
      c->eax = (*(float*)(c->ebp - 8) + 1) * *(float*)(c->esi + 0x4C8);

    return EXEC_DEFAULT;
}

int __stdcall correctSlow_2(LoHook* h, HookContext* c)
{
   if(*(float*)(c->esi + 0x4C8) < 0.5001)
      c->eax = (*(int*)(c->ebp - 4) + 1) * *(float*)(c->esi + 0x4C8);

   c->return_address += 0x14;
    return NO_EXEC_DEFAULT;
}

int __stdcall correctSlow_3(LoHook* h, HookContext* c)
{
   if(*(float*)(c->ecx + 0x4C8) < 0.5001)
      c->eax = (*(float*)(c->ebp - 4) + 1) * *(float*)(c->ecx + 0x4C8);

    return EXEC_DEFAULT;
}
...
// Продвинутая и экспертная Медлительность - округление вверх
_PI->WriteLoHook(0x441D0A, correctSlow_1);
_PI->WriteLoHook(0x441E2D, correctSlow_1);
_PI->WriteLoHook(0x44858D, correctSlow_2);
_PI->WriteLoHook(0x4485D5, correctSlow_2);
_PI->WriteLoHook(0x448624, correctSlow_1);
_PI->WriteLoHook(0x4486A2, correctSlow_1);
_PI->WriteLoHook(0x448A2E, correctSlow_3);
Вернуться к началу

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

Re: Улучшение ИИ

Сообщение Rolex » 25 май 2021, 17:45

Ben80 писал(а):

К сожалению, разработчики не учли, что существа под Замедлением теряют не только в скорости, но и в интеллекте, и это, возможно, даже критичнее, чем потеря скорости.

Не совсем понял, а что в данном случае Вы подразумеваете под интеллектом?
Вернуться к началу

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

Re: Улучшение ИИ

Сообщение Ben80 » 25 май 2021, 17:53

Я, видимо, недостаточно правильно выразился (пытался сказать коротко и емко). А имел в виду особенности поведения существ под управлением ИИ в бою. Приоритетом ИИ при атаке врукопашную является количество ходов до цели. Поэтому чем медленнее монстр под управлением ИИ, тем легче мало-мальски сведущему игроку его дурачить (пока он бегает туда-сюда, его, например, просто расстреливают). Если рассматривать оригинальный ИИ, то существа со скоростью 4 и меньше в этом плане очень уязвимы. Есть код, который изрядно помогает медленным ИИ существам - в теме плагинов выложен Battle_AI, к которому у меня сейчас есть большое дополнение. Но в оригинальной игре есть настолько тяжелые случаи (например, Дендроиды, Гномы, Зомби, Големы, скорость которых может упасть до единицы), что никакие интеллектуальные примочки и компрессы не помогут. А вот округление Замедления вверх - поможет.
Вернуться к началу

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

Re: Улучшение ИИ

Сообщение Rolex » 25 май 2021, 19:38

По-моему, округление вверх для Замедления сделано и в HotA. А есть ли какие-то различия в работе с вашим кодом?
HotA писал(а):

Продвинутая и экспертная Медлительность уменьшает скорость по формуле ((старая скорость x 0,5) + 1), округление вниз.
Вернуться к началу

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

Re: Улучшение ИИ

Сообщение Ben80 » 25 май 2021, 19:50

Различий, пожалуй, нет.

Но такая формула - отнюдь не ноу-хау Хоты. Впервые, пожалуй, я такое увидел в тн Джебус-моде https://forum.df2.ru/index.php?showtopic=36605&st=0 которому помог случиться ваш наставник в кодинге AlexSpl.

А когда познакомился с Двойкой, узнал что еще там такое использовалось, в очень древние времена.
Можете в этом убедиться здесь https://handbookhmm.ru/2-spells

***

Кстати, именно просмотр темы с Джебус-модом на ДФ форуме привел меня к мысли, что AlexSpl - тот человек, который может помочь с моддингом для Героев. Первоначально я пытался списаться по скайпу с программистом HotA с ником Sav, который мне написал, что он не занимается обучением программированию под Героев, но изредка может отвечать на какие-то вопросы. Я, конечно, немного расстроился, хотя позднее, узнав политику Хоты, понял, что тот ответ мне был более чем доброжелательным.

***

Хотя вообще-то, тут интересный момент. Я думал, у них такая формула
Цитата:
(Скорость + 1) / 2

потому что если такая
Цитата:
((старая скорость x 0,5) + 1)

то это конечно, совсем другой коленкор. Может, у них на сайте формула неправильно написана ? Потому что по ней выходит, что существо со скоростью 4 после продвинутого/экспертного замедления будет иметь скорость 3.
А по формуле Двойки или по моей формуле должно иметь скорость 2.
Вернуться к началу

Пред.След.

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

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

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