|
|
MisterGoblin

 
Tavern Dweller
|
posted January 21, 2026 03:20 PM |
|
|
Need some help from pros.
Where can i find in exe code for Titan's bolt, so i can add it to pool of spells. I tried to remove this option, as mentioned in BTB's guide, but it doesn't work:
BYTE 2, BIT 6 (20)
------------------
Only used on Titan's Bolt. Indicates an artifact-only spell, and is presumably related to preventing it
from appearing via other means (i.e. mage guilds, shrines, tomes).
____________
|
|
MisterGoblin

 
Tavern Dweller
|
posted January 25, 2026 10:25 PM |
|
|
MisterGoblin said: Need some help from pros.
Where can i find in exe code for Titan's bolt, so i can add it to pool of spells. I tried to remove this option, as mentioned in BTB's guide, but it doesn't work:
BYTE 2, BIT 6 (20)
------------------
Only used on Titan's Bolt. Indicates an artifact-only spell, and is presumably related to preventing it
from appearing via other means (i.e. mage guilds, shrines, tomes).
Spell does genberate after changing of that bit (silently) if you give none 0 values to magic guild in towns, it can appear, but it won't appear in "tomes of magic" or other artifacts that could generate spell. Who knows where to find code/offsets for magic tomes?
____________
|
|
Icewolf11

 
Tavern Dweller
|
posted January 26, 2026 08:08 PM |
|
|
Ok, maybe someone can help me out here.
I tried moving the +1 Luck ability from Halflings to Horned Demons.
According to BTB's guide there are 3 offsets that need to be changed.
03DCE2/04C134/04C134
BTB actually made a little mistake here and just put the second offset twice instead of a third one.
But to me it looks like I found it at offset 4B11E.
Now to the problem:
I canged all 3 of them to the unit ID of the Horned Demon and on the adventure map the demons actually seem to have +1 Luck.
When in a battle thougth they still have neutral Luck and the right click info reads
"creature name always has positive luck"
"Spell -1"
And I tested it, they can't get lucky (or unlucky) hits, Halflings still get +1 luck in battle despite seemingly loosing it in the hero panel on the adventure map.
So is there some other check that still looks for Halflings when in battle? Did I get the wrong offset for the third ID change?
Does someone know what is happening here and could lend me a hand?
|
|
AlexSpl

   
    
Responsible
Supreme Hero
|
posted January 27, 2026 12:09 PM |
|
|
You can see a disclaimer on the line 69 -
--- THIS GUIDE MAKES ABSOLUTELY NO GUARANTEE ABOUT EDITING HOTA ---
So, this is the case 
Quote: So is there some other check that still looks for Halflings when in battle?
Yep, and it's inside one of many HotA hooks. You have to look relevant code in HotA.dll, and it's probably not a task you are up to.
Quote: Did I get the wrong offset for the third ID change?
Nope. You found a correct address.
|
|
Icewolf11

 
Tavern Dweller
|
posted January 28, 2026 07:45 PM |
|
|
AlexSpl said: You can see a disclaimer on the line 69 -
--- THIS GUIDE MAKES ABSOLUTELY NO GUARANTEE ABOUT EDITING HOTA ---
So, this is the case 
Quote: So is there some other check that still looks for Halflings when in battle?
Yep, and it's inside one of many HotA hooks. You have to look relevant code in HotA.dll, and it's probably not a task you are up to.
Quote: Did I get the wrong offset for the third ID change?
Nope. You found a correct address.
I suspected that the HotA.dll was the culprint, but hoped it wasn't the case, since Halflings are also in the base game.
Thanks for confirming it.
Would have been flavourful to give them luck, but I guess I have to find something different for the Demons.
|
|
AlexSpl

   
    
Responsible
Supreme Hero
|
posted January 28, 2026 07:53 PM |
|
Edited by AlexSpl at 20:01, 28 Jan 2026.
|
It's still possible, but, as I wrote many times before, don't try to edit HotA as the team asked.
As for Halflings, I don't remember, but maybe IDs of new Halflings and the old ones are not the same.
OK. Actually they are the same -
MON_H3_NUM = 200;
Creature_Name: array[0..MON_H3_NUM - 1] of string =
({000} 'Pikemen', 'Halberdiers', 'Archers', 'Marksmen', 'Griffins', 'Royal Griffins', 'Swordsmen', 'Crusaders', 'Monks', 'Zealots', 'Cavaliers', 'Champions', 'Angels', 'Archangels',
{014} 'Centaurs', 'Centaur Captains', 'Dwarves', 'Battle Dwarves', 'Wood Elves', 'Grand Elves', 'Pegasi', 'Silver Pegasi', 'Dendroid Guards', 'Dendroid Soldiers', 'Unicorns', 'War Unicorns', 'Green Dragons', 'Gold Dragons',
{028} 'Gremlins', 'Master Gremlins', 'Stone Gargoyles', 'Obsidian Gargoyles', 'Stone Golems', 'Iron Golems', 'Magi', 'Arch Magi', 'Genies', 'Master Genies', 'Nagas', 'Naga Queens', 'Giants', 'Titans',
{042} 'Imps', 'Familiars', 'Gogs', 'Magogs', 'Hell Hounds', 'Cerberi', 'Demons', 'Horned Demons', 'Pit Fiends', 'Pit Lords', 'Efreet', 'Efreet Sultans', 'Devils', 'Arch Devils',
{056} 'Skeletons', 'Skeleton Warriors', 'Walking Dead', 'Zombies', 'Wights', 'Wraiths', 'Vampires', 'Vampire Lords', 'Liches', 'Power Liches', 'Black Knights', 'Dread Knights', 'Bone Dragons', 'Ghost Dragons',
{070} 'Troglodytes', 'Infernal Troglodytes', 'Harpies', 'Harpy Hags', 'Beholders', 'Evil Eyes', 'Medusas', 'Medusa Queens', 'Minotaurs', 'Minotaur Kings', 'Manticores', 'Scorpicores', 'Red Dragons', 'Black Dragons',
{084} 'Goblins', 'Hobgoblins', 'Wolf Riders', 'Wolf Raiders', 'Orcs', 'Orc Chieftains', 'Ogres', 'Ogre Magi', 'Rocs', 'Thunderbirds', 'Cyclopes', 'Cyclops Kings', 'Behemoths', 'Ancient Behemoths',
{098} 'Gnolls', 'Gnoll Marauders', 'Lizardmen', 'Lizard Warriors', 'Gorgons', 'Mighty Gorgons', 'Serpent Flies', 'Dragon Flies', 'Basilisks', 'Greater Basilisks', 'Wyverns', 'Wyvern Monarchs', 'Hydras', 'Chaos Hydras',
{112} 'Air Elementals', 'Earth Elementals', 'Fire Elementals', 'Water Elementals', 'Gold Golems', 'Diamond Golems', 'Pixies', 'Sprites', 'Psychic Elementals', 'Magic Elementals',
{122} '[Unknown]', 'Ice Elementals', '[Unknown]', 'Magma Elementals', '[Unknown]', 'Storm Elementals', '[Unknown]', 'Energy Elemantals', 'Firebirds', 'Phoenixes',
{132} 'Azure Dragons', 'Crystal Dragons', 'Faerie Dragons', 'Rust Dragons', 'Enchanters', 'Sharpshooters', 'Halflings', 'Peasants', 'Boars', 'Mummies',
{142} 'Nomads', 'Rogues', 'Trolls', '[Unknown]', 'Ballista', '[Unknown]', '[Unknown]', 'Arrow Turrets',
{150} 'Cannons', 'Sea Dogs', 'Electric Towers', 'Nymphs', 'Oceanids', 'Crew Mates', 'Seamen', 'Pirates', 'Corsairs', 'Stormbirds', 'Ayssids', 'Sea Witches', 'Sorceresses', 'Nix', 'Nix Warriors', 'Sea Serpents', 'Haspids',
{167} 'Satyrs', 'Fangarms', 'Leprechauns', 'Steel Golems',
{171} 'Halfling Grenadiers', 'Mechanics', 'Engineers', 'Armadillos', 'Bellwether Armadillos', 'Automatons', 'Sentinel Automatons', 'Sandworms', 'Olgoi-Khorkhoi', 'Gunslingers', 'Bounty Hunters', 'Couatls', 'Crimson Couatls', 'Dreadnoughts', 'Juggernauts',
{186} 'Kobolds', 'Kobold Foremen', 'Mountain Rams', 'Argali', 'Snow Elves', 'Steel Elves', 'Yeti', 'Yeti Runemasters', 'Shamans', 'Great Shamans', 'Mammoths', 'War Mammoths', 'Jotunns', 'Jotunn Warlords');
|
|
blacksuzumiya

 
Tavern Dweller
|
posted January 31, 2026 06:20 PM |
|
|
Hello there, I have a question. I've managed to change non-HotA heroes specialities via hex-editing as well as text description, but after trying to change specialities icon, they stay the same in game. I've checked this multiple times also checking guides and forums. The last thing to try is checking HotA.lod because I saw someone mentioning that these UN32 and UN44 for non-HotA + HotA heroes are stored there, but after trying to open the file its all mess and random symbols - is it encrypted? If so, is there a way to edit specialities icons visually in any way? Changing things in H3sprite.lod does nothing with HotA installed. These icons are the last things I need to finish my homebrew project to play with my girlfriend with our edited non-HotA heroes!! Thanks for any replies.
____________
|
|
AlexSpl

   
    
Responsible
Supreme Hero
|
posted January 31, 2026 08:24 PM |
|
|
|
It's indeed encryptred. Your best bet would to place them in _HD3_Data\Common.
|
|
Phoenix4ever

 
     
Legendary Hero
Heroes is love, Heroes is life
|
posted January 31, 2026 11:21 PM |
|
|
|
ArchDruid

 
 
Adventuring Hero
|
posted February 24, 2026 12:59 AM |
|
|
Hello guys!
Why is navigation skill doesn't effect the movement points when boarded in an Airship?
Reading the constellations also should have effect on the movement when you are in an Airship, not just in a regular ship. It's weird.
Where can I find the basic value of movement points (2000) coded in HotA.dll?
All the movement point values were stored in movement.txt, but it is closed down in HotA 1.8.0, because HotA.lod is inaccessible.
|
|
DarkAtom

 
 
Adventuring Hero
|
posted February 24, 2026 03:23 AM |
|
|
|
The file is identical to the one in 1.7.3, so you can just replace it in HotA_ext.lod.
|
|
BigPig2

 
 
Adventuring Hero
|
posted March 11, 2026 03:11 PM |
|
Edited by BigPig2 at 16:01, 11 Mar 2026.
|
(from page 116)AlexSpl said: About the future of modding. (...) Modders will get access to the original methods of the game with the original names.
(my bold) Can these be deduced somehow (are the names of variables or functions preserved into asm/hex?) or has someone somewhere found access to the original source code for the game? Just curious, no shade intended.
Quote: The above method is used only for evaluation of spells with ID 15 and more (starting from Magic Arrow). To evaluate Quicksand and other spells with ID less than 15 you have to add a case to void __thiscall type_AI_spellcaster::consider_spell(type_AI_spellcaster *this, type_spell_choice *choice) method.
Do you have any clues as to why these functions are divided this way at all?
Also, seems like at least the second section already has a way to handle spells without a specified value function, does the first one lack it? Or does "unimplemented" produce values so low they are too low to ever be chosen?
Another thing I wondered, assuming one is satisfied with just lifting the function from another spell (maybe the one for slow could work for quicksand/land mine?), or using a constant, doesnt this sound kinda doable in hex?
Also, on an unrelated note, is 04467E where the global spell length for spells with "has duration" flag is defined? What do you know about this code section? Could the value of this variable be divided by a constant without too much hassle in hex?
|
|
DarkAtom

 
 
Adventuring Hero
|
posted March 12, 2026 10:21 AM |
|
|
BigPig2 said: are the names of variables or functions preserved into asm/hex?
Normally they are not (release executables are stripped) but in this particular case they are taken from the unreleased beta of the Dreamcast port of the game (which was a debug build and had all symbols).
|
|
BigPig2

 
 
Adventuring Hero
|
posted April 12, 2026 11:38 PM |
|
Edited by BigPig2 at 23:44, 12 Apr 2026.
|
Would that be the same code the IDA by void17 is based on? Speaking of which, someone in this thread encountered the same problem as me - the Free IDA refusing to open .idb format but the link to the solution has since perished. Does anyone have the .i64 version lying around? Alternatively, any suggestions for another app I can used to open this .idb with? (I've googled around but its confusing stuff)
Anyways, I finished reading this thread and more than anything else I gotta say it was quite a journey getting to know this forum's lore, watching some of today's gurus' humble beginnings. Got a few handy bookmarks but not an awful lot BTB's reference guide doesn't cover. Got closer to solving a couple issues left on my list, the main one being:
1) Spell duration (which I am looking to divide by a constant).
As i understand the formula at 04467E (SoD HD):
8B 8C 9E 98 01 00 00 (mov ecx,[esi+ebx*4+$00000198])
is where the spell duration for "SP = duration" type of spells is defined (And btw, has anyone succeeded in definitively verifying the relationship between this property and the Byte 1 BIT 3 (04) spell flag?) but I am struggling to understand this block of code as a whole. I've tried experimenting with Cheat Engine breakpoints and while I still dont really know what I am doing with it, I see that casting a spell of this type runs the entire block starting at 44610. (I am assuming the few 90's directly prior are filler separating this block from the previous, likely unrelated one?) At the same time, if I am reading the CE correctly, the value equivalent to my hero's SP is stored in EAX and EDX at that (break)point in time?
From what I understand the solution here will be to jump out to some unoccupied location and do the operation before jumping back in? To that end, I noticed a huge section at the beginning of the exe filled with plain zeros: 2F0-FD3, which looks like more real estate than I imagine ever needing for this and other minor changes I might attempt in the future. How can I verify if this region is not used for some other purposes? And more generally, how do I find and verify space for jump-patches? Theres multiple areas with 15 bytes of 90's in a row, those would be my second guess?
2) The second issue I have been fighting is hero spell specialties, namely for shield-type spells. I have tried giving my heroes Shield and Air Shield specialties and these dont seem to respond to ANY type of bonus. I imagine this might be something to do with either the type of value they take in SPtraits (both have the form of a percentage multiplier) - I've experimented with a lot of different forms of tiered bonus but have not found one that interacts. I havent tested it yet but I have a suspicion the same might be the case with "Protect from" spells as well as slow? But I see both HotA and some of the posters on this forum appear to have succeeded with this in their mods? Can anyone give me a hint how that was achieved?
3) Finally, I am still studying AI secondary skill value functions (two code sections starting 12C0B0 and 124B70) but I cant seem to pinpoint where each begins and ends, could anyone help me identify one of them or give me some pointers on how to recognize them? Again, I am looking to adjust these by changing the constants in their formulas so this should be a simple jump patch in worst case scenario?
4) Of much less priority but still on the to do list: I had a look at the fix for the AI necromancy calculation bug (always produces 1 skele) in the russian plugins and the fix, if I understand correctly, is reversing the order of operations as the game appears to calculate the Necromancy effect after setting losing hero's army to zero, rather than before. Could this mean a hex patch of swapping the order of two blocks of code responsible could be a solution or is that too optimistic?
Anyways, great thread, guys, thank you to all the contributors.
|
|
Andarch1

 
Tavern Dweller
|
posted April 16, 2026 10:43 PM |
|
|
BigPig2 said: Does anyone have the .i64 version lying around?
https://github.com/void2012/NH3API/releases
|
|
BigPig2

 
 
Adventuring Hero
|
posted April 18, 2026 01:10 AM |
|
|
Thank u so much, Andarch1! (And thanks to DarkAtom for the earlier reply, I had a look at it but never figured out how to open/read it..)
In the meantime, I have made some progress on question 3 above (with a huge boost from IDA Free's autoanalysis function). Key findings (some of these have been described or hinted at in this thread already but not spelled out explicitly):
1. The table at 125184-1251F3 lists 28 pointers, 4 bytes long, one for each of the skills in the order following the list of formulas by AlexSpl in the AI skill priorities thread. To change the formula of a skill to another existing one, you can simply swap the pointer for the one used for your target skill.
2. There is redundancies in the formulas, with both Tactics (skill 19) and Offense (22) sharing formulas with other skills (see the list) despite using separate code blocks, these two blocks can be easily repurposed.
3. The formulas of the shape of Value = [(1000 + Army_Power) * x/10^n can be easily multiplied or divided by powers of 2 or 10 by adjusting the magic numbers and/or SAR/SAL instruction arguments in the code used for optimised divison by 10 and 100, other constants are generally also achievable without all that much hassle (but kind of difficult to explain in general terms - u modify the division code block). I describe an example of the former on the third page of the abovementioned thread (which, on second thought, I maybe didnt need to reopen).
I am still studying the formulas involving spell_efficiency factor but they can likely be manipulated in similar ways.
As the question originally centered around AI heroes and Wisdom I have run some ("tens" of) tests with knights and they seem to consistently (~85% of the time) get Wisdom as their 5-7th skill on average if set to start with lvl 24. With their odds to roll Wisdom in the first place, and the fact they start with no spellbook so the spell_efficiency factor probably doesnt get them far (I still dont understand its workings enough to say for sure), they owe this to the "get offered Wisdom/School skill every x levels" rule (switching it off makes Wisdom rates drop dramatically). Interestingly, despite the rule seemingly ignoring skill odds, they appear to get Air and Water Schools much more often and the other two.. This is with no interaction with map objects and I imagine the odds drop with more skills found in huts, universities, scholars etc. Overall, my impression is, adjusting the values in the "every x level" formula might be a more effective way to control this.
With these possibilities I'm curious of others' experiences and opinions about which skills AI benefits from most, with focus on skill mechanics since the values can generally be adjusted to taste.
I wonder for example if AI benefits from scouting in any way? It seems to "see" beyond its line of sight well enough without it? Does it use Diplomacy competently? Tactics is a bit hit and miss? Necromancy is bugged and besides, all the heroes it is available to start with it, but if it was available to others?
|
|
purerogue3

 
   
Famous Hero
|
posted April 18, 2026 08:23 PM |
|
|
|
anyone have the address for the unit produced by external dwellings added by Hota(leprechaun,satyr,fangarm)?
|
|
BigPig2

 
 
Adventuring Hero
|
posted April 19, 2026 02:25 PM |
|
|
Found some hints in the .i64 to help me figure out my question 2) there above. In the SetSpellInfluence function I see:
Quote: case SPELL_MIRTH:
this->mirthBonus = effect;
break;
(...)
case SPELL_FORTUNE:
v22 = (hero *)casting_hero;
this->fortuneBonus = effect;
if ( v22 )
this->fortuneBonus += hero::GetHeroSpellBonus(v22, spell, this->sMonInfo.level, effect);
break;
And indeed, Mirth doesnt seem to apply any specialty bonus. Basically only the spells, which had specialists in SoD appear to have a call to this function (although I havent checked the damage spells yet). Interestingly, however, nor do Bless or Hypnotize, which do have specialists? Do these two not actually receive specialty bonuses or am I missing something?
|
|
AlexSpl

   
    
Responsible
Supreme Hero
|
posted April 19, 2026 03:11 PM |
|
|
Bless specialists increase basic damage, so it's only logical to apply their bonus after basic damage itself has been already calculated. So, here we go -
int army::SoD_ComputeAttackerDamageBonuses() @ 443040h
@ 443480h:
if ( this->spellInfluence[SPELL_BLESS] )
v34 += hero::GetHeroSpellBonus(v32, SPELL_BLESS, this->sMonInfo.level, base_damage);
Hypnotize specialty increases the amount of units affected by Hypnotize spell, so the spell will work where its basic version won't. If a spell works or not, that's defined by -
float __thiscall combatManager::SpellCastWorkChance() @ 5A83A0
For Hypnotize precisely see 5A8673 -
case SPELL_HYPNOTIZE:
v24 = akSpellTraits[SPELL_HYPNOTIZE].m_mastery_bonus[hero::get_spell_level(
v35,
SPELL_HYPNOTIZE,
this->SoD_Magic_Terrain)]
+ akSpellTraits[60].m_power_factor * this->iSideSpellPower[casting_side];
v25 = hero::GetHeroSpellBonus(v35, SPELL_HYPNOTIZE, target_army->sMonInfo.level, v24) + v24;
if ( !target_army->spellInfluence[SPELL_MAGIC_MIRROR]
&& target_army->numTroops * target_army->sMonInfo.hitPoints <= v25 )
{
goto LABEL_92;
}
result = 0.0;
break;
|
|
BigPig2

 
 
Adventuring Hero
|
posted April 19, 2026 04:47 PM |
|
Edited by BigPig2 at 16:52, 19 Apr 2026.
|
Oh I see. I cant seem to find where the curse effect is applied though? Do you know which function handles it?
Also, I cant see a spell damage function with cases for different spells, are all damage type spells handled by hero::modify_spell_damage ? Would that include for example land mine? Which in turn calls hero::GetHeroSpellBonus and its default clause I guess? Or do damage spells call hero specialty directly like the enchantments somewhere?
|
| |
|
|