Объявления

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

База данных IDA от void17

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5580
Зарегистрирован: 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)
Поблагодарили: 2184 раз.

Re: База данных IDA от void17

Сообщение AlexSpl » 23 ноя 2021, 01:44

Yes, but for now we haven't even started :smile1:
Вернуться к началу

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

Re: База данных IDA от void17

Сообщение AlexSpl » 23 ноя 2021, 02:34

Разобрал функцию:

Код: Выделить всё
double __thiscall army::get_unit_combat_value(const army *this, int a2, int a3, int shoot, int a5)
{
  char Shoot; // bl
  int adjusted_attack; // eax
  int adjusted_defense; // eax
  double AirShield_Multiplier; // st7
  int side; // eax
  hero *hero; // eax
  ECreatureType Type; // eax
  hero *hero_1; // eax
  int side0; // eax
  int v15; // edx
  int side1; // ecx
  int side2; // ecx
  int side3; // ecx
  int SpellDurationBless; // edx
  int MinDamage; // eax
  int MaxDamage; // ecx
  int *dmg; // eax
  signed int CurseDamage; // edx
  bool damage_zero; // cc
  FCreatureFlags Flags; // eax
  double k; // st7
  int army_current_health; // edi
  int army_health; // edx
  army *v29; // ecx
  int i; // esi
  int side4; // esi
  int side5; // ecx
  FCreatureFlags *p_Flags; // ecx
  int stack_full_health2; // eax
  double stack_full_health; // st7
  double multiplier1; // [esp+14h] [ebp-20h]
  double avg_damage; // [esp+1Ch] [ebp-18h]
  double multiplier; // [esp+24h] [ebp-10h]
  double damage; // [esp+24h] [ebp-10h]
  double fight_value_mod; // [esp+24h] [ebp-10h]
  double attack_mod; // [esp+2Ch] [ebp-8h]
  int delta_attack; // [esp+30h] [ebp-4h]

  adjusted_attack = army::get_adjusted_attack(this, 0, shoot);
  delta_attack = adjusted_attack - akCreatureTypeTraits[this->Type].Attack - a2;
  adjusted_defense = army::get_adjusted_defense(this, 0, 1);
  Shoot = shoot;
  multiplier = 1.0;
  a2 = adjusted_defense - akCreatureTypeTraits[this->Type].Defence - a3;
  if ( shoot )
  {
    if ( !this->SpellDuration[AIR_SHIELD] )
      goto SkipMultiplier;
    AirShield_Multiplier = this->AirShield_Multiplier;
  }
  else
  {
    if ( !this->SpellDuration[SHIELD] )
      goto SkipMultiplier;
    AirShield_Multiplier = this->Shield_Multiplier;
  }
  multiplier = AirShield_Multiplier;
SkipMultiplier:
  if ( this->SpellDuration[STONE] )
    multiplier = multiplier * 0.5;
  if ( this->SpellDuration[HYPNOTIZE] )
    side = 1 - this->Side;
  else
    side = this->Side;
  hero = gpCombatManager->Hero[side];
  if ( hero )
    multiplier = hero::GetDefenseFactor(hero) * multiplier;
  multiplier1 = (a2 * 0.05 + 1.0) * multiplier;
  if ( Shoot )
  {
    Type = this->Type;
    if ( Type != _BALLISTA_
      && Type != ARROW_TOWER
      && ((this->Flags & SHOOTER) == 0
       || this->Shots <= 0
       || ((hero_1 = gpCombatManager->Hero[combatMonster_GetSide(this)]) == 0
        || !hero::IsWieldingArtifact(hero_1, BOW_OF_THE_SHARPSHOOTER))
       && army::enemy_is_adjacent(this, 0)
       || this->SpellDuration[FORGETFULNESS] && this->ForgetfulnessLevel >= ADVANCED) )
    {
      Shoot = 0;
      LOBYTE(shoot) = 0;
    }
  }
  attack_mod = delta_attack * 0.05 + 1.0;
  if ( !Shoot && (this->Flags & SHOOTER) != 0 )
    attack_mod = attack_mod * 0.5;
  if ( this->Type == _BALLISTA_ )
  {
    v15 = this->SpellDuration[HYPNOTIZE];
    side0 = this->Side;
    side1 = v15 ? 1 - side0 : this->Side;
    if ( gpCombatManager->Hero[side1] )
    {
      if ( v15 )
        side2 = 1 - side0;
      else
        side2 = this->Side;
      if ( gpCombatManager->Hero[side2]->SecondarySkills[ARTILLERY] > 1 )
        attack_mod = attack_mod + attack_mod;
      if ( v15 )
        side3 = 1 - side0;
      else
        side3 = this->Side;
      attack_mod = attack_mod * ArtilleryEfficiency[gpCombatManager->Hero[side3]->SecondarySkills[ARTILLERY]];
    }
  }
  SpellDurationBless = this->SpellDuration[BLESS];
  if ( SpellDurationBless || this->SpellDuration[CURSE] )
  {
    MaxDamage = this->MaxDamage;
    MinDamage = this->MinDamage;
    a2 = MinDamage + MaxDamage;
    avg_damage = (MinDamage + MaxDamage) / 2.0;
    if ( SpellDurationBless )
    {
      a2 = MaxDamage + this->BlessDamage;
      damage = a2;
    }
    else if ( this->SpellDuration[CURSE] )
    {
      CurseDamage = this->CurseDamage;
      a2 = 1;
      a3 = MinDamage - CurseDamage;
      damage_zero = MinDamage - CurseDamage < 1;
      dmg = &a2;
      if ( !damage_zero )
        dmg = &a3;
      damage = *dmg;
    }
    else
    {
      damage = (MinDamage + MaxDamage) / 2.0;
    }
    Shoot = shoot;
    attack_mod = damage / avg_damage * attack_mod;
  }
  if ( Shoot && (this->Flags & DOUBLEATTACK) != 0 )
    attack_mod = attack_mod + attack_mod;
  k = sqrt(attack_mod * multiplier1);
  Flags = this->Flags;
  fight_value_mod = k * akCreatureTypeTraits[this->Type].Fight;
  if ( (Flags & (SUMMON|SIEGEWEAPON)) != 0 )
  {
    if ( (Flags & CLONE) != 0 )
      army_current_health = 1;
    else
      army_current_health = this->AmountAlive * this->Health - this->HealthLost;
    side4 = this->Side;
    army_health = 0;
    shoot = 0;
    side5 = side4;
    i = gpCombatManager->HeroArmySum[side4];
    v29 = gpCombatManager->TroopStacks[side5];
    if ( i > 0 )
    {
      p_Flags = &v29->Flags;
      do
      {
        if ( (*p_Flags & (SUMMON|CANNOTMOVE|SIEGEWEAPON)) == 0 )
        {
          if ( (*p_Flags & CLONE) != 0 )
            stack_full_health2 = 1;
          else
            stack_full_health2 = *(p_Flags - 14) * *(p_Flags + 15) - *(p_Flags - 11);
          army_health += stack_full_health2;
        }
        p_Flags += 0x152;
        --i;
      }
      while ( i );
      shoot = army_health;
    }
    if ( !army_current_health )
      return 0.1;
    stack_full_health = shoot;
    shoot = army_health + army_current_health;
    return stack_full_health * fight_value_mod / (army_health + army_current_health);
  }
  return fight_value_mod;
}

Это для примера. Названия переменных брал интуитивно, опираясь на игровой опыт. Вот это, конечно же, не мешало бы перевести в "хитпоинты": stack_full_health2 = *(p_Flags - 14) * *(p_Flags + 15) - *(p_Flags - 11); Но функция для примера и для небольшого обсуждения о том, что можно исправить, чтобы она выглядела лучше.
Вернуться к началу

offlineАватара пользователя
void_17  
имя: имя
Ветеран
Ветеран
 
Сообщения: 545
Зарегистрирован: 25 апр 2021, 15:05
Откуда: Оттуда
Пол: Мужчина
Поблагодарили: 129 раз.

Re: База данных IDA от void17

Сообщение void_17 » 23 ноя 2021, 02:48

Дискорд сервер
https://discord.gg/BrbwGNFYgP
Вернуться к началу

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

Re: База данных IDA от void17

Сообщение AlexSpl » 23 ноя 2021, 02:51

Короче, вот это return army_health_2 * fight_value_mod / (army_health + army_current_health); должно быть:

fight_value_mod / (1 + stack_current_health / army_current_health), если математически. Главное, не запутаться во всех этих присваиваниях переменных :smile1:

Цитата:
Дискорд сервер

Это лучше в первый пост, чтобы ссылка не потерялась.
Вернуться к началу

offlineRoseKavalier  
Мастер
Мастер
 
Сообщения: 331
Зарегистрирован: 23 сен 2017, 17:00
Пол: Не указан
Поблагодарили: 234 раз.

Re: База данных IDA от void17

Сообщение RoseKavalier » 23 ноя 2021, 03:02

Now that you are using IDA 7.6 (available since earlier, but was not well documented) it is time to learn about shifted pointers:
* right-click flags and click convert to struct ...
* select army or whatever you named it (I dislike army and armyGroup, I'm using CombatStack)
* enter 84 in Pointer shift value in the bottom left
Изображение
Much better:
 
Изображение
Вернуться к началу

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

Re: База данных IDA от void17

Сообщение AlexSpl » 23 ноя 2021, 03:09

And how to fight variables which mean the same thing (e.g. side, side0, side1, ...)? I hate them :smile26: Is there a way to name all of them just "Side" for the sake of human understanding?
Вернуться к началу

offlineRoseKavalier  
Мастер
Мастер
 
Сообщения: 331
Зарегистрирован: 23 сен 2017, 17:00
Пол: Не указан
Поблагодарили: 234 раз.

Re: База данных IDA от void17

Сообщение RoseKavalier » 23 ноя 2021, 03:15

Shift+F to force a new variable. (when the same variable is re-used for several meanings)
It still gets messy, but sometimes during decompilation it helps.

Duplicate names aren't possible sadly =\
Вернуться к началу

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

Re: База данных IDA от void17

Сообщение AlexSpl » 23 ноя 2021, 03:20

Also I hate when the compiler uses arguments (e.g. a2 in the example above) as variables. I guess it wouldn't do that if they were const. It's very confusing.
Вернуться к началу

offlineАватара пользователя
void_17  
имя: имя
Ветеран
Ветеран
 
Сообщения: 545
Зарегистрирован: 25 апр 2021, 15:05
Откуда: Оттуда
Пол: Мужчина
Поблагодарили: 129 раз.

Re: База данных IDA от void17

Сообщение void_17 » 23 ноя 2021, 03:25

AlexSpl писал(а):

And how to fight variables which mean the same thing (e.g. side, side0, side1, ...)? I hate them :smile26: Is there a way to name all of them just "Side" for the sake of human understanding?


Я обычно делаю так: Var, _Var, Var_, _Var_ и т.д.
Вернуться к началу

offlineАватара пользователя
void_17  
имя: имя
Ветеран
Ветеран
 
Сообщения: 545
Зарегистрирован: 25 апр 2021, 15:05
Откуда: Оттуда
Пол: Мужчина
Поблагодарили: 129 раз.

Re: База данных IDA от void17

Сообщение void_17 » 23 ноя 2021, 03:28

Цитата:
Дискорд сервер

Это лучше в первый пост, чтобы ссылка не потерялась.

А вы тоже присоединитесь к серверу :smile2:
Вернуться к началу

Пред.След.

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

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

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

cron