Heroes of Might and Magic Community
visiting hero! Register | Today's Posts | Games | Search! | FAQ/Rules | AvatarList | MemberList | Profile


Age of Heroes Headlines:  
5 Oct 2016: Heroes VII development comes to an end.. - read more
6 Aug 2016: Troubled Heroes VII Expansion Release - read more
26 Apr 2016: Heroes VII XPack - Trial by Fire - Coming out in June! - read more
17 Apr 2016: Global Alternative Creatures MOD for H7 after 1.8 Patch! - read more
7 Mar 2016: Romero launches a Piano Sonata Album Kickstarter! - read more
19 Feb 2016: Heroes 5.5 RC6, Heroes VII patch 1.7 are out! - read more
13 Jan 2016: Horn of the Abyss 1.4 Available for Download! - read more
17 Dec 2015: Heroes 5.5 update, 1.6 out for H7 - read more
23 Nov 2015: H7 1.4 & 1.5 patches Released - read more
31 Oct 2015: First H7 patches are out, End of DoC development - read more
5 Oct 2016: Heroes VII development comes to an end.. - read more
[X] Remove Ads
LOGIN:     Username:     Password:         [ Register ]
HOMM1: info forum | HOMM2: info forum | HOMM3: info mods forum | HOMM4: info CTG forum | HOMM5: info mods forum | MMH6: wiki forum | MMH7: wiki forum
Heroes Community > Heroes 3.5 - WoG and Beyond > Thread: How to edit HotA?
Thread: How to edit HotA? This Popular Thread is 111 pages long: 1 10 20 ... 21 22 23 24 25 ... 30 40 50 60 70 80 90 100 110 111 · «PREV / NEXT»
Serp
Serp


Known Hero
posted October 01, 2017 09:09 PM

What components from Visual Studio do I need to create those dll files?
I aborted the installation of the two workloads, cause it is 11 GB big and download connection is terrible here...

So it might be better to not install workloads, but single components.
So which ones do I need at least?

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
RoseKavalier
RoseKavalier


Admirable
Supreme Hero
posted October 01, 2017 09:36 PM
Edited by RoseKavalier at 04:42, 02 Oct 2017.

Serp said:

(Visual Studio Community is installing at the moment.. takes very long unfortunately, so I was not able to test yet ... I chose the first and 3rd "workload" for windows. I hope these are correct?)


I'm not sure what you actually need, I've got myself a VS 2013 and VS 2015 copy on another machine and they're < 3 Gig each.

Serp said:

1) The example test code here http://handbookhmm.ru/forum/viewtopic.php?f=56&t=518 contains this:
#include "patcher_x86.hpp"
But why does not a single source code from the downloaded plugins contains this line?


Because it is included in homm3.h, as well as several other files. That way you only need to include 1 header when making a new project and don't forget stuff

Serp said:

2) I noticed the plugin mods in russian forum (and also the test code) have a slightly different form to add the hooks:


I don't really know, I got the original setup from someone and never tinkered with it

Serp said:

Can you also give me code for scholar choice (when it is a secondary skill)? (when denying, scholar still disappears)
A explantion would be also good

I know the general region of code, I'll look it over in a bit.

Serp said:
I mean the past pages of the thread you and others always mentioned "this hex ... is responsible for this and that". And my goal would be to be able to at least be able to create my own plugins, when you or anyone else is telling me the assembly hex to change.
So I need to know: When to use a patch and when a hook and when something else? And eg how can I develope on my own this line:  "*(int*)(*(int*)0x6992D0 + 0x38) - 0x7805; // grab user's decision"  Why so many "*" and why + and - ?


* are used for casting and pointers ... lets you get the values you want.

If you do (int*)address, it casts address to int type. This can be useful to cast an address to a specific structure.
*(int*)address -> gives the value of int at address.

0x6992D0 is where the address of WindowManager structure is stored, to retrieve the address of it you do
*(int *)0x6992D0
Let's call this o_WndMgr as it is in homm3.h.

+ 0x38 is the offset to the ID of the last clicked item.
When you write:
o_WndMgr + 0x38
It will give you the place where the value of the ID of last clicked item is stored... NOT the ID of that item.

o_WndMgr + 0x38 shows you where what you're looking for is, but not the value.
To get the value you do:
*(int *)(o_WndMgr + 0x38)
This gives you the ID of the clicked item!

Think of it as a shelf with boxes and stuff in the box

0x6992D0 is the room where the shelf is stored
*(int *)0x6992D0  is the shelf
*(int *)0x6992D0 + 0x38 is one of the boxes on the shelf
*(int *)(*(int *)0x6992D0 + 0x38) is what is inside the box - the clicked ID in this case.

By default, the 'OK' button in H3 has ID 0x7805, so you can always compare directly to that instead of subtracting and comparing to 0 - same result.

i.e. if (*(int *)(*(int *)0x6992D0 + 0x38) != 0x7805)

~~~

Alternatively, in homm3.h you have some well defined structures. You can get the same reasoning using structures and pointers:

Quote:
if (o_WndMgr->result_dlg_item_id != DIID_OK)
   ...logic here...


 Send Instant Message | Send E-Mail | View Profile | PP | Quote Reply | Link
RoseKavalier
RoseKavalier


Admirable
Supreme Hero
posted October 01, 2017 10:23 PM
Edited by RoseKavalier at 04:42, 02 Oct 2017.

The function that handles Scholars is:
0x4A4A30

Easy way to find this:
0x4A8160 is the "visit object" function.
Almost every time your hero steps on a "yellow" tile, this function gets triggered (there are a few exceptions, like "Event").
@ 4A81AA there is a switch(case) {}, place a breakpoint (F2) there with OllyDbg.

When you visit an object (in this case Scholar), the game will begin executing this code - but it will pause at our breakpoint.
Note: you won't see the function names by default, I've added these with labels recently.


Now just step forward a few times and we will get to the Scholar function.


If you don't have any information, you may need to go through this function a few times to get an idea of what's going on, but here it's quite straightforward since I've previously labeled things used here:


So from this brief analysis, we see that the secondary skill is offered before the textbox is created. Therefore, what needs to be done:
1-insert some code before the secondary skill is given
2-create a textbox giving the choice
3-if choice is accepted ( == 0x7805) give the secondary skill (see 0x4A4AE4 - 0x4A4AEF)
4-set return address to 0x4A4B86 (this is where all 3 procedures - spell - primary - secondary - meet again) which will delete scholar and update map look.

To get the correct text for point #2 look at the logic between 0x4A4AFE and 0x4A4B34.

IMO, you should also add logic for what to do if the hero cannot learn the skill even if you clicked OK:
1a-check if that skill level is already 3
1b-check if hero already has 8 skills
1c-if yes to both, set return address to 0x4A4B3F (like 0x4A4AF1 does when it fails to give the SSkill).

Now as to the actual code, you can try your hand at it ... if you still feel overwhelmed I (or someone else) can do it later or guide you along your steps to your first H3 plugin

~~~

EDIT:
I've made the plugin, while I can give you the code right away, it might be best to help you work on it for the long run, let me know

 Send Instant Message | Send E-Mail | View Profile | PP | Quote Reply | Link
AlexSpl
AlexSpl


Responsible
Supreme Hero
posted October 02, 2017 01:30 AM

Quote:
What components from Visual Studio do I need to create those dll files?
I aborted the installation of the two workloads, cause it is 11 GB big and download connection is terrible here...

You need a C/C++ compiler only. Try VS 2008 Express Edition (895 MB): https://go.microsoft.com/fwlink/?LinkId=104679 (direct link).

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Serp
Serp


Known Hero
posted October 02, 2017 10:31 PM

AlexSpl said:
Quote:
What components from Visual Studio do I need to create those dll files?
I aborted the installation of the two workloads, cause it is 11 GB big and download connection is terrible here...

You need a C/C++ compiler only. Try VS 2008 Express Edition (895 MB): https://go.microsoft.com/fwlink/?LinkId=104679 (direct link).

Thanks, this works

I wanted to create the dll following your explanation here:
http://handbookhmm.ru/forum/viewtopic.php?f=56&t=518

But you did not mentioned what to do with the patcher_86x.hpp file ?! Where should I put it ? I put it in ProjectsWitcher_Hut_ChoiceWitcher_Hut_Choice (where also by default the header "stdafx.h" is located and also added it to the "header files" within the project.
Then I tried "#include patcher_86x.hpp", but when trying to build, I get error, that it can not find this file.
I tried the same with homm3.h file.

And also 7) from your explanation, I set it to "release" but is this saved? When I open this menu again, it is not anymore set on "Release" so I have no clue what this does or should do. I simply hit Alt-F7 and change the Configuration to "Release" and hit "ok".

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
AlexSpl
AlexSpl


Responsible
Supreme Hero
posted October 02, 2017 10:44 PM

Quote:
But you did not mentioned what to do with the patcher_86x.hpp file ?! Where should I put it ?

Put it next to dllmain.cpp, if you use #include "patcher_x86.hpp". It's a relative path.

Quote:
When I open this menu again, it is not anymore set on "Release" so I have no clue what this does or should do.

It's remembered.

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Serp
Serp


Known Hero
posted October 02, 2017 11:03 PM

AlexSpl said:
Quote:
But you did not mentioned what to do with the patcher_86x.hpp file ?! Where should I put it ?

Put it next to dllmain.cpp, if you use #include "patcher_x86.hpp". It's a relative path.

Quote:
When I open this menu again, it is not anymore set on "Release" so I have no clue what this does or should do.

It's remembered.

I don't know what is wrong.
In the project I had them in "Header Files" and tried now to add them to "Source Files" but both is not working:
https://www2.pic-upload.de/img/34021573/hdmodpluginwitchhut.jpg

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
AlexSpl
AlexSpl


Responsible
Supreme Hero
posted October 02, 2017 11:12 PM
Edited by AlexSpl at 23:16, 02 Oct 2017.

You have to write "patcher_x86.hpp", not "patcher_86x.hpp".

And change the configuration of your project to "Release". See "Debug" next to ">" button. Change it to "Release".

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Serp
Serp


Known Hero
posted October 02, 2017 11:28 PM

AlexSpl said:
You have to write "patcher_x86.hpp", not "patcher_86x.hpp".

And change the configuration of your project to "Release". See "Debug" next to ">" button. Change it to "Release".

thanks
worked and also the plugin works
I guess it is Multiplayer compatible? Or should I test it in MP first?

Tomorrow I will try to write code for the scholar
@RoseKavalier:
Why you wrote that I need to check how many skills hero has and what level of skill and so on?
Isn't this already checked by the game itself?

And your description sounds like I have to create my own textbox? I don't know the code for that I guess
Maybe this a still a bit too complicated for a beginner?

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
AlexSpl
AlexSpl


Responsible
Supreme Hero
posted October 02, 2017 11:37 PM

Quote:
I guess it is Multiplayer compatible? Or should I test it in MP first?

If your code doesn't deal with player's ID, it will work in multiplayer in most cases.

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
RoseKavalier
RoseKavalier


Admirable
Supreme Hero
posted October 03, 2017 04:22 AM bonus applied by Maurice on 03 Oct 2017.

Serp said:
Why you wrote that I need to check how many skills hero has and what level of skill and so on?
Isn't this already checked by the game itself?

The game does check it, but we will be replacing that piece of code to achieve our goal of giving the choice.

The second reason to check which skill the scholar is offering and our current level is to create the textbox using the correct picture (.def frame) and the subtext that goes with it. See info from ERM help:


Finally, the last reason to check it is that the game usually does this - if you cannot be granted this particular skill, then it gives you a primary skill bonus instead.

Serp said:
And your description sounds like I have to create my own textbox? I don't know the code for that I guess
Maybe this a still a bit too complicated for a beginner?


Definitely not too complicated! You just need some help
Warning, long read ahead!

Step 1
I have this:
Quote:
_PI->WriteLoHook(0x4A4AE4, wandering_scholar_sskill_choice);

It's convenient for 2 reasons:
the skill identity is freely available (EAX) and the hero has not yet tried to learn it.

So we can do this:
Quote:
int skill_id = c->eax;


Also quite useful is the hero's structure, it's currently stored in EBX in that area (this needs some time getting used to recognizing).
Quote:
_Hero_ *hero = (_Hero_*)c->ebx;



_Hero_ is a structure defined in homm3.h, so we can get some data easily from this hero.

When you type...
Quote:
hero->

...you will see a lot of options. The ones that interest us at this time are:
*second_skill_count // the number of skills this hero currently has
*second_skill[] // an array that stores the 28 skill level for each of this hero

a)b)c)
Quote:
int skill_level = hero->second_skill[skill_id];

Now you can check if this is equal to 3 OR if hero->second_skill_count is equal to 8. If either of these are true, then the hero cannot learn this skill... the game would lead you back to 0x4A4B3F where you may learn a primary skill instead (see 0x4A4AF1) and specify not to execute the original code.

d) there is an extra step I did not cover previously.
What if an AI triggers this Scholar? In my previous post you can see that at 0x4A4AF8 there is a comment about AI. In the visit object function, the 4th argument is "0" if it's an AI visiting an object... this argument is also passed to the scholar function.
Anyhow, this logic is checked starting at 0x4A4AF3:
Quote:
if (*(BYTE*)(c->ebp + 0x14) == 0)
return EXEC_DEFAULT;


What's the reasoning here?
AI are not able to handle textboxes so let's just have them execute the normal game code instead by exiting current hook.

If this were my plugin, I'd also place a no multiplayer check in this section but it's up to you.

Step 2
If you look at my previous post, you can see "CALL generic textbox"  function (0x4F6C00). It has 12 arguments (PUSH ...) to be properly called, this is a __fastcall type of function meaning that registers ECX and EDX work as arguments. Don't worry too much about knowing these things right away, it took me months to be aware of the difference

Luckily for us, patcher_x86 (and homm3.h for some reason) make our job easy since we can use the macro CALL_12.
Quote:

CALL_12(return_type, call_type, address, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)



Let's go over the arguments one by one.
return_type: does this function return anything?
No... there are a few ways to check this. Usually return value is given by register EAX and you should see some logic with the EAX register after the CALL (not the case here).
So we don't care about return type, let's use void.

call_type: like I said, this is a __fastcall function since ECX and EDX are arguments.

address: 0x4F6C00 ... simple enough

a1 this is ECX (works this way for __fastcall). In this case this is the text of the Scholar. You could input you own text e.g. "Would you like to learn this skill?" or you could also use the default text. Depending on what header files you have access to, this can be done quite simply or with some more difficulty:

Follow the logic from these addresses:
0x4A4B15, 0x4A4B20, 0x4A4B29
Quote:
*(char*)(*(char*)(*(char*)0x696A68 + 0x20) + 0x1CC)


More simply if you have the right headers:
Quote:

#define o_ADVEVENT_TXT (*(_TXT_**)0x696A68)
o_ADVEVENT_TXT->GetString(115) // line 116 - 1 (count from 0)


(if this doesn't work in your project because you lack some files, they are linked in Russian forums)

a2: this one is EDX, that'll be the type of message box to create.
1 - OK
2 - OK/CANCEL
4 - right-click textbox
I have this somewhere in my files... you may need it.
Quote:
#define MBX_OKCANCEL 2


a3 work backwards from 0x4A4B27 (arguments or PUSHes are passed right to left)
-1

a4
-1

a5
0x14 (or 20)

a6: this is the .def frame to use. The logic to get this is obtained from addresses:
0x4A4AFE, 0x4A4B08, 0x4A4B11
Essentially this comes out to be:
Quote:

skill_id * 3 + skill_level + 2 + 1


Why the extra +1? Because at this stage, the hero will not have been given the secondary skill

a7:
-1

a8:
0

a9:
-1

a10:
0

a11:
-1

a12:
0

In the end all this rambling comes out to only 1 unknown: a6
Quote:
#define Show_Scholar_SSkill_Yes_No(frame)
CALL_12(void, __fastcall, 0x4F6C00, o_ADVEVENT_TXT->GetString(115), MBX_OKCANCEL, -1, -1, 0x14, frame, -1, 0, -1, 0, -1, 0)



And that's step 2 of my 4-step plan.

For step 3
This one you already have in part:
Quote:
if (o_WndMgr->result_dlg_item_id == DIID_OK)
  .... logic....



So what's the required logic here?
We must go back in the original code where the hero would normally learn the secondary skill., this is at 0x4A4AE6... function 0x4E2540.
This is a __thiscall as in my previous post, meaning 3 arguments:
ECX (hero structure)
arg 1 : skill id
arg 2 : 1 (because scholar only grants +1)

In homm3.h, go to the _Hero_ structure, scroll down a bit to the functions section (e.g. RemoveDollArtifact, AddDolLArtifact...) and we will add a new function for heroes:
Quote:
int LearnSecondarySkill(int skill_id, int skill_increase) { return CALL_3(int, __thiscall, 0x4E2540, this, skill_id, skill_increase);}

this refers to the current object - in this case the hero (ECX).

Finally we have an easy way of granting this hero the secondary skill:
Quote:
hero->LearnSecondarySkill(skill_id, 1);


All that's left is to change the return address and tell patcher that we don't want to execute the original game code (return NO_EXEC_DEFAULT.

~~~

If you want to see what it looks overall, check this spoiler out.
For learning purposes, it may be best to try and tinker with it before looking at it though

I need a better way to show code on here
____________
My Let's Plays: Metataxer's Revenge - The Empire of The World 2

 Send Instant Message | Send E-Mail | View Profile | PP | Quote Reply | Link
Serp
Serp


Known Hero
posted October 03, 2017 12:41 PM

@RoseKavalier:
Might need some time or days to try around with the code

But a question in advance:
I know modding some games in lua.
And I would like to make sure, that it is really necessary that we do these checks on our own, cause it is not a good idea to replace too much game code (change as less as possible is better).

I imagine this scholar thing as a function. Is it really one single game function that does all the checks first and then gives the secondary skill and then gives out the textbox? If it is 1 single function I guess it is really not psosible to hook into the middle of this function.
But maybe they are seperated functions? The best way would be, if we would have a function that is called after all the checks, to give the hero the secondary skill. It could look like this:
function GiveSkill(hero,skill,reason)
And then we schould only replace this function, saving the original before. Then we would check if reason=="scholar". If it is, create our choice textbox. If it is not, call the old function.

So what is the structure of the that scholar code from the game? Is it really not possible to hook into it after the checks are done from the game, so we can be sure the game really will give out a secondary skill to that hero?

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
RoseKavalier
RoseKavalier


Admirable
Supreme Hero
posted October 03, 2017 02:18 PM
Edited by RoseKavalier at 14:21, 03 Oct 2017.

If you look at this image from a few posts ago it shows you the game logic.

For the overall function... I don't have it with me at the moment but it goes a bit like this.

Quote:
Get Scholar type (0/1/2)
if (Spell type) {
   extract spell id
   check spell level && if hero has high enough Wisdom
   check for spellbook
   if yes, give spell
   if no, go to Scholar (primary type)
   if AI, go to cleanup procedure
   make a textbox for human showing his new spell
   go to cleanup procedure
}
if (Secondary type) {
   extract sskill id
   Try to give sskill // this function checks if you have 8 skills or if this secondary skill's level is already 3)
   if it failed, go to Scholar (primary type)
   if AI, go to cleanup procedure
   make a textbox for human showing his new sskill
   go to cleanup procedure
}    
if (Primary type) {
   extract primary type
   give primary skill
   if AI, go to cleanup procedure
   make a textbox for human showing his new Primary skill
}
Cleanup procedure:
   Redraw map
   Delete Scholar (make sound if human & everything else required)
   a few more things I forget
   exit function



The reason why it's much more complicated than the Witch Hut hook is because in Witch Hut, the Secondary Skill is given AFTER the textbox. For scholar it's not that way because developers wanted scholar to give primary skill if you couldn't get the other options.

In fact, we're not really changing the code, it's executing the very same code (if you want you can write all of this in Assembly) but we are changing the order of things. The (secondary type) will look like this instead:

Quote:

if (Secondary type) {
   extract sskill id
   go to HOOK
   Normal procedure
   Try to give sskill // this function checks if you have 8 skills or if this secondary skill's level is already 3)
   if it failed, go to Scholar (primary type)
   if AI, go to cleanup procedure
   make a textbox for human showing his new sskill
   go to cleanup procedure
}  

HOOK
{
   if AI, go to (normal procedure) // probably better to put this first
   Check if hero can learn this secondary skill
   if no, go to (Primary type)    
   make textbox for human ASKING if he wants this new skill
   if yes, give new skill
   go to cleanup procedure
}




More or less the same code, different order. If you compare in disassembler, you will see a lot of similar stuff in the hook, with slightly different appearance and order.

~~~~

There's actually no way to place the hook after the textbox is made because there is not enough room to do so. When you place a hook, you need 5 bytes, there is one big rule to make sure no crashes will happen:
* the middle/end of the hook CANNOT be the arrival point of another jump. Anything except the very start is no-go.

The image I linked doesn't show it (cut off) but there's an arrival point there from 0x4A4ADC... it looks very similar to 0x4A4AD9 and is marked with a > in disassembler.

Anyway, if you somehow had the room to place the hook there, you would need to find the secondary skill used, decrease it by 1, check if it is now 0, unlearn skill [adjust the number of secondary known, remove the secondary from the secondary order (1-8)]. IMO that's more work and there isn't an existing function for unlearning secondary skills in SoD/HotA.
____________
My Let's Plays: Metataxer's Revenge - The Empire of The World 2

 Send Instant Message | Send E-Mail | View Profile | PP | Quote Reply | Link
avatar
avatar


Promising
Supreme Hero
posted October 03, 2017 06:08 PM

Little offtop - is there possibility to compile english version of hd-mod plugins from df2.ru?

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
AlexSpl
AlexSpl


Responsible
Supreme Hero
posted October 03, 2017 06:12 PM

Quote:
There's actually no way to place the hook after the textbox is made because there is not enough room to do so. When you place a hook, you need 5 bytes, there is one big rule to make sure no crashes will happen:
* the middle/end of the hook CANNOT be the arrival point of another jump. Anything except the very start is no-go.

You can always run the original code within your hook, you can even rewrite a whole function

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
AlexSpl
AlexSpl


Responsible
Supreme Hero
posted October 03, 2017 06:19 PM

Quote:
Little offtop - is there possibility to compile english version of hd-mod plugins from df2.ru?


Yes, it's possible. Which one you are interested in?

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
avatar
avatar


Promising
Supreme Hero
posted October 03, 2017 07:00 PM

1. http://forum.df2.ru/index.php?showtopic=30848&st=20&p=688550&#entry688550

2. and 3.  http://forum.df2.ru/index.php?showtopic=30848&st=20&p=688848&#entry688848 - I know the second one is only for sod+hd mod

4. http://forum.df2.ru/index.php?showtopic=30848&st=20&p=691569&#entry691569

5. http://forum.df2.ru/index.php?showtopic=30848&st=20&p=744804&#entry744804

I guess the rest dll-s from this site have not any language-display texts (I'm not talking about era scripts).

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Serp
Serp


Known Hero
posted October 03, 2017 07:17 PM

@avatar: Did you tried them already?
Eg. the EagleEye plugin does not contain any text, it will print out the default message from eagly eye, which depends on your game language (at least I see english).
And did you try if those plugins even work for you? For me not a single HD Plugin from there worked. I compiled them again (with source code) now and now they do work.
I used the patcher I got from here:
I got the "sample" folder from here:
http://wforum.heroes35.net/showthread.php?tid=862&pid=98158#pid98158

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Serp
Serp


Known Hero
posted October 03, 2017 07:31 PM

@RoseKavalier:
thank you for detailed explanation
But I'm very sure I don't want to learn this assembly stuff ever

Is the scholar code not multiplayer compatible? Can you make it compatible?
I mean MP is the only purpose of this plugin =/ When playing alone you can always save/load. But it this sucks in MP

I copied your spoiler code now and I'm very sure I never came to this solution
At the moment it does not work, but I'm sure it is because of WriteLoHook (0x4A4AFE, wandering_scholar_sskill_choice); ? I just guessed this 0x4A4AFE value

Quote:

#include "HotA\homm3.h"

Patcher* _P;
PatcherInstance* _PI;
static _bool_ plugin_On = 0;

#define o_ADVEVENT_TXT (*(_TXT_**)0x696A68)
#define Show_SSKill_MSG_YES_NO(frame) \
CALL_12(void, __fastcall, 0x4F6C00,o_ADVEVENT_TXT->GetString(115), MBX_OKCANCEL, -1, -1, 0x14, frame, -1, 0, -1, 0, -1, 0);

int __stdcall wandering_scholar_sskill_choice(LoHook *h, HookContext *c)
{
   int skill_id = c->eax; // grab skill to learn
   _Hero_ *hero = (_Hero_*)c->ebx; // grab current hero structure
   int skill_level = hero->second_skill[skill_id]; // current skill level
   if (*(BYTE*)(c->ebp + 0x14) == 0 ) // || o_IsMultiPlayerGame // disable for AI
       return EXEC_DEFAULT;
   
   if (hero->second_skill_count == 8 || skill_level==3) // if hero can not learn skill
   {
       c->return_address = 0x4A4B3F; // change return address to learn primary skill
       return NO_EXEC_DEFAULT; // do not execute original code that was overwritten
   }
   
   Show_SSKill_MSG_YES_NO(skill_id * 3 + skill_level + 2 + 1); // is the ID of the frame to use from .DEF file.
   // The extra + 1 is because the skill is not yet increased!
   // equivalent to ... MOVSX ECX,BYTE PTR DS:[EBX+EDI+0C9] ... LEA EDX, [EDI*2 + EDI] ... LEA EAX, [EDX+ECX+2]
   
   if (o_WndMgr->result_dlg_item_id == DIID_OK) // did user click ok?
       hero->LearnSecondarySkill(skill_id,1); // then leanr the skill
   
   c->return_address = 0x4A4B86; // go to exit procedure
   return NO_EXEC_DEFAULT; // do not execute original code that was overwritten
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
   if ( DLL_PROCESS_ATTACH == ul_reason_for_call )
   {
       if (!plugin_On)
       {
           plugin_On = 1;
           _P = GetPatcher();
           _PI = _P->CreateInstance("HD.Plugin.ScholarChoice_HotA");
           
           _PI-> WriteLoHook (0x4A4AFE, wandering_scholar_sskill_choice);
       }
   }
   return TRUE;
}



The error log is this:
1>c:usersserpens66documentsvisual studio 2008projectsscholarchoicehotascholarchoicehotahotahomm3_ids.h(547) : warning C4005: 'HID_LORD_HAART' : macro redefinition
1>        c:usersserpens66documentsvisual studio 2008projectsscholarchoicehotascholarchoicehotahotahomm3_ids.h(401) : see previous definition of 'HID_LORD_HAART'
1>c:usersserpens66documentsvisual studio 2008projectsscholarchoicehotascholarchoicehotahotahomm3_ids.h(638) : warning C4005: 'SPL_DISPEL' : macro redefinition
1>        c:usersserpens66documentsvisual studio 2008projectsscholarchoicehotascholarchoicehotahotahomm3_ids.h(594) : see previous definition of 'SPL_DISPEL'
1>c:usersserpens66documentsvisual studio 2008projectsscholarchoicehotascholarchoicehotahotabase.h(392) : warning C4996: 'vsprintf': This function or variable may be unsafe. Consider using vsprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        c:program files (x86)microsoft visual studio 9.0vcincludestdio.h(366) : see declaration of 'vsprintf'
1>c:usersserpens66documentsvisual studio 2008projectsscholarchoicehotascholarchoicehotahotabase.h(422) : warning C4996: 'sscanf': This function or variable may be unsafe. Consider using sscanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        c:program files (x86)microsoft visual studio 9.0vcincludestdio.h(324) : see declaration of 'sscanf'
1>c:usersserpens66documentsvisual studio 2008projectsscholarchoicehotascholarchoicehotapatcher_x86_commented.hpp(125) : warning C4005: '_bool_' : macro redefinition
1>        c:usersserpens66documentsvisual studio 2008projectsscholarchoicehotascholarchoicehotahotabase.h(64) : see previous definition of '_bool_'
1>c:usersserpens66documentsvisual studio 2008projectsscholarchoicehotascholarchoicehotapatcher_x86_commented.hpp(678) : warning C4010: single-line comment contains line-continuation character
1>c:usersserpens66documentsvisual studio 2008projectsscholarchoicehotascholarchoicehotapatcher_x86_commented.hpp(679) : warning C4010: single-line comment contains line-continuation character
1>c:usersserpens66documentsvisual studio 2008projectsscholarchoicehotascholarchoicehotadllmain.cpp(30) : error C2039: 'LearnSecondarySkill' : is not a member of '_Hero_'
1>        c:usersserpens66documentsvisual studio 2008projectsscholarchoicehotascholarchoicehotahotahomm3.h(492) : see declaration of '_Hero_'
1>Build log was saved at "file://c:UsersSerpens66DocumentsVisual Studio 2008ProjectsScholarChoiceHotAScholarChoiceHotADebugBuildLog.htm"
1>ScholarChoiceHotA - 1 error(s), 7 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========




How to change secondary skill description within plugin code?
Eg. I have now the NewEagleEye and the LearningSkill plugin.
I would like to adjust the description.
1) For eagleye it would be enough to adjust the % to new fix values.
2) While for Learning the % value should change depending on the formula to recalculate the +% experience the hero is getting (the higher the level, the more +% he gets)
Quote:
int __stdcall changeLearningPower(LoHook* h, HookContext* c)
{
   char learningSkill = *(char*)(c->ecx + 0xDE);
   _word_ heroLevel = *(_word_*)(c->ecx + 0x55);

   float multiplier = learningSkill * heroLevel / (float)15.0;
   *(float*)(c->ebp - 4) = (float)multiplier;

   return EXEC_DEFAULT;
}



Does anyone know why the TownPortal Plugin is not working?
http://forum.df2.ru/index.php?s=&showtopic=30848&view=findpost&p=743167
I compiled it again (like all the other plugins) and now the plugin is correctly loaded.
When I do not have enough movemenpoints, I can not use townportal (as intended).
But when I can cast the spell and hit the townportal symbol, the game crashes =/

Code:
Quote:

#include "HotA\homm3.h"

Patcher* _P;
PatcherInstance* _PI;
static _bool_ plugin_On = 0;

int __stdcall tpCostForHuman(LoHook* h, HookContext* c)
{
  *(int*)(c->ebp - 0x40) = 1200;
  *(int*)(c->ebp - 0x3C) = 1200;
  *(int*)(c->ebp - 0x38) = 1000;
  *(int*)(c->ebp - 0x34) = 800;
 
  return EXEC_DEFAULT;
}

int __stdcall skipTownPortalConfirm(LoHook* h, HookContext* c)
{
  if ( c->eax == -1 ) {
     c->ecx = *(unsigned char*)(c->edi + 5); // Execute a jam-patched command
     c->return_address = 0x41D990; // Bypass the jmp-patch
     return NO_EXEC_DEFAULT;
  }
 
  c->return_address = 0x41D939;
  return NO_EXEC_DEFAULT;
}

int __stdcall mpointsEarth_1(LoHook* h, HookContext* c) {
  int level = c->eax;
  int mpoints[] = {1200, 1200, 1000, 800};
  c->eax = mpoints[level];
 
  c->return_address = 0x56B5AA;
  return NO_EXEC_DEFAULT;
}

int __stdcall mpointsEarth_2(LoHook* h, HookContext* c) {
  int level = c->eax;
  int mpoints[] = {1200, 1200, 1000, 800};
  c->eax = mpoints[level];
  c->ecx = *(int*)(c->esi + 0x4D);
 
  c->return_address = 0x430532;
  return NO_EXEC_DEFAULT;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
   if ( DLL_PROCESS_ATTACH == ul_reason_for_call )
   {
       if (!plugin_On)
       {
           plugin_On = 1;
           _P = GetPatcher();
           _PI = _P->CreateInstance("HD.Plugin.TownPortalHotA");
           
           _PI-> WriteLoHook (0x41D538, tpCostForHuman); // change the MP costs from 300/300/200 to 1200/1000/800
           _PI-> WriteHexPatch (0x41D6D1, "90 90 90 90 90 90 90 90 90 90 90"); // cancel the check for the Earth Magic level in the main spell function
           _PI-> WriteLoHook (0x56B59B, mpointsEarth_1); // Expenses MP in the auxiliary. functions 1
           _PI-> WriteHexPatch (0x56B3B4, "90 90 90 90 90 90"); // cancel the check for the level of Earth Magic in the helper. functions 1
           _PI-> WriteLoHook (0x430520, mpointsEarth_2); // Expenses MP in the auxiliary. functions 2
           _PI-> WriteLoHook (0x41D934, skipTownPortalConfirm); // bypass the jmp patch HD mode (version 3.809 and higher)
       }
   }
   return TRUE;
}


 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
avatar
avatar


Promising
Supreme Hero
posted October 03, 2017 07:33 PM
Edited by avatar at 19:35, 03 Oct 2017.

Didn't test them yet, just discovered this topic, but for example in Eagle Eye code I can see such line...



so I assumed, that these binary patches contain some texts in russian.

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Jump To: « Prev Thread . . . Next Thread » This Popular Thread is 111 pages long: 1 10 20 ... 21 22 23 24 25 ... 30 40 50 60 70 80 90 100 110 111 · «PREV / NEXT»
Post New Poll    Post New Topic    Post New Reply

Page compiled in 0.3210 seconds