Рейтинги опасности в type_AI_combat_parameters:
- Код: Выделить всё
type_AI_combat_parameters *__thiscall type_AI_combat_parameters::type_AI_combat_parameters(
type_AI_combat_parameters *this,
combatManager *pCombatManager,
int side)
{
int *ArmyNum; // eax
combatManager *pCombatManager_0; // ebx
army *iArmy; // edi
int defense_modifier; // eax
int attack_modifier; // ebx
bool Done; // zf
int total_combat_value_2; // eax
int total_combat_value; // eax
int attack_modifier_0; // ecx
int casterSide; // edx
int total_combat_value_0; // eax
int attack_modifier_1; // ecx
int enemySide; // edx
int total_combat_value_1; // eax
int attack_modifier_2; // ecx
int enemySide_0; // edx
int enemyTotalCombatValue; // edx
int casterTotalCombatValueDoubled; // ecx
int casterActiveStacksCombatValue; // ecx
int i; // ecx
bool can_shoot; // [esp+10h] [ebp-18h]
int iSide; // [esp+18h] [ebp-10h]
army (*Army)[21]; // [esp+1Ch] [ebp-Ch]
int *ArmyNum_0; // [esp+20h] [ebp-8h]
char v29; // [esp+27h] [ebp-1h]
combatManager *casterActiveStacksCombatValue_0; // [esp+30h] [ebp+8h]
int iStack; // [esp+34h] [ebp+Ch]
int total_combat_value_3; // [esp+34h] [ebp+Ch]
pCombatManager_0 = pCombatManager;
iArmy = pCombatManager->Army[0];
this->side[AI_CASTER] = side;
ArmyNum = pCombatManager->ArmyNum;
v29 = 1;
this->side[1] = 1 - side;
this->attack_modifier = 0;
this->defense_modifier = 0;
this->isOpponentDangerous = 0;
this->field_9 = 0;
Army = pCombatManager->Army;
ArmyNum_0 = pCombatManager->ArmyNum;
iSide = 2;
do
{
for ( iStack = 0; iStack < *ArmyNum; ++iStack )
{
if ( iArmy->AmountAlive > 0 && iArmy->CreatureType != CID_ARROW_TOWER )
{
can_shoot = army::can_shoot(iArmy, 0);
attack_modifier = army::get_attack_modifier(iArmy, 0, can_shoot);
defense_modifier = army::get_defense_modifier(iArmy);
if ( (v29 || this->attack_modifier > attack_modifier) && (this->attack_modifier = attack_modifier, v29)
|| this->defense_modifier > defense_modifier )
{
this->defense_modifier = defense_modifier;
}
pCombatManager_0 = pCombatManager;
ArmyNum = ArmyNum_0;
v29 = 0;
}
++iArmy;
}
++ArmyNum;
// Переходим к следующей стороне
iArmy = &(*Army)[21];
Done = iSide == 1;
ArmyNum_0 = ArmyNum;
++Army;
--iSide;
}
while ( !Done );
total_combat_value = combatManager::get_total_combat_value(
pCombatManager_0,
this->side[AI_CASTER],
this->attack_modifier,
this->defense_modifier,
1);
attack_modifier_0 = this->attack_modifier;
casterSide = this->side[AI_CASTER];
this->casterTotalCombatValue = total_combat_value;
total_combat_value_0 = combatManager::get_total_combat_value(
pCombatManager_0,
casterSide,
attack_modifier_0,
this->defense_modifier,
0);
attack_modifier_1 = this->attack_modifier;
enemySide = this->side[AI_ENEMY];
this->casterActiveStacksCombatValue = total_combat_value_0;
total_combat_value_1 = combatManager::get_total_combat_value(
pCombatManager_0,
enemySide,
attack_modifier_1,
this->defense_modifier,
1);
attack_modifier_2 = this->attack_modifier;
enemySide_0 = this->side[AI_ENEMY];
this->enemyTotalCombatValue = total_combat_value_1;
total_combat_value_2 = combatManager::get_total_combat_value(
pCombatManager_0,
enemySide_0,
attack_modifier_2,
this->defense_modifier,
0);
enemyTotalCombatValue = this->enemyTotalCombatValue;
casterTotalCombatValueDoubled = 2 * this->casterTotalCombatValue;
this->enemyActiveStacksCombatValue = total_combat_value_2;
if ( casterTotalCombatValueDoubled < enemyTotalCombatValue
&& (gpGame->PlayerInfo.GameDifficulty > EASY || gpCombatManager->isHuman[this->side[AI_CASTER]]) )
{
this->isOpponentDangerous = 1;
}
total_combat_value_3 = total_combat_value_2;
casterActiveStacksCombatValue = this->casterActiveStacksCombatValue;
casterActiveStacksCombatValue_0 = casterActiveStacksCombatValue;
// Выбираем сильнейшую сторону
if ( casterActiveStacksCombatValue < total_combat_value_2 )
{
casterActiveStacksCombatValue = total_combat_value_2;
total_combat_value_2 = this->casterActiveStacksCombatValue;
casterActiveStacksCombatValue_0 = casterActiveStacksCombatValue;
total_combat_value_3 = total_combat_value_2;
}
// Определяем уровень опасности по отношению активных сил армий
if ( 5 * total_combat_value_2 > casterActiveStacksCombatValue && casterActiveStacksCombatValue )
{
this->DangerRating = 0;
do
{
i = this->DangerRating;
// Рейтинги опасности:
// DangerRating = 1 при отношении сил более 2.6
// DangerRating = 2 при отношении сил более 1.9
// DangerRating = 3 при отношении сил более 1.5
// DangerRating = 4 при отношении сил более 1.31
// DangerRating = 5 при отношении сил более 1.2
// DangerRating = 6 при отношении сил более 1.13
if ( casterActiveStacksCombatValue_0 / total_combat_value_3 >= StrengthRatio[i] )
break;
this->DangerRating = i + 1;
}
while ( i + 1 < 6 );
// Мининальный рейтинг опасности - 1
++this->DangerRating;
return this;
}
else
{
this->DangerRating = 1;
return this;
}
}
Только пока не выяснял, для чего они. Может, для принятия решения о побеге (но тогда что они делают в type_AI_combat_parameters?). Может, влияют на поведение компа при касте заклинаний. Например, я замечал, что комп под конец, если побеждает с большим отрывом, кастует Resurrection, а если проигрывает, спамит призывом. Но это нужно проверять, а из-за этих повторных использований одних и тех же переменных, не сразу поймёшь, о какой стороне идёт речь, даже в декомпилированном листинге. Нужно упрощать код в блокноте
Но это уже позже.
Итого, type_AI_combat_parameters выглядит вот так:
- Код: Выделить всё
type_AI_combat_parameters struc ; (sizeof=0x28, align=0x4, mappedto_370)
00000000 ; XREF: FF015A1C/r
00000000 attack_modifier dd ?
00000004 defense_modifier dd ?
00000008 isOpponentDangerous db ?
00000009 field_9 db ? ; XREF: long combatManager::choose_melee_action(army *,bool,bool,long)+1F/w
0000000A field_A db ?
0000000B field_B db ?
0000000C casterTotalCombatValue dd ?
00000010 enemyTotalCombatValue dd ?
00000014 casterActiveStacksCombatValue dd ?
00000018 enemyActiveStacksCombatValue dd ?
0000001C DangerRating dd ?
00000020 side dd 2 dup(?)
00000028 type_AI_combat_parameters ends
Нераспознанное поле field_9 (предполагаю, что это флаг симуляции битвы isBattleSimulated, например), остальные, скорее всего, паддинг (align = 4).
Чтобы окончательно разобраться, нужно эти поля визуализировать и посмотреть, как они меняются в реальном бою. Можно хукнуть type_AI_combat_parameters::type_AI_combat_parameters() и выводить сообщения, например.