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: Heroes 3 Hacking Reference Guide
Thread: Heroes 3 Hacking Reference Guide This thread is 41 pages long: 1 10 20 ... 28 29 30 31 32 ... 40 41 · «PREV / NEXT»
AlexSpl
AlexSpl


Responsible
Supreme Hero
posted October 23, 2022 10:45 PM
Edited by AlexSpl at 22:48, 23 Oct 2022.

You can easily add a section to the end of the executable with this simple program - addscn

You can build this program from the sources or just download this ready-to-use version - AddSection

Here is an example of usage:

AddSection heroes3.exe .patch 0x1000 text
AddSection <path to PE file> <section name> <VirtualSize> <Characteristics>

text = 0x60000020, which means it has the same characteristics as the .text section of the original code section of Heroes 3 (Text Executable Readable).

Then you'll get a message like this (it's an example for kb.exe):

File size in bytes: 13073920
You can proceed to copy your raw section data to file offset 0xc77e00 up to a length of 0x1000
The section will be mapped at RVA 0x1ac5000
New file size in bytes: c78e00
Operation completed successfully.


Feel free to write your code incl. jumps back to the original code @ 0xc77e00 (for the above example).

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


Adventuring Hero
posted October 26, 2022 09:49 AM
Edited by Parascus at 11:36, 26 Oct 2022.

Hi BTB,

well for my first question I thought of higher level languages and guessed that the images of e.g. IMRL30.def are used as an array of images. The images are -3 morale over neutral to +3 morale (7 images). My expectation was that when I have a possible morale of -4 to +6 I only have to rearrange the boundaries when the "pointer" to the correct image is calculated. But I could not recognize anything that would be this pointer, an access to the image or anything else looking familiar.

For the second question, the part where I tried to add a new speciality to Visions I thought about substacting not 0D but 02 so I could move the speciality information. But doing that I can't influence Hypnotize.
I now have used AlexSpl program to expand the space. (@AlexSpl: Thanks alot for the tip) It seems to work because I can still run Heroes. But I don't get it work with visions. What I have done is:
 1. Copy all speciality data to the new area (from 0E6358 to 2B2000)
 2. Make sure the first number of 2B2000 starts with the first spell (Summon Boat) and all "new" spells return 06.
 3. Set the thrid spell to 04 to be executed at expert level
 4. Changed the code at 0E6291 to:
       Heroes3 HD.exe+E6291 - 90 90 90 90 90 90 90 90 - nop                                          No operations regarding 0D substraction, just use the spell speciality
       Heroes3 HD.exe+E6299 - 33 D2                   - xor edx,edx                                  Null the edx
       Heroes3 HD.exe+E629B - 8A 90 00D06D00          - mov dl,[eax+006DD000]                        Load the speciality type (I don't understand why it is not 006B2000
       Heroes3 HD.exe+E62A1 - FF 24 95 3C634E00       - jmp dword ptr [edx*4+"Heroes3 HD.exe"+E633C] Untouched
       Heroes3 HD.exe+E62A8 - 8B 45 0C                - mov eax,[ebp+0C]                             Untouched
       Heroes3 HD.exe+E62AB - 5E                      - pop esi                                      Untouched
       Heroes3 HD.exe+E62AC - 8B 04 85 A8EA6300       - mov eax,[eax*4+"Heroes3 HD.exe"+23EAA8]      Untouched
       Heroes3 HD.exe+E62B3 - 8B E5                   - mov esp,ebp                                  Untouched
       Heroes3 HD.exe+E62B5 - 5D                      - pop ebp                                      Untouched
       Heroes3 HD.exe+E62B6 - C2 0C00                 - ret 000C                                     Untouched
 But it still don't work. I know that this routine is called, when Weakness, Curse or Stone Skin is called and it this still works. But for Visions it do not enter even the code calling the function where other (in battle spells) are called. Do you have any clue how it coould work?

For the third question: Thanks, there are some additional images in the H3bitmap.lod, but that might not have been used in the end.

The forth question the first thing I was supprised by was that the code at 4422C9 is always executed by hovering over the target unit. I expected it to be triggered once but I asume it has to be this way to detect the end of the magical effect. I tried to step through the commands but get lost because I can't figure out what some of the operands do. I would try the following:

 1. Overwrite 42255 to jump at a new location (maybe my new space)
 2. NOP out to 4225E
At the new area I would
 1. Load the skill (mov a1,[edi+00000498]
 2. Test if the power is 0
 3. JNE 6.
 4. Set defense to 0 (pop edi and ebp)
 5. return to caller (code after 42255)
 6. Test if the power is 1
 7. JNE 10.
 8. Set defense to 1/4 of the original value
 9. return to caller (code after 42255)
 10. Test if the power is 2
 11. JNE 14.
 12. Set defense to 1/2 of the original value
 13. return to caller (code after 42255)
 12. Set defense to 3/4 of the original value
 13. return to caller (code after 42255)

But it is really difficult when a even fail at understanding the Opcode of "test". How can I test on a1 == 2? Else I do not know how to call a function correctly. As mentioined above I thought the target should be 006b200 (2b2000 + 400000) When I than try to lay some coding at 2b20a0 and try to get the correct address by editing in Cheat Engine I land anywhere but at my code (although I took also a look on big endien address).

Best regards

The bloody newbie parascus
____________

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


Responsible
Supreme Hero
posted October 26, 2022 11:48 AM
Edited by AlexSpl at 11:51, 26 Oct 2022.

Quote:
But I don't get it work with visions.

Visions' code starts @ 0x41C69B. For example, @ 0x41C727 the following function is called:

int hero::GetManaCost(int,armyGroup *,bool)

You have to place your jump somewhere around these addresses to implement your new adventure spell specialty code.

In your example above you are in the following function - hero::GetHeroSpellBonus() - which, indeed, calculates spell bonuses, but to make it work for Visions, you have to:

1) Add a new case into it;
2) Add a routine to Visions' code @ 0x41C69B so that it would actually call -

int hero::GetHeroSpellBonus(SpellID,int,int)

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


Adventuring Hero
posted October 26, 2022 12:11 PM

Hi AlexSpl,

how does your functions work. At this moment I only have the executable file. I asume the language is C++ which I learned a long long ... long time ago. Are there sources whcih can be expanded? Does this compile in ddl files? If yes, how do I do the connection between the original functions and the dll functions?

Best Regards

Parascus
____________

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


Responsible
Supreme Hero
posted October 26, 2022 12:19 PM

Quote:
Are there sources whcih can be expanded? Does this compile in ddl files? If yes, how do I do the connection between the original functions and the dll functions?

1. Well, there are no sources of the game, all we have is just the executable with debug symbols which, nevertheless, helps a lot.

2. Basically, yes, you do compile your own code and get a dll with your patches which, then, are attached to the original game process.

3. You need some sort of API. The most advanced API for H3 atm is H3API by RoseKavalier.

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


Adventuring Hero
posted October 26, 2022 03:27 PM

Hi AlexSpl,

thanks for your response. But I have to admit that I have to insert some longs in my previous reply.

I do not know what debug symbols is and how to call a dll with assembler language. Else I have downloaded Visual Studio Code and added the API of RoseKavalier ... resulting in many errors because of the size of the structures. And the tutorial of Visual Studio Code I found where on Version 2010 where you code create a project in VSC but now everything is different. Do you have some easy to understand docs I can look at?

I admit it would be easier to code the functions and call them from HOMM III, but for me I don't think it's the lack of C++ knowledge regarding language. It is the infrastructure like the variable types to use, presets to get a dll compiled and link them to the executable.

Any further tipps are welcome.

Best regards

Parascus
____________

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


Responsible
Supreme Hero
posted October 26, 2022 04:00 PM

Quote:
Do you have some easy to understand docs I can look at?

There is a quick start guide for beginners there (you'll probably need to translate it first). After completing all the steps you will write your first simple plugin which uses patcher_x86 (you can do most no-so-complicated things with just it alone). You will find more complex examples to compile throughout the thread, if language is not a big issue to you.

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


Adventuring Hero
posted October 26, 2022 04:16 PM



I will give Google Translate a try ... never learned russian and I'm glad to get by with englisch.

Best regards and thanks for the link

Parascus
____________

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


Responsible
Supreme Hero
posted October 26, 2022 05:01 PM
Edited by AlexSpl at 17:04, 26 Oct 2022.

If you manage to build your first plugin, you'll be able to re-use its code, changing something here and there, for most, if not all, of your simple tasks, including direct hex-patching. You won't need jumps (forth and back) anymore, nor to restore instructions wiped by them, and will be able to carry over all of your previous patches directly to a plugin by using the following function:

_PI->WriteHexPatch(0xADDRESS, "YO UR PA TC H.");

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


Adventuring Hero
posted October 26, 2022 05:03 PM

Hi AlexSpl,

ok now I have a start. I could translate the first steps via Google as well es the first comments of the patcher_x86.hpp. I changed the compilation settings to Win32 everywhere I found them. The compilation was successful and I copied the DLL into the Packs folder of _HD3_Data. But when I use HD-Launcher and try to add the plugin the list is empty. Any idea what I did wrong or missed?

Best regards

Parascus
____________

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


Responsible
Supreme Hero
posted October 26, 2022 05:05 PM

You should create a folder with the name of your plugin in the Packs folder and copy your dll into it.

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


Adventuring Hero
posted October 26, 2022 05:45 PM

Hi once more,

thank you for this hint. Now I got the Message when the day changes. Great!

Do I understand this correct:
1. the Patcher is determined
2. a patcher instance is created by the patcher
3. a function call is written into the homm3.exe which calls the dll function.

But how do I know the locations where I can write the function call into?

Thanks in advance

Parascus
____________

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


Responsible
Supreme Hero
posted October 26, 2022 06:16 PM

Quote:
Do I understand this correct:
1. the Patcher is determined
2. a patcher instance is created by the patcher
3. a function call is written into the homm3.exe which calls the dll function.

1, 2. Yes. 3. It's more complicated than that. Basically (for so-called hooks), the patcher writes a jump to the address space of a dll where your custom code is stored, makes all necessary and routine work for you to run your code in a correct way, and then jumps back to the original code (you can specify return address and whether to execute instructions wiped by your jumps or not).

Quote:
But how do I know the locations where I can write the function call into?

It's the same thing as with hex-patches. You have to analyze the code of the game (by reading listings created by disassemblers like IDA, by setting breakpoints, etc.). Later, when you get accustomed to basics, you will be able to re-write whole functions of the original game without much trouble using available APIs.

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


Adventuring Hero
posted October 26, 2022 06:43 PM

Hi AlexSpl,

now I (think I) understand. It's a hook which does not replace the original exe code but is asked everytime a specific address is executed. And by returning EXEC_DEFAULT it also executes the code afterwards. When I don't want this, I can return NO_EXEC_DEFAULT. And in this case I have to define an address where the original code continues to run. And I always get the LoHook and HookContext addresses and can read e.g. the registers.

And if I know in a register there's a heroe structure I can read the specific fields? And can I also manipulate the memory with this pointer so I can (in my case) set the defense value of a unit (asuming I have the pointer again)?

Kind regards

Parascus
____________

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


Responsible
Supreme Hero
posted October 26, 2022 06:48 PM
Edited by AlexSpl at 18:50, 26 Oct 2022.

Quote:
And if I know in a register there's a heroe structure I can read the specific fields? And can I also manipulate the memory with this pointer so I can (in my case) set the defense value of a unit (asuming I have the pointer again)?

Exactly It's a true magic of high-level programming. Your code will become readable. For example,

double army::ComputeAttackerDamageReduction(army* defender, bool is_shooting)
{
  int attack = get_adjusted_attack(defender, is_shooting);
  int defense = defender->get_adjusted_defense(this, true);

  double mod = defense > attack ? min(1.0 - (defense - attack) * 0.025, 0.3) : 1.0;
 
  if (this->armyType == eCreaturePsychicElemental && defender->sMonInfo.attributes & CF_IMMUNE_TO_MIND_SPELLS)
     mod *= 0.5;

  if (this->armyType == eCreatureMagicElemental &&
     (defender->armyType == eCreatureMagicElemental || defender->armyType == eCreatureBlackDragon))
     mod *= 0.5;

  if (is_shooting)
  {
     int hex = this->gridIndex;
     if (this->sMonInfo.attributes & CF_DOUBLE_WIDE)
        hex += this->facing ? 1 : -1;

     if (pCombatManager->hasObstaclePenalty(this, hex, defender->gridIndex))
        mod *= 0.5;

     if (pCombatManager->hasDistancePenalty(this, defender))
        mod *= 0.5;
  }

  if (this->sMonInfo.attributes & CF_SHOOTING_ARMY && !is_shooting && !(sMonInfo.attributes & CF_NO_MELEE_PENALTY))
     mod *= 0.5;

  // Effects
  bool blinded = this->residualBlindness;
  bool paralyzed = this->residualParalyze;
  int blindRetalMod = (int)(this->blindFactor * 100);
  int paralyzeRetalMod = o_Spell[SPELL_PARALYZE].effect[eMasteryAdvanced];

  int effectMod = 100;

  if (blinded && blindRetalMod < effectMod)
     effectMod = blindRetalMod;

  if (paralyzed && paralyzeRetalMod < effectMod)
     effectMod = paralyzeRetalMod;
 
  if (spellInfluence[SPELL_FEAR])
  {
     int schoolLevel = activeSpellMastery[this->group][this->index][SPELL_FEAR];
     if (fearSpellParams[schoolLevel].retalDamageMod < effectMod)
        effectMod = fearSpellParams[schoolLevel].retalDamageMod;
  }

  mod = mod * effectMod / 100;
  return mod;
}

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


Adventuring Hero
posted October 26, 2022 07:10 PM

Hi AlexSpl,

thanks for the example. This shows good where a problem of mine really is. Your signiture of the function is:
double army::ComputeAttackerDamageReduction(army* defender, bool is_shooting)

In this case you use a namespace or it is C++? Is the army:: necessary or just a convenience?

Army* is a pointer on the defender, the boolean is a flag indicating the attack was a shot? That's different from a LoHook pointer and a HookContext. And you return the modifier as a double value instead of the info if the original code has to be executed as well. Is this because this is jsut a sub procedure you are calling from you hook?

At this moment I try to modify the defense reduction using frenzy. I think in eax there is the power info of the spell table. So I ask:
int __stdcall GetHeroSpellBonus(LoHook* h, HookContext* c)
{
   if (c->eax == 3) {

   }
   else if (c->eax == 2)
   {

   }
   else if (c->eax == 1)
   {

   }
   else
   {

   }

   return EXEC_DEFAULT;
}
Looking into the executable (4422C9) I find the following opcodes:
  pop edi
  pop ebp

I would have expected an access to a register (or an offset of a register and a assignment of 0. What does it do besides irritating me?

I'm sorry that I have so many questions but it is really interesting and every time I manage something, it's like xmass.

Best wishes

Parascus
____________

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


Responsible
Supreme Hero
posted October 26, 2022 07:24 PM
Edited by AlexSpl at 19:29, 26 Oct 2022.

Quote:
Is this because this is jsut a sub procedure you are calling from you hook?

Yes, it is. The above function is called from HiHook, but I'd recommend to use LoHook as it has a standard signature and, generally, closer to what we see in listings produced by disassemblers. You can directly work with registers in LoHook. If you know, for example, that in c->ebx is a pointer to hero, you can write:

hero* Hero = (hero*)c->ebx;

and then work with Hero as a pointer to an instance of the class hero, making things much simpler. For example, that's how you can read Hero's attack:

Hero->attack

That simple.

Quote:
Looking into the executable (4422C9) I find the following opcodes:
 pop edi
 pop ebp

I would have expected an access to a register (or an offset of a register and a assignment of 0. What does it do besides irritating me?


Those instructions just belong to what is called a function's epilogue, don't touch them Better try to compile a couple of simple plugins to get more experience of how things work.

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


Responsible
Supreme Hero
posted October 26, 2022 07:47 PM

Here's the class hero with some methods even (and, of course, field offsets for convenience):

#pragma pack(push, 1)
class hero : public type_obscuring_object
{
public:
  short mana;                               // 0x018
  THeroID id;                               // 0x01A
  int map_editor_id;                        // 0x01E
  char playerOwner;                         // 0x022
  char name[13];                            // 0x023
  THeroClass hero_class;                    // 0x030
  unsigned char portrait;                   // 0x034
  int targetX;                              // 0x035
  int targetY;                              // 0x039
  short targetZ;                            // 0x03D
  short last_magic_school_level;            // 0x03F
  unsigned short target_distance;           // 0x041
  unsigned char target_is_critical;         // 0x043
  unsigned char patrolX;                    // 0x044
  unsigned char patrolY;                    // 0x045
  char patrolRadius;                        // 0x046
  unsigned char facing;                     // 0x047
 
  enum Formation : int {
     GroupedFormation = 1,
     PlacementFormation = 2
  };

  unsigned char formation;                  // 0x048
  int maxMobility;                          // 0x049
  int currMobility;                         // 0x04D
  int experience;                           // 0x051
  short Level;                              // 0x055
  unsigned long TrainingGroundFlags;        // 0x057
  unsigned long DefenseTowerFlags;          // 0x05B
  unsigned long GardenOfRevelationFlags;    // 0x05F
  unsigned long MercCampFlags;              // 0x063
  unsigned long PowerSchoolFlags;           // 0x067
  unsigned long TreeOfKnowledgeFlags;       // 0x06B
  unsigned long LibraryFlags;               // 0x06F
  unsigned long ArenaFlags;                 // 0x073
  unsigned long MagicSchoolFlags;           // 0x077
  unsigned long WarSchoolFlags;             // 0x07B
  unsigned long UniversityFlags;            // 0x07F
  unsigned long Shrine1Flags;               // 0x083
  unsigned long Shrine2Flags;               // 0x087
  unsigned long Shrine3Flags;               // 0x08B
  unsigned char iLevelSeed;                 // 0x08F
  unsigned char lastWisdom;                 // 0x090
  armyGroup heroArmy;                       // 0x091
  char SSLevel[28];                         // 0x0C9
  unsigned char SSOrder[28];                // 0x0E5
  int numSSs;                               // 0x101
  unsigned long flags;                      // 0x105
  float turnExperienceToRVRatio;            // 0x109
  char dWalkSpellsCast;                     // 0x10D
  TSkillMastery disguiseLevel;              // 0x10E
  TSkillMastery flightLevel;                // 0x112
  TSkillMastery waterWalkPower;             // 0x116
  char moraleBonus;                         // 0x11A
  char luckBonus;                           // 0x11B
  bool IsSleeping;                          // 0x11C
  long bounty;                              // 0x11D                              
  std::bitset<48> TownSpecialGrantedMask;   // 0x121
  TSkillMastery visionsPower;               // 0x129
  type_artifact equipped[19];               // 0x12D
  bool locked_slot[15];                     // 0x1C6
  type_artifact backpack[64];               // 0x1D4
  char backpack_count;                      // 0x3D4
  TSex sex;                                 // 0x3D5
  bool IsBiographyCustomized;               // 0x3D9
  stdString customBiography;                // 0x3DA
  char in_spellbook[140];                   // 0x3EA
  //bool in_spellbook[70];                  // 0x3EA
  //bool available_spells[70];              // 0x430
  char stats[4];                            // 0x476
  float aggression;                         // 0x47A
  long value_of_power;                      // 0x47E
  long value_of_duration;                   // 0x482
  long value_of_knowledge;                  // 0x486
  long value_of_spring;                     // 0x48A
  long value_of_well;                       // 0x48E
                                            // 0x492

   inline int get_spell_level(SpellID spell, int land_modifier) {
      return CALL_3(int, __thiscall, 0x4E52F0, this, spell, land_modifier);
   }
   inline int GetManaCost(int iWhichSpell, armyGroup* const enemy, int land_modifier) {
      return CALL_4(int, __thiscall, 0x4E54B0, this, iWhichSpell, enemy, land_modifier);
   }
   inline void UseSpell(int cost) {
      CALL_2(void, __thiscall, 0x4D9540, this, cost);
   }
   inline int GetHeroSpellBonus(SpellID spell_id, int target_level, int value) {
      return CALL_4(int, __thiscall, 0x4E6260, this, spell_id, target_level, value);
   }
   void AddSpell(int whichSpell);
   void UpdateSpellsFromArtifacts();
   int getBestMagicSchoolForSpell(SpellID spell);
   inline TAdventureObjectType get_special_terrain() {
      return CALL_1(TAdventureObjectType, __thiscall, 0x4E5210, this);
   }
};
#pragma pack(pop)

You may freely get any info you want about a hero from just knowing a pointer.

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


Adventuring Hero
posted October 26, 2022 09:17 PM

Hello AlexSpl,

thanks for the structure. I have found the files of RoseKavalier and try to use them. But as you suggested I start with some easy tasks ... and failed :-(

I have the following function:
   void changeSkillValues()
   {
       char buf[48] = "0000000000010000EE020000EE020000";
       char* conbuf = (char*)buf;
       _PI->WriteHexPatch(0x0063ea18, conbuf);
   }

This should change the amount of money with the skills of estates. In this case, basic estates has 00010000. Having the big/little endien this should be 256 of additional gold. When I test this, I get 268 gold more. When I check this with the cheat engine everything seems fine ...

Sorry, but do you have any idea? (Last question for today)

Kind regards

Parascus
____________

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


Responsible
Supreme Hero
posted October 26, 2022 09:24 PM
Edited by AlexSpl at 21:25, 26 Oct 2022.

Use decimal values:

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.NewEstates");
       
        _PI->WriteDword(0x63EA18, 0);      // None
        _PI->WriteDword(0x63EA1C, 125);    // Basic
        _PI->WriteDword(0x63EA20, 250);    // Advanced
        _PI->WriteDword(0x63EA24, 500);    // Expert Estates
       
        // ...

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Jump To: « Prev Thread . . . Next Thread » This thread is 41 pages long: 1 10 20 ... 28 29 30 31 32 ... 40 41 · «PREV / NEXT»
Post New Poll    Post New Topic    Post New Reply

Page compiled in 0.1026 seconds