Объявления

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

Как создать плагин для HD мода

Герои Меча и Магии 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: Как создать плагин для HD мода

Сообщение AlexSpl » 27 авг 2021, 14:39

Добавил Disease (картинка пока прежняя):

Код: Выделить всё
#define _CRT_SECURE_NO_WARNINGS
#include <bitset>
#include "..\..\HotA\homm3.h"

#define SPELLS_MAX 128
#define ANIMS_MAX 128
#define ADVSPELLS_NUM 10
#define SPECABIL_NUM 11
#define ARTIFACTS_NUM 144

#define SPELLS_NUM 89
#define SPL_FEAR_NEW 81
#define SPL_POISON_NEW 82
#define SPL_DISEASE_NEW 83
#define SPL_AGING_NEW 84
#define SPL_DEATH_CLOUD_NEW 85
#define SPL_DEATH_BLOW_NEW 86
#define SPL_FIREBIRD_NEW 87
#define SPL_MAGIC_ELEMENTAL_NEW 88

#define ANIMS_NUM 89
#define ANIM_FEAR_NEW 83
#define ANIM_POISON_NEW 84
#define ANIM_DISEASE_NEW 85
#define ANIM_AGING_NEW 86
#define ANIM_DEATH_CLOUD_NEW 87
#define ANIM_DEATH_BLOW_NEW 88

Patcher* _P;
PatcherInstance* _PI;

struct _ComboArtInfo_ {
   int index;
   std::bitset<160> parts;
};

struct _MagicAnim_ {
   char* defName;
   char* name;
   int type;
};

#define o_ComboArtInfo (*(_ComboArtInfo_**)0x660B6C)
#define o_MagicAnim ((_MagicAnim_*)0x641E18)

_Spell_ spell[SPELLS_MAX];
_MagicAnim_ anim[ANIMS_MAX];
//char iniPath[MAX_PATH];

char spellIndirectTableA[] = {
   // Spells (starting from Quicksand #10)
    0,  1,  2,  2,  3,  4,  4,  4,  4,  4,
    5,  5,  5,  5,  4,  4,  4,  4,  4,  4,
    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
    6,  4,  4,  4,  4,  4,  4,  4,  4,  4,
    4,  4,  4,  4,  4,  4,  4,  4,  4,  5,
    4,  4,  4,  7,  8,  9, 10, 10, 10, 10,
   // Special Abilities (you cannot cast them anyway)
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   -1,
   // New Spells (starting from Fear #81)
    4,  4,  4,  4,  5,  4, 10, 10
};

char spellIndirectTableB[] = {
   // Spells (starting from Quicksand #10)
    0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
   10, 11, 12, 13, 14, 15, 16, 17, 17, 17,
   17, 17, 17, 17, 17, 18, 17, 19, 20, 20,
   21, 17, 17, 22, 17, 17, 17, 23, 17, 17,
   17, 17, 17, 17, 17, 17, 17,  7, 17, 24,
   17, 17, 17, 25, 26, 27, 28, 29, 30, 31,
   // Special Abilities
   32, 33, 34, 17, 17, 34, 37, 37, 35, 37,
   36,
   // New Spells (starting from Fear #81)
   17, 17, 17, 17, 11, 17, 38, 39
};

char spellIndirectTableC[] = {
   // Spells (starting from Shield #27)
    0,  1,  2,  3,  4,  5,  6,  7, 32,  8,
   32, 32, 32, 32,  9, 10, 11, 12, 13, 14,
   32, 15, 16, 17, 18, 19, 20, 21, 22, 23,
   32, 24, 25, 26, 27, 28, 32, 32, 32, 32,
   32, 32, 32,
   // Special Abilities
   32, 29, 32, 30, 32, 31, -1, -1, -1, -1,
   -1,
   // New Spells (starting from Fear #81)
   32, 32, 33, 32, 32, 32, 32, 32
};

char spellIndirectTableD[] = {
   // Spells (starting from Weakness #45)
    0,  1,  9,  2,  9,  9,  9,  9,  3,  4,
    9,  9,  9,  9,  9,  5,  9,  9,  9,  9,
    9,  9,  9,  9,  9,
    // Special Abilities
    9,  9,  6,  7,  9,  8, -1, -1, -1, -1,
    -1,
    // New Spells (starting from Fear #81)
    9,  9, 10,  9,  9,  9,  9,  9
};

bool shrineSpells[SPELLS_MAX];

struct DiseaseSpellParams {
   int AttackPenalty;
   int DefensePenalty;
   int SpeedPenalty;
};

DiseaseSpellParams diseaseSpell[4];
DiseaseSpellParams diseaseSpellParams[2][21];

int __stdcall afterInit(LoHook* h, HookContext* c)
{
   // Spell Table
   for (int i = 0; i < SPL_FEAR_NEW; ++i)
      spell[i] = o_Spell[i];

   // Fear
   spell[SPL_FEAR_NEW].type = -1;
   spell[SPL_FEAR_NEW].wav_name = "FearRoE.wav";
   spell[SPL_FEAR_NEW].animation_ix = ANIM_FEAR_NEW;
   spell[SPL_FEAR_NEW].flags = 0x20415;
   spell[SPL_FEAR_NEW].name = "Fear";
   spell[SPL_FEAR_NEW].short_name = "Fear";
   spell[SPL_FEAR_NEW].level = 4;
   spell[SPL_FEAR_NEW].school_flags = SSF_EARTH;
   spell[SPL_FEAR_NEW].mana_cost[0] = 16;
   spell[SPL_FEAR_NEW].mana_cost[1] = 8;
   spell[SPL_FEAR_NEW].mana_cost[2] = 8;
   spell[SPL_FEAR_NEW].mana_cost[3] = 8;
   spell[SPL_FEAR_NEW].eff_power = 0;
   spell[SPL_FEAR_NEW].effect[0] = 75;
   spell[SPL_FEAR_NEW].effect[1] = 75;
   spell[SPL_FEAR_NEW].effect[2] = 50;
   spell[SPL_FEAR_NEW].effect[3] = 25;
   spell[SPL_FEAR_NEW].chance2get_var[0] = 10;
   spell[SPL_FEAR_NEW].chance2get_var[1] = 10;
   spell[SPL_FEAR_NEW].chance2get_var[2] = 10;
   spell[SPL_FEAR_NEW].chance2get_var[3] = 10;
   spell[SPL_FEAR_NEW].chance2get_var[4] = 10;
   spell[SPL_FEAR_NEW].chance2get_var[5] = 10;
   spell[SPL_FEAR_NEW].chance2get_var[6] = 10;
   spell[SPL_FEAR_NEW].chance2get_var[7] = 10;
   spell[SPL_FEAR_NEW].chance2get_var[8] = 10;
   spell[SPL_FEAR_NEW].ai_value[0] = 50;
   spell[SPL_FEAR_NEW].ai_value[1] = 50;
   spell[SPL_FEAR_NEW].ai_value[2] = 50;
   spell[SPL_FEAR_NEW].ai_value[3] = 50;
   spell[SPL_FEAR_NEW].description[0] =
      "{Fear}\n\nStrikes an enemy unit with such fear that it becomes unable to attack and nearly unable to move.\n";
   spell[SPL_FEAR_NEW].description[1] =
      "{Basic Fear}\n\nStrikes an enemy unit with such fear that it becomes unable to attack and nearly unable to move.\n\nSpell Point cost is half that of Normal Fear.\n";
   spell[SPL_FEAR_NEW].description[2] =
      "{Advanced Fear}\n\nStrikes an enemy unit with such fear that it becomes unable to attack and nearly unable to move.\n\nPenalty to movement is twice that of Basic Fear.\n";
   spell[SPL_FEAR_NEW].description[3] =
      "{Expert Fear}\n\nStrikes an enemy unit with such fear that it becomes unable to attack and nearly unable to move.\n\nPenalty to movement is three times that of Basic Fear.\n";

   // Poison
   spell[SPL_POISON_NEW].type = -1;
   spell[SPL_POISON_NEW].wav_name = "Poison.wav";
   spell[SPL_POISON_NEW].animation_ix = ANIM_POISON_NEW;
   spell[SPL_POISON_NEW].flags = 0x1015;
   spell[SPL_POISON_NEW].name = "Poison";
   spell[SPL_POISON_NEW].short_name = "Poison";
   spell[SPL_POISON_NEW].level = 4;
   spell[SPL_POISON_NEW].school_flags = SSF_EARTH;
   spell[SPL_POISON_NEW].mana_cost[0] = 20;
   spell[SPL_POISON_NEW].mana_cost[1] = 16;
   spell[SPL_POISON_NEW].mana_cost[2] = 16;
   spell[SPL_POISON_NEW].mana_cost[3] = 16;
   spell[SPL_POISON_NEW].eff_power = 0;
   spell[SPL_POISON_NEW].effect[0] = 0;
   spell[SPL_POISON_NEW].effect[1] = 0;
   spell[SPL_POISON_NEW].effect[2] = 0;
   spell[SPL_POISON_NEW].effect[3] = 0;
   spell[SPL_POISON_NEW].chance2get_var[0] = 10;
   spell[SPL_POISON_NEW].chance2get_var[1] = 10;
   spell[SPL_POISON_NEW].chance2get_var[2] = 10;
   spell[SPL_POISON_NEW].chance2get_var[3] = 10;
   spell[SPL_POISON_NEW].chance2get_var[4] = 10;
   spell[SPL_POISON_NEW].chance2get_var[5] = 10;
   spell[SPL_POISON_NEW].chance2get_var[6] = 10;
   spell[SPL_POISON_NEW].chance2get_var[7] = 10;
   spell[SPL_POISON_NEW].chance2get_var[8] = 10;
   spell[SPL_POISON_NEW].ai_value[0] = 50;
   spell[SPL_POISON_NEW].ai_value[1] = 50;
   spell[SPL_POISON_NEW].ai_value[2] = 50;
   spell[SPL_POISON_NEW].ai_value[3] = 50;
   spell[SPL_POISON_NEW].description[0] =
      "{Poison}\n\nPoison Description.\n";
   spell[SPL_POISON_NEW].description[1] =
      "{Basic Poison}\n\nBasic Poison Description.\n";
   spell[SPL_POISON_NEW].description[2] =
      "{Advanced Poison}\n\nAdvanced Poison Description.\n";
   spell[SPL_POISON_NEW].description[3] =
      "{Expert Poison}\n\nExpert Poison Description.\n";

   // Disease
   spell[SPL_DISEASE_NEW].type = -1;
   spell[SPL_DISEASE_NEW].wav_name = "Disease.wav";
   spell[SPL_DISEASE_NEW].animation_ix = ANIM_DISEASE_NEW;
   spell[SPL_DISEASE_NEW].flags = 0x40045;
   spell[SPL_DISEASE_NEW].name = "Disease";
   spell[SPL_DISEASE_NEW].short_name = "Disease";
   spell[SPL_DISEASE_NEW].level = 4;
   spell[SPL_DISEASE_NEW].school_flags = SSF_EARTH;
   spell[SPL_DISEASE_NEW].mana_cost[0] = 16;
   spell[SPL_DISEASE_NEW].mana_cost[1] = 12;
   spell[SPL_DISEASE_NEW].mana_cost[2] = 12;
   spell[SPL_DISEASE_NEW].mana_cost[3] = 12;
   spell[SPL_DISEASE_NEW].eff_power = 0;
   spell[SPL_DISEASE_NEW].effect[0] = 2;
   spell[SPL_DISEASE_NEW].effect[1] = 2;
   spell[SPL_DISEASE_NEW].effect[2] = 4;
   spell[SPL_DISEASE_NEW].effect[3] = 4;
   spell[SPL_DISEASE_NEW].chance2get_var[0] = 10;
   spell[SPL_DISEASE_NEW].chance2get_var[1] = 10;
   spell[SPL_DISEASE_NEW].chance2get_var[2] = 10;
   spell[SPL_DISEASE_NEW].chance2get_var[3] = 10;
   spell[SPL_DISEASE_NEW].chance2get_var[4] = 10;
   spell[SPL_DISEASE_NEW].chance2get_var[5] = 10;
   spell[SPL_DISEASE_NEW].chance2get_var[6] = 10;
   spell[SPL_DISEASE_NEW].chance2get_var[7] = 10;
   spell[SPL_DISEASE_NEW].chance2get_var[8] = 10;
   spell[SPL_DISEASE_NEW].ai_value[0] = 50;
   spell[SPL_DISEASE_NEW].ai_value[1] = 50;
   spell[SPL_DISEASE_NEW].ai_value[2] = 50;
   spell[SPL_DISEASE_NEW].ai_value[3] = 50;
   spell[SPL_DISEASE_NEW].description[0] =
      "{Disease}\n\nDisease Description.\n";
   spell[SPL_DISEASE_NEW].description[1] =
      "{Basic Disease}\n\nBasic Disease Description.\n";
   spell[SPL_DISEASE_NEW].description[2] =
      "{Advanced Disease}\n\nAdvanced Disease Description.\n";
   spell[SPL_DISEASE_NEW].description[3] =
      "{Expert Disease}\n\nExpert Disease Description.\n";

   diseaseSpell[0].AttackPenalty = 2;
   diseaseSpell[0].DefensePenalty = 2;
   diseaseSpell[0].SpeedPenalty = 20;
   diseaseSpell[1].AttackPenalty = 2;
   diseaseSpell[1].DefensePenalty = 2;
   diseaseSpell[1].SpeedPenalty = 20;
   diseaseSpell[2].AttackPenalty = 4;
   diseaseSpell[2].DefensePenalty = 4;
   diseaseSpell[2].SpeedPenalty = 40;
   diseaseSpell[3].AttackPenalty = 4;
   diseaseSpell[3].DefensePenalty = 4;
   diseaseSpell[3].SpeedPenalty = 40;
   
   // Aging
   spell[SPL_AGING_NEW].type = -1;
   spell[SPL_AGING_NEW].wav_name = "Age.wav";
   spell[SPL_AGING_NEW].animation_ix = ANIM_AGING_NEW;
   spell[SPL_AGING_NEW].flags = 0x1015;
   spell[SPL_AGING_NEW].name = "Aging";
   spell[SPL_AGING_NEW].short_name = "Aging";
   spell[SPL_AGING_NEW].level = 5;
   spell[SPL_AGING_NEW].school_flags = SSF_FIRE;
   spell[SPL_AGING_NEW].mana_cost[0] = 25;
   spell[SPL_AGING_NEW].mana_cost[1] = 20;
   spell[SPL_AGING_NEW].mana_cost[2] = 20;
   spell[SPL_AGING_NEW].mana_cost[3] = 20;
   spell[SPL_AGING_NEW].eff_power = 0;
   spell[SPL_AGING_NEW].effect[0] = 0;
   spell[SPL_AGING_NEW].effect[1] = 0;
   spell[SPL_AGING_NEW].effect[2] = 0;
   spell[SPL_AGING_NEW].effect[3] = 0;
   spell[SPL_AGING_NEW].chance2get_var[0] = 10;
   spell[SPL_AGING_NEW].chance2get_var[1] = 10;
   spell[SPL_AGING_NEW].chance2get_var[2] = 10;
   spell[SPL_AGING_NEW].chance2get_var[3] = 10;
   spell[SPL_AGING_NEW].chance2get_var[4] = 10;
   spell[SPL_AGING_NEW].chance2get_var[5] = 10;
   spell[SPL_AGING_NEW].chance2get_var[6] = 10;
   spell[SPL_AGING_NEW].chance2get_var[7] = 10;
   spell[SPL_AGING_NEW].chance2get_var[8] = 10;
   spell[SPL_AGING_NEW].ai_value[0] = 50;
   spell[SPL_AGING_NEW].ai_value[1] = 50;
   spell[SPL_AGING_NEW].ai_value[2] = 50;
   spell[SPL_AGING_NEW].ai_value[3] = 50;
   spell[SPL_AGING_NEW].description[0] =
      "{Aging}\n\nAging Description.\n";
   spell[SPL_AGING_NEW].description[1] =
      "{Basic Aging}\n\nBasic Aging Description.\n";
   spell[SPL_AGING_NEW].description[2] =
      "{Advanced Aging}\n\nAdvanced Aging Description.\n";
   spell[SPL_AGING_NEW].description[3] =
      "{Expert Aging}\n\nExpert Aging Description.\n";

   // Death Cloud
   spell[SPL_DEATH_CLOUD_NEW].type = 0;
   spell[SPL_DEATH_CLOUD_NEW].wav_name = "Deathcld.wav";
   spell[SPL_DEATH_CLOUD_NEW].animation_ix = ANIM_DEATH_CLOUD_NEW;
   spell[SPL_DEATH_CLOUD_NEW].flags = 0x8281;
   spell[SPL_DEATH_CLOUD_NEW].name = "Death Cloud";
   spell[SPL_DEATH_CLOUD_NEW].short_name = "Death Cloud";
   spell[SPL_DEATH_CLOUD_NEW].level = 5;
   spell[SPL_DEATH_CLOUD_NEW].school_flags = SSF_EARTH;
   spell[SPL_DEATH_CLOUD_NEW].mana_cost[0] = 25;
   spell[SPL_DEATH_CLOUD_NEW].mana_cost[1] = 20;
   spell[SPL_DEATH_CLOUD_NEW].mana_cost[2] = 20;
   spell[SPL_DEATH_CLOUD_NEW].mana_cost[3] = 20;
   spell[SPL_DEATH_CLOUD_NEW].eff_power = 40;
   spell[SPL_DEATH_CLOUD_NEW].effect[0] = 30;
   spell[SPL_DEATH_CLOUD_NEW].effect[1] = 30;
   spell[SPL_DEATH_CLOUD_NEW].effect[2] = 60;
   spell[SPL_DEATH_CLOUD_NEW].effect[3] = 120;
   spell[SPL_DEATH_CLOUD_NEW].chance2get_var[0] = 10;
   spell[SPL_DEATH_CLOUD_NEW].chance2get_var[1] = 10;
   spell[SPL_DEATH_CLOUD_NEW].chance2get_var[2] = 10;
   spell[SPL_DEATH_CLOUD_NEW].chance2get_var[3] = 10;
   spell[SPL_DEATH_CLOUD_NEW].chance2get_var[4] = 10;
   spell[SPL_DEATH_CLOUD_NEW].chance2get_var[5] = 10;
   spell[SPL_DEATH_CLOUD_NEW].chance2get_var[6] = 10;
   spell[SPL_DEATH_CLOUD_NEW].chance2get_var[7] = 10;
   spell[SPL_DEATH_CLOUD_NEW].chance2get_var[8] = 10;
   spell[SPL_DEATH_CLOUD_NEW].ai_value[0] = 50;
   spell[SPL_DEATH_CLOUD_NEW].ai_value[1] = 50;
   spell[SPL_DEATH_CLOUD_NEW].ai_value[2] = 50;
   spell[SPL_DEATH_CLOUD_NEW].ai_value[3] = 50;
   spell[SPL_DEATH_CLOUD_NEW].description[0] =
      "{Death Cloud}\n\nDeath Cloud Description.\n";
   spell[SPL_DEATH_CLOUD_NEW].description[1] =
      "{Basic Death Cloud}\n\nBasic Death Cloud Description.\n";
   spell[SPL_DEATH_CLOUD_NEW].description[2] =
      "{Advanced Death Cloud}\n\nAdvanced Death Cloud Description.\n";
   spell[SPL_DEATH_CLOUD_NEW].description[3] =
      "{Expert Death Cloud}\n\nExpert Death Cloud Description.\n";

   // Death Blow
   spell[SPL_DEATH_BLOW_NEW].type = 1;
   spell[SPL_DEATH_BLOW_NEW].wav_name = "Deathblo.wav";
   spell[SPL_DEATH_BLOW_NEW].animation_ix = ANIM_DEATH_BLOW_NEW;
   spell[SPL_DEATH_BLOW_NEW].flags = 0x1015;
   spell[SPL_DEATH_BLOW_NEW].name = "Death Blow";
   spell[SPL_DEATH_BLOW_NEW].short_name = "Death Blow";
   spell[SPL_DEATH_BLOW_NEW].level = 5;
   spell[SPL_DEATH_BLOW_NEW].school_flags = SSF_FIRE;
   spell[SPL_DEATH_BLOW_NEW].mana_cost[0] = 25;
   spell[SPL_DEATH_BLOW_NEW].mana_cost[1] = 20;
   spell[SPL_DEATH_BLOW_NEW].mana_cost[2] = 20;
   spell[SPL_DEATH_BLOW_NEW].mana_cost[3] = 20;
   spell[SPL_DEATH_BLOW_NEW].eff_power = 0;
   spell[SPL_DEATH_BLOW_NEW].effect[0] = 0;
   spell[SPL_DEATH_BLOW_NEW].effect[1] = 0;
   spell[SPL_DEATH_BLOW_NEW].effect[2] = 0;
   spell[SPL_DEATH_BLOW_NEW].effect[3] = 0;
   spell[SPL_DEATH_BLOW_NEW].chance2get_var[0] = 10;
   spell[SPL_DEATH_BLOW_NEW].chance2get_var[1] = 10;
   spell[SPL_DEATH_BLOW_NEW].chance2get_var[2] = 10;
   spell[SPL_DEATH_BLOW_NEW].chance2get_var[3] = 10;
   spell[SPL_DEATH_BLOW_NEW].chance2get_var[4] = 10;
   spell[SPL_DEATH_BLOW_NEW].chance2get_var[5] = 10;
   spell[SPL_DEATH_BLOW_NEW].chance2get_var[6] = 10;
   spell[SPL_DEATH_BLOW_NEW].chance2get_var[7] = 10;
   spell[SPL_DEATH_BLOW_NEW].chance2get_var[8] = 10;
   spell[SPL_DEATH_BLOW_NEW].ai_value[0] = 50;
   spell[SPL_DEATH_BLOW_NEW].ai_value[1] = 50;
   spell[SPL_DEATH_BLOW_NEW].ai_value[2] = 50;
   spell[SPL_DEATH_BLOW_NEW].ai_value[3] = 50;
   spell[SPL_DEATH_BLOW_NEW].description[0] =
      "{Death Blow}\n\nDeath Blow Description.\n";
   spell[SPL_DEATH_BLOW_NEW].description[1] =
      "{Basic Death Blow}\n\nBasic Death Blow Description.\n";
   spell[SPL_DEATH_BLOW_NEW].description[2] =
      "{Advanced Death Blow}\n\nAdvanced Death Blow Description.\n";
   spell[SPL_DEATH_BLOW_NEW].description[3] =
      "{Expert Death Blow}\n\nExpert Death Blow Description.\n";

   // Firebird
   spell[SPL_FIREBIRD_NEW].type = 0;
   spell[SPL_FIREBIRD_NEW].wav_name = "SumnElm.wav";
   spell[SPL_FIREBIRD_NEW].animation_ix = ID_NONE;
   spell[SPL_FIREBIRD_NEW].flags = 0x80001;
   spell[SPL_FIREBIRD_NEW].name = "Firebird";
   spell[SPL_FIREBIRD_NEW].short_name = "Firebird";
   spell[SPL_FIREBIRD_NEW].level = 5;
   spell[SPL_FIREBIRD_NEW].school_flags = SSF_FIRE;
   spell[SPL_FIREBIRD_NEW].mana_cost[0] = 30;
   spell[SPL_FIREBIRD_NEW].mana_cost[1] = 25;
   spell[SPL_FIREBIRD_NEW].mana_cost[2] = 25;
   spell[SPL_FIREBIRD_NEW].mana_cost[3] = 25;
   spell[SPL_FIREBIRD_NEW].eff_power = 0;
   spell[SPL_FIREBIRD_NEW].effect[0] = 50;
   spell[SPL_FIREBIRD_NEW].effect[1] = 50;
   spell[SPL_FIREBIRD_NEW].effect[2] = 75;
   spell[SPL_FIREBIRD_NEW].effect[3] = 100;
   spell[SPL_FIREBIRD_NEW].chance2get_var[0] = 10;
   spell[SPL_FIREBIRD_NEW].chance2get_var[1] = 10;
   spell[SPL_FIREBIRD_NEW].chance2get_var[2] = 10;
   spell[SPL_FIREBIRD_NEW].chance2get_var[3] = 10;
   spell[SPL_FIREBIRD_NEW].chance2get_var[4] = 10;
   spell[SPL_FIREBIRD_NEW].chance2get_var[5] = 10;
   spell[SPL_FIREBIRD_NEW].chance2get_var[6] = 10;
   spell[SPL_FIREBIRD_NEW].chance2get_var[7] = 10;
   spell[SPL_FIREBIRD_NEW].chance2get_var[8] = 10;
   spell[SPL_FIREBIRD_NEW].ai_value[0] = 50;
   spell[SPL_FIREBIRD_NEW].ai_value[1] = 50;
   spell[SPL_FIREBIRD_NEW].ai_value[2] = 100;
   spell[SPL_FIREBIRD_NEW].ai_value[3] = 150;
   spell[SPL_FIREBIRD_NEW].description[0] =
      "{Firebird}\n\nAllows you to summon firebirds.  Once cast, no other elemental types may be summoned.\n";
   spell[SPL_FIREBIRD_NEW].description[1] =
      "{Basic Firebird}\n\nAllows you to summon firebirds.  Once cast, no other elemental types may be summoned.\n";
   spell[SPL_FIREBIRD_NEW].description[2] =
      "{Advanced Firebird}\n\nAllows you to summon firebirds.  Once cast, no other elemental types may be summoned.\n\n" \
      "Summons approximately one-and-a-half times the number of units as Basic Summon Firebird.\n";
   spell[SPL_FIREBIRD_NEW].description[3] =
      "{Expert Firebird}\n\nAllows you to summon firebirds.  Once cast, no other elemental types may be summoned.\n\n" \
      "Summons approximately twice the number of units as Basic Summon Firebird.\n";

   // Magic Elemental
   spell[SPL_MAGIC_ELEMENTAL_NEW].type = 0;
   spell[SPL_MAGIC_ELEMENTAL_NEW].wav_name = "SumnElm.wav";
   spell[SPL_MAGIC_ELEMENTAL_NEW].animation_ix = ID_NONE;
   spell[SPL_MAGIC_ELEMENTAL_NEW].flags = 0x80001;
   spell[SPL_MAGIC_ELEMENTAL_NEW].name = "Magic Elemental";
   spell[SPL_MAGIC_ELEMENTAL_NEW].short_name = "Magic Elemental";
   spell[SPL_MAGIC_ELEMENTAL_NEW].level = 5;
   spell[SPL_MAGIC_ELEMENTAL_NEW].school_flags = SSF_AIR | SSF_FIRE | SSF_WATER | SSF_EARTH;
   spell[SPL_MAGIC_ELEMENTAL_NEW].mana_cost[0] = 30;
   spell[SPL_MAGIC_ELEMENTAL_NEW].mana_cost[1] = 25;
   spell[SPL_MAGIC_ELEMENTAL_NEW].mana_cost[2] = 25;
   spell[SPL_MAGIC_ELEMENTAL_NEW].mana_cost[3] = 25;
   spell[SPL_MAGIC_ELEMENTAL_NEW].eff_power = 0;
   spell[SPL_MAGIC_ELEMENTAL_NEW].effect[0] = 100;
   spell[SPL_MAGIC_ELEMENTAL_NEW].effect[1] = 100;
   spell[SPL_MAGIC_ELEMENTAL_NEW].effect[2] = 150;
   spell[SPL_MAGIC_ELEMENTAL_NEW].effect[3] = 200;
   spell[SPL_MAGIC_ELEMENTAL_NEW].chance2get_var[0] = 10;
   spell[SPL_MAGIC_ELEMENTAL_NEW].chance2get_var[1] = 10;
   spell[SPL_MAGIC_ELEMENTAL_NEW].chance2get_var[2] = 10;
   spell[SPL_MAGIC_ELEMENTAL_NEW].chance2get_var[3] = 10;
   spell[SPL_MAGIC_ELEMENTAL_NEW].chance2get_var[4] = 10;
   spell[SPL_MAGIC_ELEMENTAL_NEW].chance2get_var[5] = 10;
   spell[SPL_MAGIC_ELEMENTAL_NEW].chance2get_var[6] = 10;
   spell[SPL_MAGIC_ELEMENTAL_NEW].chance2get_var[7] = 10;
   spell[SPL_MAGIC_ELEMENTAL_NEW].chance2get_var[8] = 10;
   spell[SPL_MAGIC_ELEMENTAL_NEW].ai_value[0] = 50;
   spell[SPL_MAGIC_ELEMENTAL_NEW].ai_value[1] = 50;
   spell[SPL_MAGIC_ELEMENTAL_NEW].ai_value[2] = 100;
   spell[SPL_MAGIC_ELEMENTAL_NEW].ai_value[3] = 150;
   spell[SPL_MAGIC_ELEMENTAL_NEW].description[0] =
      "{Magic Elemental}\n\nAllows you to summon magic elementals.  Once cast, no other elemental types may be summoned.\n";
   spell[SPL_MAGIC_ELEMENTAL_NEW].description[1] =
      "{Basic Magic Elemental}\n\nAllows you to summon magic elementals.  Once cast, no other elemental types may be summoned.\n";
   spell[SPL_MAGIC_ELEMENTAL_NEW].description[2] =
      "{Advanced Magic Elemental}\n\nAllows you to summon magic elementals.  Once cast, no other elemental types may be summoned.\n\n" \
      "Summons approximately one-and-a-half times the number of units as Basic Summon Magic Elemental.\n";
   spell[SPL_MAGIC_ELEMENTAL_NEW].description[3] =
      "{Expert Magic Elemental}\n\nAllows you to summon magic elementals.  Once cast, no other elemental types may be summoned.\n\n" \
      "Summons approximately twice the number of units as Basic Summon Magic Elemental.\n";

   _PI->WriteDword(0x687FA8, (int)&spell);

   // Magic Animation Table
   for (int i = 0; i < ANIM_FEAR_NEW; ++i)
      anim[i] = o_MagicAnim[i];

   // Fear
   anim[ANIM_FEAR_NEW].defName = "C07spE0.def";
   anim[ANIM_FEAR_NEW].name = "Fear";
   anim[ANIM_FEAR_NEW].type = 0x101;

   // Poison
   anim[ANIM_POISON_NEW].defName = "sp11_.def";
   anim[ANIM_POISON_NEW].name = "Poison";
   anim[ANIM_POISON_NEW].type = 1;

   // Disease
   anim[ANIM_DISEASE_NEW].defName = "sp05_.def";
   anim[ANIM_DISEASE_NEW].name = "Disease";
   anim[ANIM_DISEASE_NEW].type = 1;

   // Aging
   anim[ANIM_AGING_NEW].defName = "sp01_.def";
   anim[ANIM_AGING_NEW].name = "Aging";
   anim[ANIM_AGING_NEW].type = 1;

   // Death Cloud
   anim[ANIM_DEATH_CLOUD_NEW].defName = "sp04_.def";
   anim[ANIM_DEATH_CLOUD_NEW].name = "DeathCloud";
   anim[ANIM_DEATH_CLOUD_NEW].type = 1;

   // Death Blow
   anim[ANIM_DEATH_BLOW_NEW].defName = "sp03_.def";
   anim[ANIM_DEATH_BLOW_NEW].name = "DeathBlow";
   anim[ANIM_DEATH_BLOW_NEW].type = 1;

   int AnimAddrDefName[] = {0x43F77E, 0x43FB6A, 0x4963FB, 0x4965CF, 0x5A5036, 0x5A6B14, 0x5A7A74, 0x5A962C};
   int AnimAddrName[] = {0x4689C4, 0x49651A, 0x4966CD, 0x5A6D2D, 0x5A7B06};
   
   for (int i = 0; i < sizeof(AnimAddrDefName) / sizeof(int); ++i)
      _PI->WriteDword(AnimAddrDefName[i], (int)&anim->defName);

   for (int i = 0; i < sizeof(AnimAddrName) / sizeof(int); ++i)
      _PI->WriteDword(AnimAddrName[i], (int)&anim->name);

   _PI->WriteDword(0x43E503, (int)&anim->type);
   
   return EXEC_DEFAULT;
}

int __stdcall disableCreatureSpells(LoHook* h, HookContext* c)
{
   for (int i = SPL_STONE; i <= SPL_ACID_BREATH; ++i)
      o_GameMgr->disabled_shrines[i] = true;

   return EXEC_DEFAULT;
}

int __stdcall shrineSpellsInit(LoHook* h, HookContext* c)
{
   for (int i = SPL_STONE; i <= SPL_ACID_BREATH; ++i)
      o_GameMgr->disabled_shrines[i] = true;   
   
   memcpy(&shrineSpells, &o_GameMgr->disabled_shrines, sizeof(shrineSpells) / sizeof(bool));   

   c->return_address = 0x4C2641;
   return NO_EXEC_DEFAULT;
}

int __fastcall fillShrines(_GameMgr_* game, int unused_edx, int shrineFlags)
{
   int availSpellsNum = 0;

   for (int i = 0; i < SPELLS_NUM; ++i)
   {
      int lvl = o_Spell[i].level - 1;
      if (lvl < 5 && 1 << lvl & shrineFlags && o_Spell[i].school_flags && !shrineSpells[i])
         ++availSpellsNum;
   }

   int spell = 0;
   int chosenSpell = 0;

   if (availSpellsNum)
   {
      int rndSpell = Randint(0, availSpellsNum - 1);
     
      for (int i = 0; i < SPELLS_NUM; ++i)
      {
         int lvl = o_Spell[i].level - 1;
         if (lvl < 5 && 1 << lvl & shrineFlags && o_Spell[i].school_flags && !shrineSpells[i])
         {
            if (spell == rndSpell) break;
            ++spell;
         }
         ++chosenSpell;
      }
     
      shrineSpells[chosenSpell] = true;
   }
   else
   {
      spell = 0;
     
      for (int i = 0; i < SPELLS_NUM; ++i)
      {
         int lvl = o_Spell[i].level - 1;
         if (lvl < 5 && 1 << lvl & shrineFlags && o_Spell[i].school_flags && !game->disabled_shrines[i])
         {
            shrineSpells[i] = false;
            ++spell;
         }
      }
     
      chosenSpell = spell ? fillShrines(game, unused_edx, shrineFlags) : ID_NONE;
   }

   return chosenSpell;
}

int __stdcall Disease(LoHook* h, HookContext* c)
{
   if (c->ebx == 33)
   {
      _Hero_* hero = *(_Hero_**)(c->ebp + 0x14);
      _BattleStack_* stack = (_BattleStack_*)c->esi;
      int schoolLevel = c->eax;
      int effect = 0;
         
      diseaseSpellParams[stack->side][stack->index_on_side].AttackPenalty = diseaseSpell[schoolLevel].AttackPenalty;
      diseaseSpellParams[stack->side][stack->index_on_side].DefensePenalty = diseaseSpell[schoolLevel].DefensePenalty;
      diseaseSpellParams[stack->side][stack->index_on_side].SpeedPenalty = diseaseSpell[schoolLevel].SpeedPenalty; // %

      // optional, as we don't have heroes with Disease spell specialty yet
      if (hero)
      {
         effect = CALL_4(int, __thiscall, 0x4E6260, hero, SPL_DISEASE_NEW, hero->level, effect);
         diseaseSpellParams[stack->side][stack->index_on_side].AttackPenalty += effect;
         diseaseSpellParams[stack->side][stack->index_on_side].DefensePenalty += effect;
         diseaseSpellParams[stack->side][stack->index_on_side].SpeedPenalty += effect; // %
      }

      stack->creature.attack -= diseaseSpellParams[stack->side][stack->index_on_side].AttackPenalty;
      stack->creature.defence -= diseaseSpellParams[stack->side][stack->index_on_side].DefensePenalty;
     
      // not allowing attack and defense to drop below 0
      if (stack->creature.attack < 0)
      {
         diseaseSpellParams[stack->side][stack->index_on_side].AttackPenalty += stack->creature.attack;
         stack->creature.attack = 0;
      }

      if (stack->creature.defence < 0)
      {
         diseaseSpellParams[stack->side][stack->index_on_side].DefensePenalty += stack->creature.defence;
         stack->creature.defence = 0;
      }

      if (!(stack->creature.flags & BCF_CANT_MOVE))
      {
         diseaseSpellParams[stack->side][stack->index_on_side].SpeedPenalty =
            stack->creature.speed * diseaseSpellParams[stack->side][stack->index_on_side].SpeedPenalty / 100;

         if (diseaseSpellParams[stack->side][stack->index_on_side].SpeedPenalty < 1)
            diseaseSpellParams[stack->side][stack->index_on_side].SpeedPenalty = 1;

         stack->creature.speed -= diseaseSpellParams[stack->side][stack->index_on_side].SpeedPenalty;
         if (stack->creature.speed < 1)
         {
            diseaseSpellParams[stack->side][stack->index_on_side].SpeedPenalty += stack->creature.speed - 1;
            stack->creature.speed = 1;
         }
      }

      c->return_address = 0x444D5C;
      return NO_EXEC_DEFAULT;
   }

   return EXEC_DEFAULT;
}

int __stdcall resetNewSpells(LoHook* h, HookContext* c)
{
   if (c->ecx == 10)
   {
      _BattleStack_* stack = (_BattleStack_*)c->esi;

      stack->creature.attack += diseaseSpellParams[stack->side][stack->index_on_side].AttackPenalty;
      stack->creature.defence += diseaseSpellParams[stack->side][stack->index_on_side].DefensePenalty;

      if (!(stack->creature.flags & BCF_CANT_MOVE))
         stack->creature.speed += diseaseSpellParams[stack->side][stack->index_on_side].SpeedPenalty;

      c->return_address = 0x4444E1;
      return NO_EXEC_DEFAULT;
   }

   return EXEC_DEFAULT;
}

int __stdcall DeathCloud(LoHook* h, HookContext* c)
{
   if (c->edx == SPL_DEATH_CLOUD_NEW)
   {
      CALL_5(void, __thiscall, 0x5A4C80, o_BattleMgr, *(int*)(c->ebp + 0xC), SPL_DEATH_CLOUD_NEW, c->esi, *(int*)(c->ebp + 0x1C));
   
      c->return_address = 0x5A2368;
      return NO_EXEC_DEFAULT;
   }

   return EXEC_DEFAULT;
}

int __stdcall SummonCreatures(LoHook* h, HookContext* c)
{
   if (c->ecx == 38 || c->ecx == 39)
   {
      int spell;
      int creature;

      switch (c->ecx)
      {
      case 38:
         spell = SPL_FIREBIRD_NEW;
         creature = CID_FIREBIRD;
         break;
      case 39:
         spell = SPL_MAGIC_ELEMENTAL_NEW;
         creature = CID_MAGIC_ELEMENTAL;
         break;
      }

      CALL_5(void, __thiscall, 0x5A7390, o_BattleMgr, spell, creature, *(int*)(c->ebp + 0x1C), c->esi);
   
      c->return_address = 0x5A2368;
      return NO_EXEC_DEFAULT;
   }

   return EXEC_DEFAULT;
}

int __stdcall setSummonedCreaturesNumber(LoHook* h, HookContext* c)
{
   int creature = *(int*)(c->ebp + 0xC);
   int sp = *(int*)(c->ebp + 0x10);
   int schoolLevel = *(int*)(c->ebp + 0x14);

   if (creature == CID_FIREBIRD)
      c->esi = o_Spell[SPL_FIREBIRD_NEW].effect[schoolLevel] * sp / 100;
   else if (creature == CID_MAGIC_ELEMENTAL)
      c->esi = o_Spell[SPL_MAGIC_ELEMENTAL_NEW].effect[schoolLevel] * sp / 100;
   else
      return EXEC_DEFAULT;

   if (c->esi < 1) c->esi = 1;
   
   c->return_address = 0x5A7526;
   return NO_EXEC_DEFAULT;
}

int __stdcall checkSummonedCreaturesType(LoHook* h, HookContext* c)
{
   int spell = c->ebx;

   switch (spell)
   {
   case SPL_FIRE_ELEMENTAL:
      c->eax = CID_FIRE_ELEMENTAL;
      break;
   case SPL_EARTH_ELEMENTAL:
      c->eax = CID_EARTH_ELEMENTAL;
      break;
   case SPL_WATER_ELEMENTAL:
      c->eax = CID_WATER_ELEMENTAL;
      break;
   case SPL_AIR_ELEMENTAL:
      c->eax = CID_AIR_ELEMENTAL;
      break;
   case SPL_FIREBIRD_NEW:
      c->eax = CID_FIREBIRD;
      break;
   case SPL_MAGIC_ELEMENTAL_NEW:
      c->eax = CID_MAGIC_ELEMENTAL;
      break;
   default:
      c->eax = ID_NONE;
   }
   
   c->return_address = 0x59F8B7;
   return NO_EXEC_DEFAULT;
}

void __fastcall updateSpellsFromArtifacts(_Hero_* hero)
{
   for (int iSpell = 0; iSpell < SPELLS_MAX; ++iSpell)
      if (hero->spell[iSpell] > 1) hero->spell[iSpell] = 0;

   for (int iSlot = 0; iSlot < 19; ++iSlot)
   {
      if (hero->doll_art[iSlot].id != ID_NONE)
      {
         if (hero->doll_art[iSlot].id == AID_SPELL_SCROLL)
         {
            if (hero->doll_art[iSlot].mod < SPELLS_NUM && !hero->spell[hero->doll_art[iSlot].mod])
               hero->spell[hero->doll_art[iSlot].mod] = 2;
         }
         else if (o_ArtInfo[hero->doll_art[iSlot].id].new_spell)
         {
            std::bitset<SPELLS_MAX> spells;
            CALL_2(int, __fastcall, 0x4D95C0, &spells, hero->doll_art[iSlot].id);

            for (std::size_t iSpell = 0; iSpell < spells.size(); ++iSpell)
            {
               if (spells[iSpell] && !hero->spell[iSpell])
                  hero->spell[iSpell] = 2;
            }

            int comboArtIndex = o_ArtInfo[hero->doll_art[iSlot].id].supercomposite;
            if (comboArtIndex != -1)
            {
               for (int iArt = 0; iArt < ARTIFACTS_NUM; ++iArt)
               {
                  if (o_ComboArtInfo[comboArtIndex].parts[iArt] && o_ArtInfo[iArt].new_spell)
                  {
                     std::bitset<SPELLS_MAX> spells;
                     CALL_2(int, __fastcall, 0x4D95C0, &spells, iArt);

                     for (std::size_t iSpell = 0; iSpell < spells.size(); ++iSpell)
                     {
                        if (spells[iSpell] && !hero->spell[iSpell])
                           hero->spell[iSpell] = 2;
                     }
                  }
               }
            }
         }
      }
   }
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
   static bool plugin_On = false;
   if ( DLL_PROCESS_ATTACH == ul_reason_for_call )
   {
      if ( !plugin_On )
      {
         plugin_On = true;
         _P = GetPatcher();
         _PI = _P->CreateInstance("HD.Plugin.H3.NewSpells");

         //GetCurrentDirectoryA(sizeof(iniPath), iniPath);
         //strcat(iniPath, "\\NewSpells.ini");

         // Moving and Expanding Spell Table
         _PI->WriteLoHook(0x4EE1C1, afterInit);
               
         // nwcthereisnospoon
         _PI->WriteByte (0x402902, SPELLS_NUM);

         // "(Already learned)" Text
         _PI->WriteDword(0x40D97C, 0x3EA);
         
         // AI
         _PI->WriteDword(0x41FBDF, 0x3EA);
         _PI->WriteByte (0x41FC91, SPELLS_NUM);
         _PI->WriteDword(0x425C72, 0x3EA);
         _PI->WriteDword(0x425E98, SPELLS_NUM * sizeof(_Spell_));
         _PI->WriteDword(0x427039, 0x3EA);
         _PI->WriteDword(0x427044, 0x3EA);
         _PI->WriteByte (0x427085, SPELLS_NUM);
         _PI->WriteDword(0x4329C1, 0x3EA);
         _PI->WriteDword(0x432A43, SPELLS_NUM * sizeof(_Spell_));
         _PI->WriteDword(0x432CDE, 0x3EA);
         _PI->WriteDword(0x432D1E, SPELLS_NUM * sizeof(_Spell_));
         // ------------
         // Adventure AI
         // ------------
         _PI->WriteDword(0x430AE5, 0x3EA + SPL_DIMENSION_DOOR);
         _PI->WriteDword(0x4E57CC, 0x3EA + SPL_SUMMON_BOAT);
         _PI->WriteDword(0x56B346, 0x3EA + SPL_TOWN_PORTAL);
         _PI->WriteDword(0x56B7EA, 0x3EA + SPL_DIMENSION_DOOR);
         _PI->WriteDword(0x56B93F, 0x3EA + SPL_FLY);
         _PI->WriteDword(0x56B99A, 0x3EA + SPL_WATER_WALK);
         // Battle AI
         _PI->WriteDword(0x43C6F2, SPELLS_NUM * sizeof(_Spell_));
         // Master Genie AI Spell Weighting
         _PI->WriteDword(0x43C21B, SPELLS_NUM * sizeof(_Spell_));
         // AI Quick Battle
         _PI->WriteDword(0x433026, 0x3EA);
         _PI->WriteDword(0x433719, 0x3EA);
         _PI->WriteDword(0x43940C, 0x3EA);
         _PI->WriteDword(0x43C561, 0x3EA);
         // AI Spell Scrolls?
         _PI->WriteDword(0x52A97A, 0x3EA);
         _PI->WriteDword(0x52A9B6, SPELLS_NUM * sizeof(_Spell_));
         
         // Can cast?
         _PI->WriteDword(0x447551, SPELLS_NUM * sizeof(_Spell_));
         
         _PI->WriteDword(0x447C7D, SPELLS_NUM * sizeof(_Spell_));
         _PI->WriteDword(0x447CC8, SPELLS_NUM * sizeof(_Spell_));
         
         // Cheats in battle
         _PI->WriteByte (0x471C57, SPELLS_NUM);
         
         // Clear _Hero_.spell[140] (optional)
         _PI->WriteDword(0x48647A, 0x23);
         _PI->WriteJmp  (0x486485, 0x486498);
         
         _PI->WriteByte (0x4864B0, SPELLS_NUM);
         
         // Load Game?
         _PI->WriteByte (0x48A34B, SPELLS_NUM);
         
         // Scholar Secondary Skill
         _PI->WriteByte (0x4A2743, SPELLS_NUM);

         // New Game?
         _PI->WriteByte (0x4C244D, SPELLS_NUM);
         _PI->WriteByte (0x4C246F, SPELLS_NUM);
         _PI->WriteDword(0x4C24C9, SPELLS_NUM * sizeof(_Spell_));
         _PI->WriteByte (0x4C250E, SPELLS_NUM);
         _PI->WriteDword(0x4C2557, SPELLS_NUM * sizeof(_Spell_));
         _PI->WriteDword(0x4C260D, SPELLS_NUM * sizeof(_Spell_));

         _PI->WriteByte (0x4E67AC, SPELLS_NUM);
         
         // Cheat Menu?
         _PI->WriteByte (0x4F508B, SPELLS_NUM);
         _PI->WriteDword(0x4F50CE, SPELLS_NUM * sizeof(_Spell_));
         _PI->WriteDword(0x4F5114, SPELLS_NUM * sizeof(_Spell_));
                           
         // Pyramids
         _PI->WriteByte (0x4C170D, SPELLS_NUM);
                 
         // Shrines
         _PI->WriteDword(0x4C92C5, SPELLS_NUM * sizeof(_Spell_));
         _PI->WriteDword(0x4C9347, SPELLS_NUM * sizeof(_Spell_));
         _PI->WriteDword(0x4C93C0, SPELLS_NUM * sizeof(_Spell_));
         
         _PI->WriteByte (0x4CEC4F, SPELLS_NUM);
         
         // Clear _Hero_.spell[140] (optional)
         _PI->WriteDword(0x4D8F2E, 0x23);
         _PI->WriteJmp  (0x4D8F36, 0x4D8F49);
         
         _PI->WriteByte (0x4D8F53, SPELLS_NUM);
         _PI->WriteByte (0x4D8F8A, SPELLS_NUM);
         
         // Tome of Air Magic
         _PI->WriteDword(0x4D962D, SPELLS_NUM * sizeof(_Spell_));
         // Tome of Fire Magic
         _PI->WriteDword(0x4D9681, SPELLS_NUM * sizeof(_Spell_));
         // Tome of Water Magic
         _PI->WriteDword(0x4D96D6, SPELLS_NUM * sizeof(_Spell_));
         // Tome of Earth Magic
         _PI->WriteDword(0x4D972E, SPELLS_NUM * sizeof(_Spell_));
         // Spellbinder's Hat
         _PI->WriteDword(0x4D9771, SPELLS_NUM * sizeof(_Spell_));
         
         // Scholars
         _PI->WriteByte (0x5012B7, SPELLS_NUM);
         
         _PI->WriteDword(0x527ACB, 0x3EA);
         _PI->WriteDword(0x527B08, SPELLS_NUM * sizeof(_Spell_));

         // RMG
         _PI->WriteDword(0x534C4B, SPELLS_NUM * sizeof(_Spell_));
         
         // RMG Spell Scrolls
         _PI->WriteDword(0x5353D5, SPELLS_NUM);
         _PI->WriteByte (0x53542B, SPELLS_NUM);
         
         // Spell Book
         _PI->WriteDword(0x59CD5E, 0x3EA);
         _PI->WriteDword(0x59CDBF, SPELLS_NUM * sizeof(_Spell_));

         // Cast Spell
         _PI->WriteDword(0x5A1AD6, SPELLS_NUM * sizeof(_Spell_));

         // Mage Guild
         _PI->WriteByte (0x5BEA2C, SPELLS_NUM);
         _PI->WriteByte (0x5BEA70, SPELLS_NUM);
         _PI->WriteByte (0x5BEAAD, SPELLS_NUM);
         _PI->WriteDword(0x5BEAFE, SPELLS_NUM * sizeof(_Spell_));
         _PI->WriteDword(0x5BEB2C, SPELLS_NUM * sizeof(_Spell_));
         _PI->WriteByte (0x5BEB48, SPELLS_NUM);
         _PI->WriteByte (0x5BEB71, SPELLS_NUM);
         _PI->WriteByte (0x5BEBB2, SPELLS_NUM);
         _PI->WriteDword(0x5BEC05, SPELLS_NUM * sizeof(_Spell_));
         _PI->WriteByte (0x5BEC1B, SPELLS_NUM);
                 
         // Conflux Grail
         _PI->WriteDword(0x5BE512, SPELLS_NUM * sizeof(_Spell_));
         _PI->WriteDword(0x5BE56E, SPELLS_NUM * sizeof(_Spell_));
         _PI->WriteDword(0x5D7464, SPELLS_NUM);
         
         // ---------------------------
         // New _Hero_.spell[140] field
         // ---------------------------
         _PI->WriteCodePatch(0x4D8B72, "%n", 8);
         _PI->WriteCodePatch(0x4D8F7F, "%n", 8);
         _PI->WriteCodePatch(0x4D95AF, "%n", 7);

         // ----------------------------------------
         // New _GameMgr_.disabled_spells[140] field
         // ----------------------------------------
         _PI->WriteByte(0x4C16ED, 4); // Pyramids
         _PI->WriteByte(0x4C254C, 4); // Titan's Lightning Bolt
         _PI->WriteByte(0x4C25F1, 4); // Titan's Lightning Bolt
         _PI->WriteByte(0x501297, 4); // Scholars
         _PI->WriteByte(0x5BEA55, 4); // Mage Guild
                         
         _PI->WriteDword(0x52AE1C, 0x3EA);

         // ------
         // Battle
         // ------
         _PI->WriteByte (0x4963E9, ANIMS_NUM);
         _PI->WriteByte (0x4965BD, ANIMS_NUM);
         _PI->WriteByte (0x502405, SPELLS_NUM);
         _PI->WriteByte (0x502451, SPELLS_NUM);
         _PI->WriteByte (0x5024CF, SPELLS_NUM);
         _PI->WriteByte (0x502515, SPELLS_NUM);
         _PI->WriteByte (0x502E62, SPELLS_NUM);
         _PI->WriteByte (0x502EB7, SPELLS_NUM);
         _PI->WriteByte (0x59EFD9, SPELLS_NUM - 1 - ADVSPELLS_NUM);
         _PI->WriteDword(0x59EFE4, (int)&spellIndirectTableA);
         _PI->WriteByte (0x5A064E, SPELLS_NUM - 1 - ADVSPELLS_NUM);
         _PI->WriteDword(0x5A0659, (int)&spellIndirectTableB);
         _PI->WriteByte (0x4446EA, SPELLS_NUM - 1 - SPL_SHIELD);
         _PI->WriteDword(0x4446FD, (int)&spellIndirectTableC);
         _PI->WriteByte (0x444262, SPELLS_NUM - 1 - SPL_WEAKNESS);
         _PI->WriteDword(0x44427A, (int)&spellIndirectTableD);
                 
         // --------------------------------------------------
         // New _BattleStack_.active_spell_duration[162] field
         // --------------------------------------------------
         _PI->WriteDword(0x43787A, 162);
         _PI->WriteCodePatch(0x437880, "%n", 19);
         _PI->WriteDword(0x43D314, 162);
         _PI->WriteDword(0x43E3DF, SPELLS_NUM);
         _PI->WriteByte (0x443F63, SPELLS_NUM);
         _PI->WriteByte (0x446F03, SPELLS_NUM);
         _PI->WriteByte (0x5A1907, SPELLS_NUM);
         _PI->WriteByte (0x5A1995, SPELLS_NUM);
         _PI->WriteByte (0x5A84C8, SPELLS_NUM);
         _PI->WriteByte (0x5A852F, SPELLS_NUM);
         _PI->WriteCodePatch(0x4446D2, "%n", 7);
         _PI->WriteCodePatch(0x4446D2, "%n", 7);
         _PI->WriteJmp  (0x444694, 0x4450C2);
         
         // Disable creature spells
         _PI->WriteLoHook(0x4C2567, disableCreatureSpells);

         // Shrine Spells
         _PI->WriteLoHook(0x4C2625, shrineSpellsInit);
         _PI->WriteHiHook(0x4C9260, SPLICE_, DIRECT_, THISCALL_, fillShrines);
         
         // Disease
         _PI->WriteLoHook(0x444701, Disease);
         _PI->WriteLoHook(0x44427E, resetNewSpells);

         // Death Cloud
         _PI->WriteLoHook(0x5A0F4C, DeathCloud);

         // Firebird, Magic Elemental
         _PI->WriteLoHook(0x59F889, checkSummonedCreaturesType);
         _PI->WriteLoHook(0x5A065D, SummonCreatures);
         _PI->WriteLoHook(0x5A7516, setSummonedCreaturesNumber);
         
         // Artifacts (incl. Spell Scrolls);
         _PI->WriteHiHook(0x4D9840, SPLICE_, DIRECT_, THISCALL_, updateSpellsFromArtifacts);
      }
   }

   return TRUE;
}

Т.к. это заклинание новое, то к нему только стандартные иммунитеты. На какие группы монстров оно не должно действовать? Делаем иммунитеты как против абилки Зомби?
Вернуться к началу

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

Re: Как создать плагин для HD мода

Сообщение Rolex » 27 авг 2021, 16:52

AlexSpl писал(а):

На какие группы монстров оно не должно действовать? Делаем иммунитеты как против абилки Зомби?

Я думаю, да, как против абилки Зомби. А на кого не действует абилка Зомби, кроме полностью иммунных и драконов с иммунитетом до 3-го и до 4-го?
Вернуться к началу

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: Как создать плагин для HD мода

Сообщение AlexSpl » 27 авг 2021, 16:54

Я не помню. Но странно выглядело бы, если бы "болела" нежить и конструкты.
Вернуться к началу

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

Re: Как создать плагин для HD мода

Сообщение Rolex » 27 авг 2021, 17:00

Нужно проверить может ли Зомби наложить Болезнь на Зомби. Если может, то значит будем делать, чтобы и нежить болела. Также с Големами и Горгулями нужно проверить в схватке с Зомби наклыдвается ли Болезнь в оригинале и делать также.
Вернуться к началу

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: Как создать плагин для HD мода

Сообщение AlexSpl » 27 авг 2021, 17:02

Итого у нас уже 4 новых рабочих заклинания. Для них осталось написать функции взвешивания и разрешить кастовать AI. Плагин готов на 70% :smile20:
Вернуться к началу

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

Re: Как создать плагин для HD мода

Сообщение Rolex » 27 авг 2021, 17:30

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

Кстати, а Вы так и не отписались насчет active_spells_power[]. Ставили брейкпоинты на чтение/запись? Используется он вообще хоть где-нибудь?

AlexSpl писал(а):

Итого у нас уже 4 новых рабочих заклинания.

Ну да, уже половина. Если идти по нарастанию сложности, то дальше у нас Death Blow. Его можно пилить на основе Бешенства (длительность) и абилки Рыцарей Смерти, только не отнимать Защиту и не прибавлять Атаку, а просто удваивать конечный урон.

После у нас останется тройка самых сложных: Aging, Poison и Fear.
Вернуться к началу

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: Как создать плагин для HD мода

Сообщение AlexSpl » 27 авг 2021, 17:38

Цитата:
Кстати, а Вы так и не отписались насчет active_spells_power[]. Используется он вообще хоть где-нибудь?

В известном мне коде - нет. Если увижу, что используется (что вряд ли), перенесу полe в код плагина.

Цитата:
После у нас останется тройка самых сложных: Aging, Poison и Fear.

Следующее - Aging, и оно легче реализуется, чем Disease. Самые сложные будут Fear и Death Blow (хотя мне лично Death Blow не нравится).

Ещё нужно подумать над весами заклинаний для генерации в гильдии магии. Предлагаю отзеркалить веса Prayer для Disease. Над весами остальных тоже нужно подумать (сейчас по 10 для каждого города).
Вернуться к началу

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

Re: Как создать плагин для HD мода

Сообщение Rolex » 27 авг 2021, 17:45

AlexSpl писал(а):

хотя мне лично Death Blow не нравится

Ну да, в сравнении с другими, которые мы добавляем, оно смотрится бледновато. Но там фишка в том, что урон увеличивается без ущерба к защите не только во время атаки, но и во время ответки в течении 1 раунда, как у Бешенства.
Последний раз редактировалось Rolex 27 авг 2021, 17:47, всего редактировалось 2 раз(а).
Вернуться к началу

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: Как создать плагин для HD мода

Сообщение AlexSpl » 27 авг 2021, 17:46

Цитата:
Ну да, в сравнении с другими, которые мы добавляем, оно смотрится бледновато. Но там фишка в том, что урон увеличивается без ущерба к защите не только во время атаки, но во время ответки в течении 1 раунда, как у Бешенства.

Может, сделать его круче? Только как, чтобы было реально востребовано?

Сейчас Disease почти противоположность Prayer. Fear возвращаем как legacy заклинание (можно будет отключить любое из новых в ini). Poison, Aging, Death Cloud и вызов существ смотрятся естественно, т.к. аналоги присутствуют в оригинале. Только Death Blow выбивается из общей картины.
Последний раз редактировалось AlexSpl 27 авг 2021, 17:51, всего редактировалось 2 раз(а).
Вернуться к началу

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

Re: Как создать плагин для HD мода

Сообщение Rolex » 27 авг 2021, 17:49

Нужно подумать. Проблема в том, что оно напоминает Благословение и Бешенство. Процент я и так сделал высокий - 50%/75%/100%. Можно еще сделать длительность в 1/2/3 раунда в зависмоти от развития школы.
Вернуться к началу

Пред.След.

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

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

Сейчас этот форум просматривают: GoGo.Ru [Bot] и гости: 3

cron