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

Full Version: Исследование героев
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Тогда надо писать методы для доступа к каждому полю. Мне не жалко того, что структура объекта открыта, я бы и код открыл, если бы он содержал только мои исследования (кстати, адреса устанавливающихся хуков можно считать открытыми - их элементарно посмотреть извне, используя patcher_x86). Пусть пользователь делает с объектом что хочет, а о том, что трогать не надо, я предупредил, и эти поля объявлены как private. Или закрытость структуры должна быть более удобной пользователю? В этом случае сделаю так.
В текущем варианте ты ограничил применение языком Си++. К другим даже обёртки не сделать.
Т. е. чтобы не ограничивать надо обязательно создать такие функции? Хорошо, тогда я сделаю это.
Да. Тогда я их прямо экспортирую в целевом языке программирования и используя, абсолютно не интересуясь двоичной структурой объекта (для меня это указатель).
solitaire345 Wrote:I found a table which holds setup of arrow towers. It is located at 0x63CF88 and stores the following values:

Code:
00000000 CreatureID      dd ?                    ; base 10
00000004 MainTowerX      dd ?                    ; base 10
00000008 MainTowerY      dd ?                    ; base 10
0000000C LowTowerX       dd ?                    ; base 10
00000010 LowTowerY       dd ?                    ; base 10
00000014 UpTowerX        dd ?                    ; base 10
00000018 UpTowerY        dd ?                    ; base 10
0000001C MissileName  dd ?                    ; offset (00000000)

Here's a function to change graphics of any town. The paremeters are:
x1 - town type; x2 - shooter ID; x3-x8 - X; Y coordinates for turrets (middle, lower, upper); x9 - pointer to missile def.

A value of -1 means "do not change"

Code:
!?FU1;
!!FU&x1<0|x1>8:E;
!!VRv1:S4*8*x1+6541192; 0x63CF88

!!if&x2<>-1;
  !!MA:Xx2/?v2;
  !!VRv2:&4;
  !!IF&v2<>4:M^Trying to set nonshoting creature as arrow tower. Exiting to avoid crash^;
  !!FU&v2<>4:E;
  !!UN:Cv1/4/x2;
!!en;
!!VRv1:+4; !!UN&x3<>-1:Cv1/4/x3;
!!VRv1:+4; !!UN&x4<>-1:Cv1/4/x4;
!!VRv1:+4; !!UN&x5<>-1:Cv1/4/x5;
!!VRv1:+4; !!UN&x6<>-1:Cv1/4/x6;
!!VRv1:+4; !!UN&x7<>-1:Cv1/4/x7;
!!VRv1:+4; !!UN&x8<>-1:Cv1/4/x8;
!!VRv1:+4; !!UN&x9<>-1:Cv1/4/x9;

The pointers to missile names (parameter 9) are these (use numbers from the first column):

Code:
6686972 (0x6608FC) titan's bolt
6686984 (0x660908) Ice elemental's shard
6686996 (ox660914) Mage's missile
6687008 (0x660920) Catapult's rock
6687020 (0x66092C) Ballista's bolt
6687032 (0x660938) lizardman's arrow
6687044 (0x660944) Cyclop's boulder
6687056 (0x660950) orc's axe
6687068 (0x66095C) Medusa's arrow
6687080 (0x660968) lich's missile
6687092 (0x660974) Gog's fireball
6687104 (0x660980) Halfling's stone
6687116 (0x66098C) Gremlin's ball
6687128 (0x660998) Elf's arrow
6687140 (0x6609A4) Zealot's missile
6687152 (0x6609B0) Crosbowman's arrow
8002324 (0x7A1B14) Dracolich's missile

Notes:
1. There is no backup, so once changed, the setup will remain until h3era.exe is restarted.
2. Changing creature does not affect the power of arrow towers.
3. Using this function after BA0 trigger will have no effect in battle, because that table is copied to temporary location for the duration of combat.
4. creature images are cropped, so some creatures will look wrong (like this).
solitaire345 Wrote:0x642EA0 - Table of creatures displayed in blacksmith screen. Gold cost is also taken from that creature.
0x6AAA60 - Table of artifacts that are sold in blacksmith. Stangely this table has two ints per town (second is always -1 and changing it has no effect).
63BD18 - таблица урона от рвов.

Code:
5a7bf0 - расчёт урона от заклинания
  базовый урон: включает силу магии и уровень навыка,
  номер заклинания,
  структура колдующего героя,
  структура героя монстра или 0,
  структура целевого монстра,
  одиночная выборочная цель? (0, 1)
ecx = combat manager
fastcall
44A1A0 (spell, creature id, resist table?, 0)


Code:
thiscall (combatman)
Получить спротивление как у Гномов
5a83a0 (заклинание, 0, структура монстра, 0, 1, 0): сопротивление (0.0..1.0)
Берс, а ты отписываешься здесь каждый раз, когда что-то находишь или отбираешь по каким-то приципам? Просто многие из этих, смежных, да и вообще различных функций мной исследованы, но я не знаю, есть ли какой-то толк их выкладывать.
Да, если нахожу что-то по просьбе или для Эры.
Толк есть. В своё время я все сообщения обошёл, вычленяя то, что можно использовать или довести до ума.
Одна из самых мозговыносящих геройских функций, понять которые с первого взгляда абсолютно невозможно, а потому она у меня очень подробно разобрана. Это функция проигрывания анимации урона стеков (при этом одновременно проигрывается анимация атакующего и боевая анимация при необходимости). Единственный урон, проигрывающийся не этой функцией - армагеддон.
Так же в этой функции накладываются заклинания, которые существа накладывают после атаки.

Стрельба и удар по всем гидр, как я помню, тоже другими проигрываются.
Я перепроверю, но вроде тем же. Анимация самого выстрела проигрывается отдельно, а вот получения урона от него - этим.
Sav, нехило 118
Посмотрел, DrawAction_Play вызывается и для любого удара, и для стрельбы.

Удар (Enemy_Gex_Around_Stack - номер атакуемого гекса вокруг стека - т. е. 0-6 (0-8), с учётом того, что гексы, окружающие стек, пронумерованы по определённому принципу):
PHP Code:
char __thiscall A0_Battle_Stack_MakeHit_sub_441330(_BattleStack_ *this, _BattleStack_ *Enemy, int Enemy_Gex_Around_Stack)
{
  
int Enemy_Gex_Around_Stack_v3; // ebx@1
  
_BattleStack_ *this_v4; // esi@1
  
char v5; // al@6
  
char v6; // zf@6
  
int v7; // edx@7
  
int v8; // edi@9
  
int v9; // edx@10
  
signed int SomeGexNum_v10; // eax@14
  
signed int EnemyGex_Num_v11; // eax@14
  
_BattleStack_ *GexStack_v12; // eax@16
  
int v13; // ebx@20
  
int v14; // edi@20
  
_BattleMgr_ *BattleMgr_v15; // ebx@23
  
int v16; // eax@24
  
signed int *v17; // ebx@25
  
int v18; // eax@29
  
unsigned int v19; // edx@31
  
_BattleStack_ *v20; // ebx@32
  
_BattleStack_ *Enemy_v21; // edi@32
  
int v22; // ecx@33
  
int v23; // edi@33
  
int v24; // ebx@37
  
int v25; // edi@37
  
signed int v26; // eax@41
  
_BattleStack_ *Enemy_v27; // eax@44
  
int Damage_v28; // eax@45
  
int v29; // eax@49
  
int v30; // eax@50
  
void *v31; // eax@59
  
void *v32; // eax@66
  
void *v33; // eax@72
  
int v34; // eax@82
  
char *Attacker_Name_v35; // eax@85
  
int Attacker_type_v36; // eax@89
  
char result; // al@100
  
int Attacker_count_v38; // [sp-10h] [bp-40h]@88
  
int v39; // [sp-Ch] [bp-3Ch]@3
  
int Damage_v40; // [sp-Ch] [bp-3Ch]@88
  
int Type_v41; // [sp-8h] [bp-38h]@3
  
_BattleStack_ *Enemy_v42; // [sp-8h] [bp-38h]@88
  
int Dead_v43; // [sp-4h] [bp-34h]@88
  
signed int a5; // [sp+Ch] [bp-24h]@9
  
int v45; // [sp+10h] [bp-20h]@25
  
int v46; // [sp+14h] [bp-1Ch]@31
  
_BattleStack_ *Enemy_v47; // [sp+18h] [bp-18h]@31
  
int v48; // [sp+1Ch] [bp-14h]@5
  
signed int a3; // [sp+20h] [bp-10h]@31
  
int Num; // [sp+24h] [bp-Ch]@31
  
_BattleStack_ *DragonBreathAttackedStack_v51; // [sp+28h] [bp-8h]@1
  
char v52; // [sp+2Fh] [bp-1h]@6

  
this_v4 = this;
  
DragonBreathAttackedStack_v51 = 0;
  
A0_Battle_ClearStacksWereHitted_sub_465BC0(A0_BattleMgr_dword_699420);
  
Enemy_Gex_Around_Stack_v3 = Enemy_Gex_Around_Stack;
  if ( (
this_v4->Creature_29dword74.Flags_dword10 >> 19) & 1 )// Атакует всех врагов вокруг
  
{
    if ( 
this_v4->Spells_Lengths_adword198[59] )// Берсерк
    
{
      
Type_v41 = 2;
      
v39 = this_v4->GexNum_dword38;
    }
    else
    {
      
Type_v41 = 1;
      
v39 = this_v4->GexNum_dword38;
    }
    
v48 = sub_524010(this_v4, v39, Type_v41, -1);
    if ( 
this_v4->CreatureType_dword34 == 47 )  // Цербер
    
{
      
v5 = this_v4->Creature_29dword74.Flags_dword10 & 1;
      
v6 = (this_v4->Creature_29dword74.Flags_dword10 & 1) == 0;
      
v52 = this_v4->Creature_29dword74.Flags_dword10 & 1;
      if ( 
v6 )
      {
        
v7 = (Enemy_Gex_Around_Stack_v3 + 5) % 6;
        
v5 = v52;
      }
      else
      {
        
v7 = dword_660898[(dword_660878[Enemy_Gex_Around_Stack_v3] + 7) % 8];
      }
      
a5 = 1;
      
v8 = ~(1 << v7) & (unsigned __int8)~(unsigned __int8)(1 << Enemy_Gex_Around_Stack_v3);
      if ( 
v5 )
        
v9 = dword_660898[(dword_660878[Enemy_Gex_Around_Stack_v3] + 1) % 8];
      else
        
v9 = (Enemy_Gex_Around_Stack_v3 + 1) % 6;
      
v48 |= v8 & ~(1 << v9);
    }
  }
  else
  {
    
Enemy->IsTarget_OfNonRoundHit_byteF0 = 1;
    if ( (
this_v4->Creature_29dword74.Flags_dword10 >> 3) & 1 )// Атакующий стек обладает драконьим дыханием
    
{
      
EnemyGex_Num_v11 = A0_Battle_Stack_Get_AroungGexNum_sub_5242E0(
                           
this_v4,
                           
this_v4->GexNum_dword38,
                           
Enemy_Gex_Around_Stack_v3);
      
SomeGexNum_v10 = sub_524280(this_v4, EnemyGex_Num_v11, Enemy_Gex_Around_Stack_v3);
      if ( 
SomeGexNum_v10 >= 0 )
      {
        if ( 
SomeGexNum_v10 < 187 )
        {
          
GexStack_v12 = A0_Battle_get_StackByGex_sub_4E7230((int)&A0_BattleMgr_dword_699420->hex[SomeGexNum_v10]);
          
DragonBreathAttackedStack_v51 = GexStack_v12;
          if ( 
GexStack_v12 )
          {
            if ( 
GexStack_v12->IsTarget_OfNonRoundHit_byteF0 )
              
DragonBreathAttackedStack_v51 = 0;
            else
              
GexStack_v12->IsTarget_OfNonRoundHit_byteF0 = 1;
          }
        }
      }
    }
  }
  
A0_Battle_ClearRedrawNeeds_sub_493290(A0_BattleMgr_dword_699420);
  
v14 = this_v4->Owner_dwordF4;
  
v13 = this_v4->StackNum_dwordF8;
  if ( 
A0_BattleMgr_dword_699420->stack[0][v13 + 14 * v14 + 7 * v14].CreatureType_dword34 == 149 )// Стрелковая башня
    
A0_Battle_SetArrowTowerRedraw_sub_46A040(
      
A0_BattleMgr_dword_699420,
      (
_BattleStack_ *)A0_BattleMgr_dword_699420->stack + v13 + 14 * v14 + 7 * v14);
  else
    *(&
A0_BattleMgr_dword_699420->field_0[4 * (5 * v14 + 20480)] + v13) = 1;
  
this_v4->CurrAttack_Is_Lucky_dword70 = 0;
  
BattleMgr_v15 = A0_BattleMgr_dword_699420;
  if ( 
A0_BattleMgr_dword_699420->hero[A0_Battle_Stack_Get_Controller_sub_43FE60(this_v4)] )
  {
    
v16 = this_v4->Luck_dword4EC;
    if ( 
v16 > 0 )
    {
      
v45 = this_v4->Luck_dword4EC;
      
a5 = 3;
      
v17 = &a5;
      if ( 
v16 <= 3 )
        
v17 = &v45;
      if ( 
A0_Rand_Int_sub_50C7C0(1, 24) <= *v17 )
      {
        
this_v4->CurrAttack_Is_Lucky_dword70 = 1;
        if ( !
A0_Battle_ShouldNotRenderBattle_sub_46A080((int)A0_BattleMgr_dword_699420) )
        {
          
A0_StartAndPlaySample_Parallel_sub_59A890("goodluck.82m", -1, 3);
          
v18 = (int)A0_Get_CreatureName_by_Type_adn_Count_sub_43FE20(
                       
this_v4->CreatureType_dword34,
                       
this_v4->Count_dword4C);
          
sprintf((int)A0_TempText_unk_697428, *(char **)(*((_DWORD *)off_6A5DC4 + 8) + 184), v18);
          
A0_Battle_MessageToLog_sub_4729D0(A0_BattleMgr_dword_699420->dlg, A0_TempText_unk_697428, 1, 0);
          
A0_Battle_Play_Std_BattleAnimation_sub_4963C0(A0_BattleMgr_dword_699420, 18, this_v4, 100, 0);
        }
      }
      
BattleMgr_v15 = A0_BattleMgr_dword_699420;
    }
  }
  
v19 = this_v4->Creature_29dword74.Flags_dword10;
  
a3 = 0;
  
Num = 0;
  
v45 = 0;
  
v46 = 0;
  
Enemy_v47 = 0;
  
a5 = 0;
  if ( (
v19 >> 19) & 1 )
  {
    
A0_Battle_Stack_RoundHit_MakeDamage_sub_440030(this_v4, v48, &a3, &Num, (int)&Enemy_v47);
    
Enemy_v21 = Enemy;
    
v20 = DragonBreathAttackedStack_v51;
  }
  else
  {
    
v23 = Enemy->Owner_dwordF4;
    
v22 = Enemy->StackNum_dwordF8;
    if ( 
BattleMgr_v15->stack[0][v22 + 14 * v23 + 7 * v23].CreatureType_dword34 == 149 )
      
A0_Battle_SetArrowTowerRedraw_sub_46A040(
        
BattleMgr_v15,
        (
_BattleStack_ *)BattleMgr_v15->stack + v22 + 14 * v23 + 7 * v23);
    else
      *(&
BattleMgr_v15->field_0[4 * (5 * v23 + 20480)] + v22) = 1;
    if ( 
DragonBreathAttackedStack_v51 )
    {
      
v25 = DragonBreathAttackedStack_v51->Owner_dwordF4;
      
v24 = DragonBreathAttackedStack_v51->StackNum_dwordF8;
      if ( 
A0_BattleMgr_dword_699420->stack[0][v24 + 14 * v25 + 7 * v25].CreatureType_dword34 == 149 )
        
A0_Battle_SetArrowTowerRedraw_sub_46A040(
          
A0_BattleMgr_dword_699420,
          (
_BattleStack_ *)A0_BattleMgr_dword_699420->stack + v24 + 14 * v25 + 7 * v25);
      else
        *(&
A0_BattleMgr_dword_699420->field_0[4 * (5 * v25 + 20480)] + v24) = 1;
    }
    
Enemy_v21 = Enemy;
    if ( (
Enemy->Creature_29dword74.Flags_dword10 >> 23) & 1 )
      
v26 = 1;
    else
      
v26 = Enemy->Count_dword4C * Enemy->Creature_29dword74.Health_dword4C - Enemy->HealthLoses_dword58;
    
a5 = v26;
    
Enemy = 0;
    if ( 
Enemy_v21 )
    {
      
Damage_v28 = A0_Battle_Stack_CalcDamage_sub_442E80((int)this_v4, 0);
      
a3 = A0_Battle_Stack_CalcDamageModifs_sub_443C60(
             
this_v4,
             
Enemy_v21,
             
Damage_v28,
             
0,
             
0,
             
this_v4->GexesWay_Length_dword490,
             (
int *)&Enemy);
      
Num = A0_Battle_Stack_MakeDamage_sub_443DB0(Enemy_v21, a3);
      
Enemy_v27 = Enemy;
      
this_v4->CurrAttack_Is_Lucky_dword70 = 0;
    }
    else
    {
      
Enemy_v27 = 0;
    }
    
Enemy_v47 = Enemy_v27;
    if ( (
signed int)Enemy_v27 > 0 )
      
Enemy_v21->CurrHit_WasDamagedByFireshield_byteE8 = 1;
    
v20 = DragonBreathAttackedStack_v51;
    if ( 
DragonBreathAttackedStack_v51 )
    {
      
Enemy = 0;
      
v29 = A0_Battle_Stack_CalcDamage_sub_442E80((int)this_v4, 0);
      
v45 = A0_Battle_Stack_CalcDamageModifs_sub_443C60(
              
this_v4,
              
v20,
              
v29,
              
0,
              
0,
              
this_v4->GexesWay_Length_dword490,
              (
int *)&Enemy);
      
v46 = A0_Battle_Stack_MakeDamage_sub_443DB0(v20, v45);
      
this_v4->CurrAttack_Is_Lucky_dword70 = 0;
    }
  }
  
A0_Battle_Set_RedrawBorders_sub_495770((int)A0_BattleMgr_dword_699420);
  
v30 = this_v4->CreatureType_dword34;
  
this_v4->CurrDrawAct_IsAttacker_byte0 = 1;
  if ( 
v30 == 110 || v30 == 111 || A0_Battle_ShouldNotRenderBattle_sub_46A080((int)A0_BattleMgr_dword_699420) )// Гидра, гидра хаоса.
    
goto LABEL_78;
  if ( 
Enemy_Gex_Around_Stack != 6 && Enemy_Gex_Around_Stack != 5 && Enemy_Gex_Around_Stack )
  {
    if ( 
Enemy_Gex_Around_Stack != 1 && Enemy_Gex_Around_Stack != 4 )
    {
      if ( 
v20 && (v31 = this_v4->Def_dword164, *((_DWORD *)v31 + 10) > 19) && *(_DWORD *)(*((_DWORD *)v31 + 11) + 76) )
      {
        
this_v4->CurrDrawAct_AttackAnimFrameSection_byte2 = 19;
      }
      else
      {
        if ( 
this_v4->CreatureType_dword34 == 146 )// Баллиста.
          
this_v4->CurrDrawAct_AttackAnimFrameSection_byte2 = 16;
        else
          
this_v4->CurrDrawAct_AttackAnimFrameSection_byte2 = 13;
      }
      goto 
LABEL_79;
    }
    if ( 
v20 )
    {
      
v32 = this_v4->Def_dword164;
      if ( *((
_DWORD *)v32 + 10) > 18 )
      {
        if ( *(
_DWORD *)(*((_DWORD *)v32 + 11) + 72) )
        {
          
this_v4->CurrDrawAct_AttackAnimFrameSection_byte2 = 18;
          goto 
LABEL_79;
        }
      }
    }
    if ( 
this_v4->CreatureType_dword34 == 146 ) // Баллиста.
    
{
      
this_v4->CurrDrawAct_AttackAnimFrameSection_byte2 = 15;
      goto 
LABEL_79;
    }
LABEL_78:
    
this_v4->CurrDrawAct_AttackAnimFrameSection_byte2 = 12;
    goto 
LABEL_79;
  }
  if ( 
v20 && (v33 = this_v4->Def_dword164, *((_DWORD *)v33 + 10) > 17) && *(_DWORD *)(*((_DWORD *)v33 + 11) + 68) )
  {
    
this_v4->CurrDrawAct_AttackAnimFrameSection_byte2 = 17;
  }
  else
  {
    if ( 
this_v4->CreatureType_dword34 == 146 ) // Баллиста.
      
this_v4->CurrDrawAct_AttackAnimFrameSection_byte2 = 14;
    else
      
this_v4->CurrDrawAct_AttackAnimFrameSection_byte2 = 11;
  }
LABEL_79:
  
Enemy->CurrDrawAct_AnimFrameSection_byte3 = A0_Battle_Stack_After_Hit_Spells_sub_440220(this_v4, Enemy_v21);// Глюк, это другая переменная
  
A0_Battle_DrawAction_Play_sub_468570(A0_BattleMgr_dword_699420, -1, 0);
  if ( !((
this_v4->Creature_29dword74.Flags_dword10 >> 19) & 1) )// Атакует всех вогруг
  
{
    if ( 
v20 && v20->CreatureType_dword34 != Enemy_v21->CreatureType_dword34 )
    {
      
v34 = this_v4->CreatureType_dword34;
      if ( 
v34 < 0 || v34 > 150 )
      {
        
Attacker_Name_v35 = A0_Empty_dword_691260;
      }
      else
      {
        if ( 
this_v4->Count_dword4C == 1 )
          
Attacker_Name_v35 = (*Main_MonsersTable_off_6747B0)[v34].NameSingle_dword14;
        else
          
Attacker_Name_v35 = (*Main_MonsersTable_off_6747B0)[v34].NameMulti_dword18;
      }
      
Dead_v43 = Num + v46;
      
Enemy_v42 = 0;
      
Damage_v40 = a3 + v45;
      
Attacker_count_v38 = this_v4->Count_dword4C;
    }
    else
    {
      
Attacker_type_v36 = this_v4->CreatureType_dword34;
      if ( 
Attacker_type_v36 < 0 || Attacker_type_v36 > 150 )
      {
        
Attacker_Name_v35 = A0_Empty_dword_691260;
      }
      else
      {
        if ( 
this_v4->Count_dword4C == 1 )
          
Attacker_Name_v35 = (*Main_MonsersTable_off_6747B0)[Attacker_type_v36].NameSingle_dword14;
        else
          
Attacker_Name_v35 = (*Main_MonsersTable_off_6747B0)[Attacker_type_v36].NameMulti_dword18;
      }
      
Dead_v43 = Num;
      
Enemy_v42 = Enemy_v21;
      
Damage_v40 = a3;
      
Attacker_count_v38 = this_v4->Count_dword4C;
    }
    
A0_Battle_Attacking_Log_Message_sub_469670(
      (int)
A0_BattleMgr_dword_699420,
      (
char)Attacker_Name_v35,
      
Attacker_count_v38,
      
Damage_v40,
      
Enemy_v42,
      
Dead_v43);
  }
  
A0_Battle_After_Attack_Abilities_sub_4408E0(this_v4, Enemy_v21, a3, Num, a5);
  if ( (
signed int)Enemy_v47 > 0 )
    
A0_Battle_Stack_GetFireshieldDamage_sub_4406E0(this_v4, Enemy_v47);
  if ( !
Enemy_v21->CurrHit_IsBlinded_byte4C0 || (result = 1, Enemy_v21->BlindSpell_Modif_dword49C != 0.0) )
    
result = Enemy->CurrDrawAct_AnimFrameSection_byte3;// Глюк, это другая переменная
  
return result;
} 

Выстрел:
PHP Code:
void __thiscall A0_Battle_Stack_MakeShot_sub_43F620(_BattleStack_ *this, int Enemy)
{
  
int v2; // ebx@1
  
_BattleStack_ *this_v3; // esi@1
  
int v4; // eax@2
  
int *v5; // edi@3
  
int v6; // eax@7
  
_Hero_ *Hero_v7; // ecx@8
  
_BattleStack_ *Enemy_v8; // edi@8
  
int CreatureType_v9; // eax@11
  
int v10; // ecx@14
  
int v11; // ebx@14
  
int v12; // edi@16
  
int v13; // ecx@16
  
int v14; // eax@19
  
signed int v15; // edi@24
  
int v16; // eax@26
  
int v17; // ecx@28
  
char v18; // al@30
  
char *v19; // eax@31
  
_BattleStack_ *Stack_v20; // edi@31
  
int v21; // ebx@31
  
int v22; // ebx@37
  
int v23; // eax@37
  
_BattleStack_ *v24; // ecx@44
  
int v25; // eax@46
  
char *v26; // eax@49
  
int v27; // ebx@56
  
int v28; // eax@56
  
int v29; // eax@58
  
char *v30; // eax@61
  
int v31; // esi@66
  
int v32; // ebx@68
  
int v33; // ecx@70
  
int v34; // ebx@70
  
int v35; // edi@72
  
int v36; // ecx@72
  
int v37; // eax@75
  
int v38; // eax@82
  
int v39; // ecx@84
  
char v40; // al@86
  
int v41; // ebx@87
  
_BattleStack_ *v42; // edi@87
  
char *v43; // eax@89
  
int v44; // eax@91
  
unsigned __int8 v45; // sf@96
  
unsigned __int8 v46; // of@96
  
int v47; // eax@100
  
char *v48; // eax@103
  
int v49; // [sp+Ch] [bp-20h]@37
  
int v50; // [sp+10h] [bp-1Ch]@37
  
int v51; // [sp+14h] [bp-18h]@31
  
int v52; // [sp+18h] [bp-14h]@3
  
int v53; // [sp+1Ch] [bp-10h]@3
  
int v54; // [sp+20h] [bp-Ch]@24
  
_BattleStack_ *v55; // [sp+24h] [bp-8h]@24
  
_BattleStack_ *v56; // [sp+28h] [bp-4h]@24

  
this_v3 = this;
  
v2 = 0;
  
this->CurrAttack_Is_Lucky_dword70 = 0;
  if ( 
A0_BattleMgr_dword_699420->hero[A0_Battle_Stack_Get_Controller_sub_43FE60(this)] )
  {
    
v4 = this_v3->Luck_dword4EC;
    if ( 
v4 > 0 )
    {
      
v53 = this_v3->Luck_dword4EC;
      
v52 = 3;
      
v5 = &v52;
      if ( 
v4 <= 3 )
        
v5 = &v53;
      if ( 
A0_Rand_Int_sub_50C7C0(1, 24) <= *v5 )
      {
        
this_v3->CurrAttack_Is_Lucky_dword70 = 1;
        if ( !
A0_Battle_ShouldNotRenderBattle_sub_46A080((int)A0_BattleMgr_dword_699420) )
        {
          
A0_StartAndPlaySample_Parallel_sub_59A890("goodluck.82m", -1, 3);
          
v6 = (int)A0_Get_CreatureName_by_Type_adn_Count_sub_43FE20(
                      
this_v3->CreatureType_dword34,
                      
this_v3->Count_dword4C);
          
sprintf((int)A0_TempText_unk_697428, *(char **)(*((_DWORD *)off_6A5DC4 + 8) + 184), v6);
          
A0_Battle_MessageToLog_sub_4729D0(A0_BattleMgr_dword_699420->dlg, A0_TempText_unk_697428, 1, 0);
          
A0_Battle_Play_Std_BattleAnimation_sub_4963C0(A0_BattleMgr_dword_699420, 18, this_v3, 100, 0);
        }
      }
    }
  }
  
Enemy_v8 = (_BattleStack_ *)Enemy;
  
A0_Battle_Stack_DrawShot_Bullet_sub_43EFE0(this_v3, (_BattleStack_ *)Enemy);
  
Hero_v7 = A0_BattleMgr_dword_699420->hero[this_v3->Owner_dwordF4];
  if ( !
Hero_v7 || !A0_Hero_Check_Has_Artifact_Weared_sub_4D9460(Hero_v7, 5) )// Повода с боеприпасами
    
--this_v3->Creature_29dword74.Ammo_dword64;
  
CreatureType_v9 = this_v3->CreatureType_dword34;
  if ( 
CreatureType_v9 == 45 )                  // Магог
  
{
    
v52 = off_687FA8[716];
    if ( 
v52 != -1 )
    {
      if ( !
A0_Battle_ShouldNotRenderBattle_sub_46A080((int)A0_BattleMgr_dword_699420) )
      {
        
A0_StartAndPlaySample_Parallel_sub_59A890((char *)off_687FA8[715], -1, 3);
        
v11 = A0_Load_Def_sub_55C9C0(A0_BattleAnims_off_641E18[3 * v52]);
        
Enemy = (int)((char *)A0_BattleMgr_dword_699420 + 112 * Enemy_v8->GexNum_dword38);
        
v10 = *(_WORD *)(Enemy + 452);
        if ( 
Enemy_v8->Creature_29dword74.Flags_dword10 & 1 )
          
v10 += (Enemy_v8->Orientation_dword44 != 0 ? 0x2C : 0) - 22;
        
v53 = v10 - *(_DWORD *)(v11 + 48) / 2;
        
v13 = *(_WORD *)(Enemy + 454) - Enemy_v8->CreatureImageHeight_dword16C / 2 - *(_DWORD *)(v11 + 52) / 2;
        
v12 = 0;
        
Enemy = v13;
        while ( 
1 )
        {
          
v14 = *(_DWORD *)(v11 + 40) > 0 && **(_DWORD **)(v11 + 44) ? ***(_DWORD ***)(v11 + 28) : 0;
          if ( 
v12 >= v14 )
            break;
          
A0_Battle_Draw_sub_493FC0((int)A0_BattleMgr_dword_699420, 0, 0, 0, 50, 1, 1);
          
A0_Battle_DrawOrSetBorders_TranparentDef_sub_494F30(
            (int)
A0_BattleMgr_dword_699420,
            
v11,
            
v12,
            
v53,
            
Enemy,
            
0,
            
0);
          
A0_FlipBattle_sub_493300((int)A0_BattleMgr_dword_699420);
          ++
v12;
        }
        
A0_Battle_Draw_sub_493FC0((int)A0_BattleMgr_dword_699420, 1, 0, 0, 0, 1, 0);
        (*(
void (__thiscall **)(int))(*(_DWORD *)v11 + 4))(v11);
        
v2 = 0;
      }
    }
    
A0_Battle_Clear_Stacks_Redraw_Needs_sub_5A69C0(A0_BattleMgr_dword_699420);
    
v15 = 0;
    
v53 = v2;
    
v55 = (_BattleStack_ *)v2;
    
v56 = (_BattleStack_ *)v2;
    
BYTE3(Enemy) = 0;
    
v54 = 0;
    do
    {
      if ( 
v15 == 6 )
        
v16 = this_v3->Attacked_Or_MoveTarget_Gex_Num_dword1C;
      else
        
v16 = sub_524370(this_v3->Attacked_Or_MoveTarget_Gex_Num_dword1C, v15);
      
v17 = (int)&A0_BattleMgr_dword_699420->hex[v16];
      if ( 
v16 >= 0 )
      {
        if ( 
v16 < 187 )
        {
          
v18 = A0_BattleMgr_dword_699420->hex[v16].bstack_side;
          if ( 
v18 >= 0 )
          {
            
v51 = *(_BYTE *)(v17 + 25);
            
v21 = v18;
            
Stack_v20 = A0_Battle_get_StackByGex_sub_4E7230(v17);
            
v19 = &A0_BattleMgr_dword_699420->field_53D4[20 * v21 + 168] + v51;
            if ( !*
v19 )
            {
              *
v19 = 1;
              if ( 
v56 )
              {
                if ( 
v56->CreatureType_dword34 != Stack_v20->CreatureType_dword34 )
                  
BYTE3(Enemy) = 1;
              }
              else
              {
                
v56 = Stack_v20;
              }
              
v51 = 0;
              if ( 
Stack_v20 )
              {
                
v23 = A0_Battle_Stack_CalcDamage_sub_442E80((int)this_v3, 0);
                
v22 = A0_Battle_Stack_CalcDamageModifs_sub_443C60(
                        
this_v3,
                        
Stack_v20,
                        
v23,
                        
1,
                        
0,
                        
this_v3->GexesWay_Length_dword490,
                        &
v51);
                
v50 = v22;
                
v49 = A0_Battle_Stack_MakeDamage_sub_443DB0(Stack_v20, v22);
                
this_v3->CurrAttack_Is_Lucky_dword70 = 0;
              }
              else
              {
                
v22 = v50;
              }
              
v55 = (_BattleStack_ *)((char *)v55 + v22);
              
v53 += v49;
            }
            
v15 = v54;
          }
        }
      }
      ++
v15;
      
v54 = v15;
    }
    while ( 
v15 < 7 );
    if ( (
signed int)v55 > 0 )
    {
      if ( 
BYTE3(Enemy) )
        
v24 = 0;
      else
        
v24 = v56;
      
v25 = this_v3->CreatureType_dword34;
      if ( 
v25 < 0 || v25 > 150 )
      {
        
v26 = A0_Empty_dword_691260;
      }
      else
      {
        if ( 
this_v3->Count_dword4C == 1 )
          
v26 = (*Main_MonsersTable_off_6747B0)[v25].NameSingle_dword14;
        else
          
v26 = (*Main_MonsersTable_off_6747B0)[v25].NameMulti_dword18;
      }
      
A0_Battle_Attacking_Log_Message_sub_469670(
        (int)
A0_BattleMgr_dword_699420,
        (
char)v26,
        
this_v3->Count_dword4C,
        (int)
v55,
        
v24,
        
v53);
      
A0_Battle_DrawAction_Play_sub_468570(A0_BattleMgr_dword_699420, v52, 1);
    }
  }
  else
  {
    if ( 
CreatureType_v9 == 64 || CreatureType_v9 == 65 )// Лич, могущественный лич
    
{
      
v32 = off_687FA8[2586];
      if ( 
v32 != -1 )
      {
        if ( !
A0_Battle_ShouldNotRenderBattle_sub_46A080((int)A0_BattleMgr_dword_699420) )
        {
          
A0_StartAndPlaySample_Parallel_sub_59A890((char *)off_687FA8[2585], -1, 3);
          
v34 = A0_Load_Def_sub_55C9C0(A0_BattleAnims_off_641E18[3 * v32]);
          
Enemy = (int)((char *)A0_BattleMgr_dword_699420 + 112 * Enemy_v8->GexNum_dword38);
          
v33 = *(_WORD *)(Enemy + 452);
          if ( 
Enemy_v8->Creature_29dword74.Flags_dword10 & 1 )
            
v33 += (Enemy_v8->Orientation_dword44 != 0 ? 0x2C : 0) - 22;
          
v49 = v33 - *(_DWORD *)(v34 + 48) / 2;
          
v36 = *(_WORD *)(Enemy + 454) - Enemy_v8->CreatureImageHeight_dword16C / 2 - *(_DWORD *)(v34 + 52) / 2;
          
v35 = 0;
          
Enemy = v36;
          while ( 
1 )
          {
            
v37 = *(_DWORD *)(v34 + 40) > 0 && **(_DWORD **)(v34 + 44) ? ***(_DWORD ***)(v34 + 28) : 0;
            if ( 
v35 >= v37 )
              break;
            
A0_Battle_Draw_sub_493FC0((int)A0_BattleMgr_dword_699420, 0, 0, 0, 100, 1, 1);
            
A0_Battle_DrawOrSetBorders_TranparentDef_sub_494F30(
              (int)
A0_BattleMgr_dword_699420,
              
v34,
              
v35,
              
v49,
              
Enemy,
              
0,
              
0);
            
A0_FlipBattle_sub_493300((int)A0_BattleMgr_dword_699420);
            ++
v35;
          }
          
A0_Battle_Draw_sub_493FC0((int)A0_BattleMgr_dword_699420, 1, 0, 0, 0, 1, 0);
          (*(
void (__thiscall **)(int))(*(_DWORD *)v34 + 4))(v34);
        }
      }
      
A0_Battle_Clear_Stacks_Redraw_Needs_sub_5A69C0(A0_BattleMgr_dword_699420);
      
v53 = 0;
      
v54 = 0;
      
v55 = 0;
      
BYTE3(Enemy) = 0;
      
v56 = 0;
      do
      {
        if ( 
v56 == (_BattleStack_ *)6 )
          
v38 = this_v3->Attacked_Or_MoveTarget_Gex_Num_dword1C;
        else
          
v38 = sub_524370(this_v3->Attacked_Or_MoveTarget_Gex_Num_dword1C, v56);
        
v39 = (int)&A0_BattleMgr_dword_699420->hex[v38];
        if ( 
v38 >= 0 )
        {
          if ( 
v38 < 187 )
          {
            
v40 = A0_BattleMgr_dword_699420->hex[v38].bstack_side;
            if ( 
v40 >= 0 )
            {
              
v49 = *(_BYTE *)(v39 + 25);
              
v41 = v40;
              
v42 = A0_Battle_get_StackByGex_sub_4E7230(v39);
              if ( 
v56 == (_BattleStack_ *)6 || (v42->Creature_29dword74.Flags_dword10 >> 4) & 1 )
              {
                
v43 = &A0_BattleMgr_dword_699420->field_53D4[20 * v41 + 168] + v49;
                if ( !*
v43 )
                {
                  *
v43 = 1;
                  
v49 = 0;
                  if ( 
v42 )
                  {
                    
v44 = A0_Battle_Stack_CalcDamage_sub_442E80((int)this_v3, 0);
                    
v50 = A0_Battle_Stack_CalcDamageModifs_sub_443C60(
                            
this_v3,
                            
v42,
                            
v44,
                            
1,
                            
0,
                            
this_v3->GexesWay_Length_dword490,
                            &
v49);
                    
v51 = A0_Battle_Stack_MakeDamage_sub_443DB0(v42, v50);
                    
this_v3->CurrAttack_Is_Lucky_dword70 = 0;
                  }
                  
v54 += v50;
                  
v53 += v51;
                  if ( 
v55 )
                  {
                    if ( 
v55->CreatureType_dword34 != v42->CreatureType_dword34 )
                      
BYTE3(Enemy) = 1;
                  }
                  else
                  {
                    
v55 = v42;
                  }
                }
              }
            }
          }
        }
        
v46 = __SETO__(&v56->CurrDrawAct_IsShooter_byte1, 7);
        
v45 = (signed int)((char *)v56 - 6) < 0;
        
v56 = (_BattleStack_ *)((char *)v56 + 1);
      }
      while ( 
v45 ^ v46 );
      if ( 
v54 > 0 )
      {
        if ( 
BYTE3(Enemy) )
          
v55 = 0;
        
v47 = this_v3->CreatureType_dword34;
        if ( 
v47 < 0 || v47 > 150 )
        {
          
v48 = A0_Empty_dword_691260;
        }
        else
        {
          if ( 
this_v3->Count_dword4C == 1 )
            
v48 = (*Main_MonsersTable_off_6747B0)[v47].NameSingle_dword14;
          else
            
v48 = (*Main_MonsersTable_off_6747B0)[v47].NameMulti_dword18;
        }
        
A0_Battle_Attacking_Log_Message_sub_469670(
          (int)
A0_BattleMgr_dword_699420,
          (
char)v48,
          
this_v3->Count_dword4C,
          
v54,
          
v55,
          
v53);
        
A0_Battle_DrawAction_Play_sub_468570(A0_BattleMgr_dword_699420, -1, 1);
      }
    }
    else
    {
      
Enemy = 0;
      if ( 
Enemy_v8 )
      {
        
v28 = A0_Battle_Stack_CalcDamage_sub_442E80((int)this_v3, 0);
        
v27 = A0_Battle_Stack_CalcDamageModifs_sub_443C60(
                
this_v3,
                
Enemy_v8,
                
v28,
                
1,
                
0,
                
this_v3->GexesWay_Length_dword490,
                &
Enemy);
        
Enemy = A0_Battle_Stack_MakeDamage_sub_443DB0(Enemy_v8, v27);
        
this_v3->CurrAttack_Is_Lucky_dword70 = 0;
      }
      else
      {
        
v27 = Enemy;
      }
      
A0_Battle_DrawAction_Play_sub_468570(A0_BattleMgr_dword_699420, -1, 0);
      
v29 = this_v3->CreatureType_dword34;
      if ( 
v29 < 0 || v29 > 150 )
      {
        
v30 = A0_Empty_dword_691260;
      }
      else
      {
        if ( 
this_v3->Count_dword4C == 1 )
          
v30 = (*Main_MonsersTable_off_6747B0)[v29].NameSingle_dword14;
        else
          
v30 = (*Main_MonsersTable_off_6747B0)[v29].NameMulti_dword18;
      }
      
A0_Battle_Attacking_Log_Message_sub_469670(
        (int)
A0_BattleMgr_dword_699420,
        (
char)v30,
        
this_v3->Count_dword4C,
        
v27,
        
Enemy_v8,
        
Enemy);
      if ( !
A0_Battle_ShouldNotRenderBattle_sub_46A080((int)A0_BattleMgr_dword_699420) )
      {
        if ( !
A0_Battle_ShouldNotRenderBattle_sub_46A080((int)A0_BattleMgr_dword_699420) )
        {
          
v31 = (int)this_v3->Shot_Sound_dword17C;
          if ( 
v31 )
            
A0_Wait_Sample_sub_59A1C0((void *)A0_SoundMgr_dword_699414, *(_DWORD *)(v31 + 28), -1);
        }
      }
    }
  }
} 

Тут всё далеко не так хорошо описано, но код здесь и без этого можно понять, благо ссылки на структуры без смещений.
Reference URL's