-
AlexSpl
имя: Александр
- Эксперт
-
- Сообщения: 5587
- Зарегистрирован: 17 сен 2010, 12:58
- Пол:
- Награды: 14
-
-
- Поблагодарили: 2185 раз.
|
AlexSpl » 23 авг 2021, 21:51
Думаю, как добавлю адреса из MoP, многое заработает Я только переживаю за active_spells_power[]. Так не хочется переносить... Представляю, как больно было переписывать функцию updateSpellsFromArtifacts(). Попробуй потом разберись в коде на asm, а на C++ через битсеты - всё красиво и понятно. С дополнениями из MoP... ...теми, что пока разобрал: - Код: Выделить всё
#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 87 #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 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 };
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 };
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, 32, 32, 32, 32 };
bool shrineSpells[SPELLS_MAX];
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 = 8; 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 = 8; 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 = 0x1015; 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 = 8; 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] = 0; spell[SPL_DISEASE_NEW].effect[1] = 0; spell[SPL_DISEASE_NEW].effect[2] = 0; spell[SPL_DISEASE_NEW].effect[3] = 0; 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";
// 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 = 2; 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 = 8; 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 = 2; 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";
_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 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; }
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->WriteDword(0x43E3DF, SPELLS_NUM); _PI->WriteByte (0x443F63, SPELLS_NUM); _PI->WriteByte (0x446F03, SPELLS_NUM); _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->WriteDword(0x4446FD, (int)&spellIndirectTableC); // -------------------------------------------------- // New _BattleStack_.active_spell_duration[162] field // -------------------------------------------------- _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); // Death Cloud _PI->WriteLoHook(0x5A0F4C, DeathCloud);
// Artifacts (incl. Spell Scrolls); _PI->WriteHiHook(0x4D9840, SPLICE_, DIRECT_, THISCALL_, updateSpellsFromArtifacts); } }
return TRUE; }
* * * Как-то не обращал раньше внимания: градации цвета прямоугольника с числом воинов в отряде - это фишка HD мода? Вроде, в оригинале был только зелёный, красный и жёлтый для положительных, отрицательных и смешанных эффектов соответственно.
|