Объявления
Поздравляем
Roman2211


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

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

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
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: База данных IDA от void17

Сообщение AlexSpl » 01 дек 2021, 01:49

Проверил в игре. unicornAura[1] (+0x524) - это вектор отрядов единорогов (H3Vector<army*>), в ауре которых находится отряд. unicornAura[0] (0x514) - по аналогии с дендроидами - вектор отрядов, на которые распространяется аура единорогов.

Тогда тут всё понятно:

Код: Выделить всё
if ( spellTargetType <= 0 && (First = Army->inUnicornAuraOf.First) != 0 && (Army->inUnicornAuraOf.Last - First) >> 2 )
{
   result = get_spell_work_chance(spell_1, (ECreatureType)MonType, DHero, Hero) * 0.80000001;
}
else
{
   result = get_spell_work_chance(spell_1, (ECreatureType)MonType, DHero, Hero);
}
break;

Если дебаф или ударное заклинание и существо находится по крайней мере в ауре одного отряда единорогов, шанс срабатывания заклинания уменьшается на 1 - 0.8 = 20%. Уже есть идея добавить опцию кумулятивной ауры. Например, если отряд находится в ауре двух единорогов, шанс срабатывания заклинания 0.8 * 0.8 = 64% и т.д. Это было бы логично, если проводить аналогию с физическими полями.

Заклинание Clone:

Код: Выделить всё
case SPL_CLONE:
   if ( (flags & CF_CLONE) != 0 || Army->clone != -1 )
   {
   LABEL_91:
      result = 0.0;
   }

clone - это указатель на клон отряда.

Итого, структура army выглядит пока так:

Код: Выделить всё
#pragma pack(push, 4)
struct army
{
  char field_0[40];
  army *clone;
  char field_1F[8];
  enum ECreatureType type;
  int hex;
  int animation;
  int animationFrame;
  int secondHexOrientation;
  char f_048[4];
  int numberAlive;
  int previousNumber;
  char f_054[4];
  int healthLost;
  int slotIndex;
  int numberAtStart;
  int f_064;
  int walkAnimationTime;
  int baseHP;
  int luckValue;
  H3CreatureInformation creatureInfo;
  char f_0E8[4];
  enum SpellID spellToApply;
  char f_0F0[4];
  int side;
  int sideIndex;
  unsigned int last_animation_time;
  int yOffset;
  int xOffset;
  char f_108[8];
  H3MonsterAnimation cranim;
  int *def;
  int *shootingDef;
  char f_16C[4];
  unsigned int moveSound;
  unsigned int attackSound;
  unsigned int getHitSound;
  unsigned int shotSound;
  unsigned int deathSound;
  unsigned int defendSound;
  unsigned int extraSound1;
  unsigned int extraSound2;
  int f_190;
  int activeSpellsNumber;
  int activeSpellDuration[81];
  int activeSpellsLevel[81];
  char f_420[52];
  int retaliations;
  int blessDamageBonus;
  int curseDamagePenalty;
  int antiMagic;
  int bloodlustEffect;
  int precisionEffect;
  int weaknessEffect;
  int stoneSkinEffect;
  int unknown13;
  int prayerEffect;
  int mirthEffect;
  int sorrowEffect;
  int fortuneEffect;
  int misfortuneEffect;
  int slayerType;
  int unknown14;
  int counterstrikeEffect;
  float frenzyMultiplier;
  int blindEffect;
  float fireShieldEffect;
  float ageHealthMultiplier;
  float protAirEffect;
  float protFireEffect;
  float protWaterEffect;
  float protEarthEffect;
  int effectShield;
  int effectAirShield;
  bool blinded;
  bool paralyzed;
  char _f_4C2[2];
  TSkillMastery forgetfulnessMastery;
  float slowEffect;
  int hasteEffect;
  int diseaseAttackEffect;
  int diseaseDefenseEffect;
  char f_4D8[8];
  int faerieDragonSpell;
  int magicMirrorEffect;
  int morale;
  int luck;
  char f_4F0[4];
  vector dendroidBinder;
  vector dendroidBinds;
  vector unicornAuraFor;
  vector inUnicornAuraOf;
  int health_AI_unk;
  army *targetArmy;
  int f_53C;
  int distanceToTargetArmy;
  int bfTargetArmies;
};
#pragma pack(pop)

Давайте добьём. Одна из самых важных структур всё-таки.

health_AI_unk - это, скорее всего, средний урон targetArmyAvgDamage самого опасного противника (targetArmy). Используется для определения, нужно ли кастовать Cure, и его ценности. Но, может быть, и весь средний урон от угрожающих противников из битового поля bfTargetArmies (нужно переименовать target, например, на threatening).
Вернуться к началу

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

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

Сообщение void_17 » 01 дек 2021, 15:00

AlexSpl, обновите базу на сервере, если не обновили.
Вернуться к началу

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

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

Сообщение void_17 » 03 дек 2021, 13:26

AlexSpl :smile11:
Вернуться к началу

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: База данных IDA от void17

Сообщение AlexSpl » 04 дек 2021, 12:08

Почему в Героях 3 размер вектора не совпадает с размером std::vector? Оказывается, Герои 3 были скомпилированы без проверки итераторов.

Цитата:
Checked iterators ensure that the bounds of your container are not overwritten. Checked iterators apply to both release builds and debug builds.

Чтобы использовать в Вашем решении std::vector вместо кастомных типов (например, H3Vector из H3API), нужно добавить следующие строки:

Код: Выделить всё
#define _SECURE_SCL 0
#define _HAS_ITERATOR_DEBUGGING 0

Для новых версий Visual Studio (не скажу, в какой точно добавили) можно писать:

Код: Выделить всё
#define _ITERATOR_DEBUG_LEVEL 0

Теперь у нас sizeof(std::vector<_Ty>) = 16 :smile20:
Вернуться к началу

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: База данных IDA от void17

Сообщение AlexSpl » 05 дек 2021, 01:42

Определил назначение ещё нескольких полей класса army, некоторые исправил (WIP, так что могут быть ошибки):

Код: Выделить всё
#pragma pack(push, 4)
struct army
{
  char field_0;
  char field_1;
  char field_2;
  int field_4;
  int field_8;
  char field_C;
  int field_10;
  int field_14;
  int field_18;
  int destinationHex;
  char field_20;
  int cloneParentIndex;
  int cloneOwnerIndex;
  int timeToLive;
  char isMoving;
  char field_31;
  enum ECreatureType creatureType;
  int hex;
  int animation;
  int animationFrame;
  int secondHexOrientation;
  char field_048[4];
  int numberAlive;
  int previousNumber;
  int field_054;
  int healthLost;
  int slotIndex;
  int numberAtStart;
  int baseSpeed;
  int walkAnimationTime;
  int baseHealth;
  int luckValue;
  TCreatureTypeTraits creature;
  char field_0E8;
  char field_0E9;
  char field_0EA;
  enum SpellID spellToApply;
  char field_0F0[4];
  int side;
  int sideIndex;
  unsigned int lastAnimationTime;
  int yOffset;
  int xOffset;
  int field_108;
  int field_10C;
  H3MonsterAnimation cranim;
  int *def;
  int *shootingDef;
  int field_16C;
  unsigned int moveSound;
  unsigned int attackSound;
  unsigned int getHitSound;
  unsigned int shotSound;
  unsigned int deathSound;
  unsigned int defendSound;
  unsigned int extraSound1;
  unsigned int extraSound2;
  int turnsToNextMove;
  int activeSpellsNumber;
  int activeSpellDuration[81];
  int activeSpellMastery[81];
  std::vector chunkVector;
  std::deque spellDeque;
  float colorSaturation;
  int retaliations;
  int blessDamageBonus;
  int curseDamagePenalty;
  int antiMagicLevel;
  int bloodlustEffect;
  int precisionEffect;
  int weaknessEffect;
  int stoneSkinEffect;
  int unknown13;
  int prayerEffect;
  int mirthEffect;
  int sorrowEffect;
  int fortuneEffect;
  int misfortuneEffect;
  int slayerType;
  int pathLength;
  int counterstrikeEffect;
  float frenzyMultiplier;
  int blindEffect;
  float fireShieldEffect;
  float healthMod;
  float protAirEffect;
  float protFireEffect;
  float protWaterEffect;
  float protEarthEffect;
  float effectShield;
  float effectAirShield;
  bool blinded;
  bool paralyzed;
  TSkillMastery forgetfulnessMastery;
  float slowEffect;
  int hasteEffect;
  int diseaseAttackPenalty;
  int diseaseDefensePenalty;
  char hasNativeTerrainBonuses;
  int defensiveStanceBonus;
  int faerieDragonSpell;
  int magicMirrorEffect;
  int morale;
  int luck;
  char field_4F0;
  char field_4F1;
  std::vector dendroidBinder;
  std::vector dendroidBinds;
  std::vector unicornAuraFor;
  std::vector inUnicornAuraOf;
  int targetArmyAvgDamage;
  army *targetArmy;
  int field_53C;
  int distanceToTargetArmy;
  int bfTargetArmies;
};
#pragma pack(pop)

Интересное поле int turnsToNextMove; B нём хранится количество ходов отрядов до следующего хода данного существа. Правда, не знаю, учитывает ли это поле заклинания, влияющие на скорость. Если да, то можно на него опираться для определения очерёдности ходов.

Ещё с полями 0x420 и 0x430 не всё понятно. Они нужны для работы очереди (std::deque) заклинаний, висящих на отряде (картинки заклинаний, которые отображаются при правом клике на отряде в его информационном окне). Но как я ни пытался привести эти поля к std::deque<SpellID>, то тут, то там не помещалось :smile14: Может, реализация старая std::deque (там в template 3 параметра вместо 2), а может что ещё хитрое, поэтому оставлю пока так (сейчас можно без ошибок получать длину очереди: spellDeque->size(), и, вроде, spellDeque->pop_back() работает, а вот на методах front() и back() - вылеты). Если никто не в курсе, что там за STL-структуры, то придётся писать свою, которая будет работать.

Heroes3f.zip
(14.08 МБ) Скачиваний: 185
Вернуться к началу

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: База данных IDA от void17

Сообщение AlexSpl » 06 дек 2021, 11:20

Скачал Visual Studio 6.0 (1998-й год), заодно Visual Studio 97. Клас deque в версии 6.0 реализован иначе, другой порядок полей.

В Visual Studio 2008 собственные поля класса:

Код: Выделить всё
_Mapptr _Map;   // pointer to array of pointers to blocks
size_type _Mapsize;   // size of map array
size_type _Myoff;   // offset of initial element
size_type _Mysize;   // current length of sequence

В 6.0:

Код: Выделить всё
_Tptr _First, _Last, _Next;
_Mapptr _Map;

А вот поля итератора версии 6.0 я узнал:

Код: Выделить всё
_A allocator;
iterator _First, _Last;
_Mapptr _Map;
size_type _Mapsize, _Size;

Думал, что там за двойка перед длиной очереди, а оказывается:

Код: Выделить всё
#define _DEQUEMAPSIZ   2

Так что тут, в отличие от std::vector, придётся либо подключать старый хедер, либо писать собственную структуру (это, конечно, если Вы пишете плагин и намереваетесь удобно работать с очередью заклинаний).

Позже обновлю базу. Старый класс std::deque находится не по тому смещению в классе army, я угадал только конец (в обеих версиях deque последнее поле - длина очереди).
Вернуться к началу

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: База данных IDA от void17

Сообщение AlexSpl » 06 дек 2021, 13:24

Вышла Ghidra 10.1 beta:

Цитата:
Performance Improvements

There have been many performance improvements to import, analysis, program data base access, many API calls, and the user interface.

Symbol performance in Ghidra was significantly improved. Specifically, new database indexes were created to improve finding primary symbols as well as improving lookups by combinations of name, namespace, and address.

Processors

Improvements and bug fixes to many processors to include: X86, ARM, AARCH64, SPARC, PPC, SH4, RISC-V, and 6502.

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

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: База данных IDA от void17

Сообщение AlexSpl » 07 дек 2021, 03:58

Итак, всё ОК со старым классом std::deque:

Итератор:

Код: Выделить всё
#pragma pack(push, 4)
struct std::deque::iterator
{
  int *first;
  int *last;
  int *next;
  int *map;
};
#pragma pack(pop)


Класс std::deque:

Код: Выделить всё
#pragma pack(push, 4)
struct std::deque
{
  char allocator;
  std::deque::iterator itFirst;
  std::deque::iterator itLast;
  int *map;
  int mapSize;
  int size;
};
#pragma pack(pop)

Размер std::deque - 0x30 = 48 байт.

army:

Код: Выделить всё
#pragma pack(push, 4)
struct army
{
  char field_0;
  char field_1;
  char field_2;
  int field_4;
  int field_8;
  char field_C;
  int field_10;
  int field_14;
  int field_18;
  int destinationHex;
  char field_20;
  int cloneParentIndex;
  int cloneOwnerIndex;
  int timeToLive;
  char isMoving;
  char field_31;
  enum ECreatureType creatureType;
  int hex;
  int animation;
  int animationFrame;
  int secondHexOrientation;
  char field_048[4];
  int numberAlive;
  int previousNumber;
  int field_054;
  int healthLost;
  int slotIndex;
  int numberAtStart;
  int baseSpeed;
  int walkAnimationTime;
  int baseHealth;
  int luckValue;
  TCreatureTypeTraits creature;
  char field_0E8;
  char field_0E9;
  char field_0EA;
  enum SpellID spellToApply;
  char field_0F0[4];
  int side;
  int sideIndex;
  unsigned int lastAnimationTime;
  int yOffset;
  int xOffset;
  int field_108;
  int field_10C;
  H3MonsterAnimation cranim;
  int *def;
  int *shootingDef;
  int field_16C;
  unsigned int moveSound;
  unsigned int attackSound;
  unsigned int getHitSound;
  unsigned int shotSound;
  unsigned int deathSound;
  unsigned int defendSound;
  unsigned int extraSound1;
  unsigned int extraSound2;
  int turnsToNextMove;
  int activeSpellsNumber;
  int activeSpellDuration[81];
  int activeSpellMastery[81];
  std::deque spellDeque;
  float colorSaturation;
  int retaliations;
  int blessDamageBonus;
  int curseDamagePenalty;
  int antiMagicLevel;
  int bloodlustEffect;
  int precisionEffect;
  int weaknessEffect;
  int stoneSkinEffect;
  int unknown13;
  int prayerEffect;
  int mirthEffect;
  int sorrowEffect;
  int fortuneEffect;
  int misfortuneEffect;
  int slayerType;
  int pathLength;
  int counterstrikeEffect;
  float frenzyMultiplier;
  int blindEffect;
  float fireShieldEffect;
  float healthMod;
  float protAirEffect;
  float protFireEffect;
  float protWaterEffect;
  float protEarthEffect;
  float effectShield;
  float effectAirShield;
  bool blinded;
  bool paralyzed;
  TSkillMastery forgetfulnessMastery;
  float slowEffect;
  int hasteEffect;
  int diseaseAttackPenalty;
  int diseaseDefensePenalty;
  char hasNativeTerrainBonuses;
  int defensiveStanceBonus;
  int faerieDragonSpell;
  int magicMirrorEffect;
  int morale;
  int luck;
  char field_4F0;
  char field_4F1;
  std::vector dendroidBinder;
  std::vector dendroidBinds;
  std::vector unicornAuraFor;
  std::vector inUnicornAuraOf;
  int targetArmyAvgDamage;
  army *targetArmy;
  int field_53C;
  int distanceToTargetArmy;
  int bfTargetArmies;
};
#pragma pack(pop)
Вернуться к началу

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: База данных IDA от void17

Сообщение AlexSpl » 07 дек 2021, 17:38

На отряды под Magic Mirror не действует Hypnotize, т.е. нельзя повесить, хотя нет сообщения о том, что этого сделать нельзя (в FizMiG'е не нашёл об этом):

Код: Выделить всё
case SPL_HYPNOTIZE:
  hypnotizeEffect_1 = akSpelltraits[SPL_HYPNOTIZE].effect[hero::get_spell_level(
                                             casterHero,
                                             SPL_HYPNOTIZE,
                                             this->specialGround)]
               + akSpelltraits[SPL_HYPNOTIZE].effPower * this->heroSpellPower[side];
  hypnotizeHealth = hero::GetHeroSpellBonus(casterHero, SPL_HYPNOTIZE, army->creature.tier, hypnotizeEffect_1)
              + hypnotizeEffect_1;
  if ( !army->activeSpellDuration[SPL_MAGIC_MIRROR] && army->numberAlive * army->creature.health <= hypnotizeHealth )
     goto STANDARD_CHANCE;
  result = 0.0;
  break;

А нет, есть :smile1: Но в описании Magic Mirror.

Разобрал параметры combatManager::SpellCastWorkChance():

Код: Выделить всё
float __thiscall combatManager::SpellCastWorkChance(
        combatManager *this,
        enum SpellID spell,
        int side,
        const army *army,
        bool isMirroredSpell,
        bool isSpellFirstStage,
        bool isCreatureCast)

Теперь можно учитывать шанс срабатывания заклинания в функциях взвешивания.
Вернуться к началу

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

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

Сообщение RoseKavalier » 07 дек 2021, 23:21

Information forgotten by most due to time.
Цитата:
Gus Smedstad
25/01/2000
Truthseeker wrote:
>
> If in battle, you try to cast Hypnotize on an opponent's troop that has Magic
> Mirror cast, and you get unlucky and get your Hypnotize gets re-directed, what
> happens and how does it work?

Hypnotize is treated specially by Magic Mirror, for pretty much the
reasons you imagine. Magic Mirror renders the target immune to
Hypnotize, rather than using the normal mechanic.

You could have found this out if you'd set up a sample map.

- Gus

LINK
Вернуться к началу

Пред.След.

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

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

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