Объявления

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

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

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1315
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 04 ноя 2017, 16:46

Ok, I always was weak in graphic things...

I have added condition
Код: Выделить всё
isSkeletsAreSlowestInArmy()
for
Код: Выделить всё
removeSkeletsFromArmy()


Procedures isSkeletsAreSlowestInArmy(), removeSkeletsFromArmy(), haveHeroTent(), haveHeroBallista(), isWaterMap(), numberOfNecroTowns(), numberOfAllTowns(), numberOfSkelets(), skeletsAISum(), armyAISum()
I will write later.

* * *
... though it will be better without isSkeletsAreSlowestInArmy().
And I have replaced numberOfSkelets() by undeadsAISum()
Последний раз редактировалось Ben80 05 ноя 2017, 12:07, всего редактировалось 6 раз(а).
Вернуться к началу

offlineRoseKavalier  
Мастер
Мастер
 
Сообщения: 331
Зарегистрирован: 23 сен 2017, 17:00
Пол: Не указан
Поблагодарили: 234 раз.

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

Сообщение RoseKavalier » 04 ноя 2017, 20:43

Seems to work fine for human, on SoD and HotA.
Of course it will need to be fine-tuned (possibly make cost higher based on hero level?) and could add some extra information (like current player gold).
First time creating something in DEFTool, it's not perfect but a good start I think!
[youtube]http://youtu.be/MTGQ8s6pwVk[/youtube]

main.cpp is below; I have added some extra things in includes which you can copy from GitHub. [removed some files per request]
Compiled DLL & 2 DEF files are attached.

I did not add anything for AI.
Код: Выделить всё
#include "includes\HoMM3_Extra.h"

Patcher* _P;
PatcherInstance* _PI;

#pragma pack(push, 1)
struct _SSkillInfo_
{
   char* name;
   char* desc[3];
};
#pragma pack(pop)

#define BID_MARKET_OF_TIME 50
#define o_SSkillInfo (*(_SSkillInfo_**)0x67DCF0)
#define o_SkillLevel(level) (*(char**)(0x6A75D4 + 4 * skill_level))
#define GOLD_NAME (*(char**)0x6A5EE4)
#define MARKET_OF_TIME_NAME (*(char**)0x6A7B1C)

#define COST1 2000
#define COST2 3500
#define COST3 5000

#define ENOUGH_GOLD 0
#define NOT_ENOUGH_GOLD 1

_Hero_ *hero;
_Player_ *me;

void UpdateMarket(_Dlg_ *dlg, int gold)
{
   int cost[3] = { COST1, COST2, COST3 };
   _DlgStaticDef_ *SSkill;
   int skill_level;

   for (int i = 0; i < 8; i++) {
      if (SSkill = (_DlgStaticDef_*)dlg->GetItem(101 + i)) {
         if (SSkill->def_frame_index >= 3) {
            skill_level = SSkill->def_frame_index % 3 + 1;
            if (gold < cost[skill_level - 1]) {
               ((_DlgStaticDef_*)(dlg->GetItem(201 + i)))->def_frame_index = NOT_ENOUGH_GOLD;
               ((_DlgStaticDef_*)(dlg->GetItem(301 + i)))->def_frame_index = NOT_ENOUGH_GOLD;
            } // not enough gold
         } // if this skill still exists on hero
      } // if SSkill
   } // loop
}

_DlgStaticTextPcx8ed_* market_of_time_statbar;
int __stdcall MarketOfTimeProc(_Dlg_* dlg, _EventMsg_* msg)
{
   int r = dlg->DefProc(msg);
   char text[100];
   _DlgStaticDef_ *SSkill;
   int skill_id, skill_level;
   int cost[3] = { COST1, COST2, COST3 };
   text[0] = 0;
   if (msg->type == MT_MOUSEOVER) { // update text of status bar
      _DlgItem_* it = dlg->FindItem(msg->x_abs, msg->y_abs);
      if (it) {
         switch (it->id) {
         case 101:
         case 102:
         case 103:
         case 104:
         case 105:
         case 106:
         case 107:
         case 108:
            SSkill = (_DlgStaticDef_*)it;
            if (SSkill->def_frame_index >= 3) {
               skill_level = SSkill->def_frame_index % 3 + 1;
               skill_id = SSkill->def_frame_index / 3 - 1;
               sprintf(text, "Forget %s %s for %d %s.", o_SkillLevel(skill_level), o_SSkillInfo[skill_id].name, cost[skill_level - 1], GOLD_NAME);
            }
            break;
         case DIID_OK:
            sprintf(text, "Exit the %s", MARKET_OF_TIME_NAME);
            break;
         default:
            break;
         }
      }
      market_of_time_statbar->SetText(text);
      market_of_time_statbar->Draw();
      market_of_time_statbar->RedrawScreen();
   }
   if (msg->type == MT_MOUSEBUTTON) { // handle left click of DEFs
      if (msg->subtype == MST_LBUTTONCLICK) {
         _DlgItem_* it = dlg->FindItem(msg->x_abs, msg->y_abs);
         if (it) {
            switch (it->id) {
            case 101:
            case 102:
            case 103:
            case 104:
            case 105:
            case 106:
            case 107:
            case 108:
               SSkill = (_DlgStaticDef_*)it;
               if (SSkill->def_frame_index >= 3) {
                  skill_level = SSkill->def_frame_index % 3 + 1;
                  skill_id = SSkill->def_frame_index / 3 - 1;
                  if (me->resourses.gold >= cost[skill_level - 1]) {
                     e_ClickSound();
                     sprintf(o_TextBuffer, "The old man asks: 'Are you sure you want to forget this skill? This cannot be undone.'\n\nThe fee is %d %s.", cost[skill_level - 1], GOLD_NAME);
                     CALL_12(void, __fastcall, 0x4F6C00, o_TextBuffer, MBX_OKCANCEL, -1, -1, 0x14, SSkill->def_frame_index, -1, 0, -1, 0, -1, 0);
                     if (o_WndMgr->result_dlg_item_id == DIID_OK) {
                        me->resourses.gold -= cost[skill_level - 1];
                        hero->UnlearnSkill(skill_id);
                        SSkill->def_frame_index = 0;
                        dlg->GetItem(it->id + 100)->Hide(); // Hide top bar
                        dlg->GetItem(it->id + 200)->Hide(); // Hide bot bar
                        dlg->GetItem(it->id + 300)->Hide(); // Hide SSkill name
                        dlg->GetItem(it->id + 400)->Hide(); // Hide SSkill level
                        UpdateMarket(dlg, me->resourses.gold);
                        dlg->Redraw();
                     }
                  }
               }
               break;
            default:
               break;
            } // switch
         } // it
      } // MST_LBUTTONCLICK

      if (msg->subtype == MST_RBUTTONDOWN) { // show SSkill information
         _DlgItem_* it = dlg->FindItem(msg->x_abs, msg->y_abs);
         if (it) {
            switch (it->id) {
            case 101:
            case 102:
            case 103:
            case 104:
            case 105:
            case 106:
            case 107:
            case 108:
               SSkill = (_DlgStaticDef_*)it;
               if (SSkill->def_frame_index >= 3) {
                  skill_level = SSkill->def_frame_index % 3 + 1;
                  skill_id = SSkill->def_frame_index / 3 - 1;
                  CALL_12(void, __fastcall, 0x4F6C00, o_SSkillInfo[skill_id].desc[skill_level - 1], MBX_RMC, -1, -1, -1, 0, -1, 0, -1, 0, -1, 0);
               }
               break;
            default:
               break;
            } // switch
         } // it
      } // MT_RBUTTONDOWN
   } // MT_MOUSEBUTTON

   return r;
}

void MarketOfTime(_Hero_ *hero, _Player_ *me)
{
   // simple array that holds cost
   int cost[3] = { COST1, COST2, COST3 };

   //////////////////////
   //
   //   Creation
   //
   //////////////////////
   _Dlg_ *dlg;
   dlg = _CustomDlg_::Create(DLG_X_CENTER, DLG_Y_CENTER, 512, 450, DF_SCREENSHOT | DF_SHADOW, MarketOfTimeProc);

   // background
   dlg->AddItem(_DlgStaticDef_::Create(0, 0, 0, "MarketTime.def", 0, 0, 0));

   // color border to player's hue
   CALL_5(int, __thiscall, 0x5FF400, dlg, 512, 13, 0, me->id);

   // title
   dlg->AddItem(_DlgStaticText_::Create(0, 30, 512, 30, MARKET_OF_TIME_NAME, "bigfont.fnt", 2, 1, ALIGN_H_CENTER | ALIGN_V_CENTER, 0));

   // description
   char* description;
   description = "An old bearded man beckons you over to hear him out. After a few moments, you discover that this strange place allows you to alter some of your past decisions. For a fee, you can forget any of the Secondary Skills you may have learned.";
   dlg->AddItem(_DlgStaticText_::Create(50, 80, 405, 64, description, "smalfont.fnt", 1, 1, ALIGN_H_CENTER | ALIGN_V_CENTER, 0));

   //////////////////////
   //
   //   Secondary Skills
   //
   //////////////////////

   int sskill_y = 182;
   int sskill_x = 75;
   int dx = 104;
   int dy = 119;
   int bar_x = 47;
   int top_bar_y = 160;
   int bot_bar_y = 230;
   int sskill_count = hero->second_skill_count;

   for (int i = 0; i < sskill_count; i++) {
      int row = i / 4;
      int col = i % 4;
      int skill = hero->ShownSSkillPosition(i + 1);
      int skill_level = hero->second_skill[skill];
      int def_frame = 2 + 3 * skill + skill_level;

      // skill def
      dlg->AddItem(_DlgStaticDef_::Create(sskill_x + dx * col, sskill_y + dy * row, 101 + i, "Secskill.def", def_frame, 0, 0));

      // allowed/disallowed colors
      int allowed_disallowed = me->resourses.gold >= cost[skill_level - 1] ? ENOUGH_GOLD : NOT_ENOUGH_GOLD;
      dlg->AddItem(_DlgStaticDef_::Create(bar_x + dx * col, top_bar_y + dy * row, 201 + i, "MarketBars.def", allowed_disallowed, 0, 0));
      dlg->AddItem(_DlgStaticDef_::Create(bar_x + dx * col, bot_bar_y + dy * row, 301 + i, "MarketBars.def", allowed_disallowed, 0, 0));

      // skill name text
      dlg->AddItem(_DlgStaticText_::Create(bar_x + dx * col, top_bar_y + dy * row, 100, 18, o_SSkillInfo[skill].name, "smalfont.fnt", 1, 401 + i, ALIGN_H_CENTER | ALIGN_V_CENTER, 0));

      // skill level text
      dlg->AddItem(_DlgStaticText_::Create(bar_x + dx * col, bot_bar_y + dy * row, 100, 18, o_SkillLevel(skill_level), "smalfont.fnt", 1, 501 + i, ALIGN_H_CENTER | ALIGN_V_CENTER, 0));
   }

   //////////////////////
   //
   //   Status Bar
   //
   //////////////////////
   market_of_time_statbar = _DlgStaticTextPcx8ed_::Create(8, 425, 512 - 16, 18, "", "smalfont.fnt", "HD_TStat.bmp", 1, 4000, ALIGN_H_CENTER | ALIGN_V_CENTER);
   dlg->AddItem(market_of_time_statbar);

   //////////////////////
   //
   //   Exit Button
   //
   //////////////////////
   dlg->AddItem(_DlgStaticPcx8_::Create(512 / 2 - 33, 450 - 72, 1234, "Box64x30.pcx"));
   dlg->AddItem(_DlgButton_::Create(512 / 2 - 32, 450 - 71, 64, 30, DIID_OK, "iOkay.def", 0, 1, 1, 28, 2));

   //////////////////////
   //
   //   Finish up
   //
   //////////////////////
   o_SoundMgr->PlaySample("HASTE.wav");
   o_MouseMgr->ChangeCursor(0, 0);
   dlg->Run();
   dlg->Destroy(TRUE);
}

int __stdcall EnterMarketTime(LoHook *h, HookContext *c)
{
   if (c->ebx == BID_MARKET_OF_TIME) {
      hero = (_Hero_*)c->arg_n(1);
      me = o_GameMgr->GetPlayer(hero->owner_id);
      if (c->arg_n(4)) { // human
         MarketOfTime(hero, me);
      }
      else { // AI

      }
   }
   return EXEC_DEFAULT;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
   static _bool_ plugin_On = 0;
   switch (ul_reason_for_call)
   {
   case DLL_PROCESS_ATTACH:
      if (!plugin_On)
      {
         plugin_On = 1;
         _P = GetPatcher();
         _PI = _P->CreateInstance("MarketOfTime");
         _PI->WriteLoHook(0x4A8194, EnterMarketTime); // same spot HotA uses
      }
      break;

   case DLL_THREAD_ATTACH:
   case DLL_THREAD_DETACH:
   case DLL_PROCESS_DETACH:
      break;
   }
   return TRUE;
}
Вложения
MarketOfTime.zip
Beta
(89.24 КБ) Скачиваний: 160
Последний раз редактировалось RoseKavalier 04 дек 2017, 17:27, всего редактировалось 1 раз.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1315
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 05 ноя 2017, 06:30

I have downloaded MarketOfTime-master.zip, create new project, put contents of main.cpp to dllmain.cpp, and copy folder "include" to project folder.

During compiling try I get:
1>Linking...
1>dllmain.obj : error LNK2001: unresolved external symbol "public: static struct _Dlg_ * __cdecl _CustomDlg_::Create(int,int,int,int,unsigned int,int (__stdcall*)(struct _Dlg_ *,struct _DlgMsg_ *))" (?Create@_CustomDlg_@@SAPAU_Dlg_@@HHHHIP6GHPAU2@PAU_DlgMsg_@@@Z@Z)
1>dllmain.obj : error LNK2001: unresolved external symbol "public: void __thiscall _DlgItem_::RedrawScreen(void)" (?RedrawScreen@_DlgItem_@@QAEXXZ)
1>dllmain.obj : error LNK2001: unresolved external symbol "struct _Wav_ * __fastcall LoadWav(char *)" (?LoadWav@@YIPAU_Wav_@@PAD@Z)

P.S. Version of Visual C++ 2008
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1315
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 05 ноя 2017, 09:44

I have wrote setIsWaterMap. It was tested.

Код: Выделить всё
bool isWaterMap = false;
...
int __stdcall setIsWaterMap(LoHook* h, HookContext* c)
{
   int mapSize = o_GameMgr->Map.size;
   int waterSize = 0;
   int rockSize = 0;
   
   for(int i = 0; i<mapSize; i++)
      for(int j = 0; j<mapSize; j++)
      {
         int mapItemAddress = (int)o_GameMgr->Map.GetItem(i,j,0);
         int land = (int)(*(_byte_*)(mapItemAddress + 4));
         if(land == 8)
            waterSize = waterSize + 1;
         if(land == 9)
            rockSize = rockSize + 1;
      }

   if(o_GameMgr->Map.has_underground)
   for(int i = 0; i<mapSize; i++)
      for(int j = 0; j<mapSize; j++)
      {
         int mapItemAddress = (int)o_GameMgr->Map.GetItem(i,j,1);
         int land = (int)(*(_byte_*)(mapItemAddress + 4));
         if(land == 8)
            waterSize = waterSize + 1;
         if(land == 9)
            rockSize = rockSize + 1;
      }
   
   mapSize = mapSize * mapSize;
   if(o_GameMgr->Map.has_underground)
      mapSize = mapSize * 2;

   if((double)waterSize/(double)(mapSize - rockSize) > 0.1)
      isWaterMap = true;
   //waterPart = (double)waterSize/(double)(mapSize - rockSize);
   return EXEC_DEFAULT;
}
...
_PI->WriteLoHook(0x4FDF90, setIsWaterMap);
Последний раз редактировалось Ben80 05 ноя 2017, 10:39, всего редактировалось 1 раз.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1315
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 05 ноя 2017, 09:48

I was not be able write code with mapItemAddress as _MapItem_*
If you will write code example which uses _MapItem_* it would be interesting for me.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1315
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 05 ноя 2017, 10:17

RoseKavalier писал(а):

Of course it will need to be fine-tuned (possibly make cost higher based on hero level?) and could add some extra information (like current player gold).


May be better stay on classical line, without complexations such as making cost higher based on hero level ?
(I use complex algorithms for AI, but in original game AI also often uses complex algorithms, and it is invisible for gamer. The visible part of game (SoD) is classical, simple and ... beautiful)
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1315
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 05 ноя 2017, 11:36

Another procedures:

Код: Выделить всё
int skeletsAISum(_Hero_* hero)
{
   int sum = 0;
   for (int i = 0; i<7; i++)
      if(hero->army.type[i] == 56 || hero->army.type[i] == 57)
         sum = sum + o_CreatureInfo[hero->army.type[i]].AI_value * hero->army.count[i];
   return sum;
}

int armyAISum(_Hero_* hero)
{
   int sum = 0;
   for (int i = 0; i<7; i++)
         sum = sum + o_CreatureInfo[hero->army.type[i]].AI_value * hero->army.count[i];
   return sum;
}

int undeadsAISum(_Hero_* hero)
{
   int sum = 0;
   for (int i = 0; i<7; i++)
      if(hero->army.type[i] > 55 && hero->army.type[i] < 70)
         sum = sum + o_CreatureInfo[hero->army.type[i]].AI_value * hero->army.count[i];
   return sum;
}

int numberOfNecroTowns(_Hero_* hero)
{
    int sum = 0;
    _Player_* player1 = o_GameMgr->GetPlayer(hero->owner_id);
    for(int i=0; i<player1->towns_count; i++)
        if (o_GameMgr->GetTown(player1->towns_ids[i])->type == 4)
            sum = sum + 1;
    return sum;
}
Последний раз редактировалось Ben80 05 ноя 2017, 15:47, всего редактировалось 1 раз.
Вернуться к началу

offlineRoseKavalier  
Мастер
Мастер
 
Сообщения: 331
Зарегистрирован: 23 сен 2017, 17:00
Пол: Не указан
Поблагодарили: 234 раз.

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

Сообщение RoseKavalier » 05 ноя 2017, 15:04

Ben80 писал(а):

I have downloaded MarketOfTime-master.zip, create new project, put contents of main.cpp to dllmain.cpp, and copy folder "include" to project folder.

During compiling try I get:
1>Linking...
1>dllmain.obj : error LNK2001: unresolved external symbol "public: static struct _Dlg_ * __cdecl _CustomDlg_::Create(int,int,int,int,unsigned int,int (__stdcall*)(struct _Dlg_ *,struct _DlgMsg_ *))" (?Create@_CustomDlg_@@SAPAU_Dlg_@@HHHHIP6GHPAU2@PAU_DlgMsg_@@@Z@Z)
1>dllmain.obj : error LNK2001: unresolved external symbol "public: void __thiscall _DlgItem_::RedrawScreen(void)" (?RedrawScreen@_DlgItem_@@QAEXXZ)
1>dllmain.obj : error LNK2001: unresolved external symbol "struct _Wav_ * __fastcall LoadWav(char *)" (?LoadWav@@YIPAU_Wav_@@PAD@Z)

P.S. Version of Visual C++ 2008

I downloaded VS 2008 and retraced your steps... it works no problem?
Double-check every file is added to project, otherwise I can share zipped folder.
 
Изображение
Изображение


~~~~~

_MapItem_ example from long ago when I was reversing, but I updated code for includes (I did not have the includes back then).
Код: Выделить всё
_MapItem_ *item;
int size = o_GameMgr->GetMapWidth();
int depth = o_GameMgr->GetMapDepth();

for (int k = 0; k <= depth; k++) {
   for (int j = 0; j < size; j++) {
      for (int i = 0; i < size; i++) {
         item = o_GameMgr->Map.GetItem(i, j, k);
         item->land_type = 0;
         item->land = (item->land + 1) % 10;
      }
   }
}
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1315
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 05 ноя 2017, 16:00

Here all procedures related to getWorstSecSkill. There all were tested a bit except getWorstSecSkill.
About 200 code lines. Use it.

getWorstSecSkill.h
(7.51 КБ) Скачиваний: 151


Код: Выделить всё
bool isWaterMap = false;
...

int skeletsAISum(_Hero_* hero)
{
   int sum = 0;
   for (int i = 0; i<7; i++)
      if(hero->army.type[i] == 56 || hero->army.type[i] == 57)
         sum = sum + o_CreatureInfo[hero->army.type[i]].AI_value * hero->army.count[i];
   return sum;
}

int armyAISum(_Hero_* hero)
{
   int sum = 0;
   for (int i = 0; i<7; i++)
         sum = sum + o_CreatureInfo[hero->army.type[i]].AI_value * hero->army.count[i];
   return sum;
}

int undeadsAISum(_Hero_* hero)
{
   int sum = 0;
   for (int i = 0; i<7; i++)
      if(hero->army.type[i] > 55 && hero->army.type[i] < 70)
         sum = sum + o_CreatureInfo[hero->army.type[i]].AI_value * hero->army.count[i];
   return sum;
}

int numberOfNecroTowns(_Hero_* hero)
{
    int sum = 0;
    _Player_* player1 = o_GameMgr->GetPlayer(hero->owner_id);
    for(int i=0; i<player1->towns_count; i++)
        if (o_GameMgr->GetTown(player1->towns_ids[i])->type == 4)
            sum = sum + 1;
    return sum;
}


int __stdcall setIsWaterMap(LoHook* h, HookContext* c)
{
    int mapSize = o_GameMgr->Map.size;
    int waterSize = 0;
    int rockSize = 0;
   
    for(int i = 0; i<mapSize; i++)
        for(int j = 0; j<mapSize; j++)
        {
            int mapItemAddress = (int)o_GameMgr->Map.GetItem(i,j,0);
            int land = (int)(*(_byte_*)(mapItemAddress + 4));
            if(land == 8)
                waterSize = waterSize + 1;
            if(land == 9)
                rockSize = rockSize + 1;
        }

    if(o_GameMgr->Map.has_underground)
    for(int i = 0; i<mapSize; i++)
        for(int j = 0; j<mapSize; j++)
        {
            int mapItemAddress = (int)o_GameMgr->Map.GetItem(i,j,1);
            int land = (int)(*(_byte_*)(mapItemAddress + 4));
            if(land == 8)
                waterSize = waterSize + 1;
            if(land == 9)
                rockSize = rockSize + 1;
        }
   
    mapSize = mapSize * mapSize;
    if(o_GameMgr->Map.has_underground)
        mapSize = mapSize * 2;

    if((double)waterSize/(double)(mapSize - rockSize) > 0.1)
        isWaterMap = true;
   else
      isWaterMap = false;
    //waterPart = (double)waterSize/(double)(mapSize - rockSize);
    return EXEC_DEFAULT;
}

bool isNecromancyNeeded(_Hero_* ourHero)
{
    int numberOfAllTowns = o_GameMgr->GetPlayer(ourHero->owner_id)->towns_count;
       
    if(CALL_2(double, __thiscall, 0x4E3F40, ourHero, 0) < 0.25 && numberOfNecroTowns(ourHero)/numberOfAllTowns < 0.3
    && undeadsAISum(ourHero) < 10000)
        return false;
    return true;
}

int getWorstSecSkill (_Hero_* ourHero)
{
    int attack = ourHero->attack;
   
    if((int)ourHero->second_skill[HSS_NAVIGATION] > 0 && isWaterMap == false)
        return HSS_NAVIGATION;
       
    if((int)ourHero->second_skill[HSS_NECROMANCY] > 0 && isNecromancyNeeded(ourHero) == false)
    {
      //if(skeletsAISum(ourHero)/armyAISum(ourHero) < 0.3)
      //   removeSkeletsFromArmy();
        return HSS_NECROMANCY;
    }
   
    if(ourHero->level >= 10 && ourHero->level < 20)
    {     
        if((int)ourHero->second_skill[HSS_EAGLE_EYE] == 1)
            return HSS_EAGLE_EYE;
       
        if((int)ourHero->second_skill[HSS_SCOUTING] == 1)
            return HSS_SCOUTING;
     
        if((int)ourHero->second_skill[HSS_FIRST_AID] == 1 && ourHero->DoesHasArtifact(AID_FIRST_AID_TENT) == false)
        if(armyAISum(ourHero) / second_skill[HSS_FIRST_AID] > 15000)
            return HSS_FIRST_AID;
       
        if((int)ourHero->second_skill[HSS_ARTILLERY] == 1 && ourHero->DoesHasArtifact(AID_BALLISTA) == false)
        if((double)armyAISum(ourHero) / pow((double)(second_skill[HSS_ARTILLERY] * attack), 0.8) > 4000.0)
            return HSS_ARTILLERY;
       
        if((int)ourHero->second_skill[HSS_PATHFINDING] == 1)
            return HSS_PATHFINDING;

        if((int)ourHero->second_skill[HSS_MYSTICISM] == 1)
            return HSS_MYSTICISM;
         
        if((int)ourHero->second_skill[HSS_FIRST_AID] == 1)
        if(armyAISum(ourHero) / second_skill[HSS_FIRST_AID] > 30000)
            return HSS_FIRST_AID;
       
        if((int)ourHero->second_skill[HSS_ARTILLERY] == 1)
        if((double)armyAISum(ourHero) / pow((double)(second_skill[HSS_ARTILLERY] * attack), 0.8) > 8000.0)
            return HSS_ARTILLERY;
    }
   
    if(ourHero->level >= 20 && ourHero->level < 30)
    {       
        if((int)ourHero->second_skill[HSS_EAGLE_EYE] > 0)
        if((int)ourHero->second_skill[HSS_EAGLE_EYE] < 3)
            return HSS_EAGLE_EYE;
       
        if((int)ourHero->second_skill[HSS_SCOUTING]] > 0)
        if((int)ourHero->second_skill[HSS_SCOUTING] < 3)
            return HSS_SCOUTING;
     
        if((int)ourHero->second_skill[HSS_FIRST_AID] > 0)
        if((int)ourHero->second_skill[HSS_FIRST_AID] < 3 && ourHero->DoesHasArtifact(AID_FIRST_AID_TENT) == false)
         if(armyAISum(ourHero) / second_skill[HSS_FIRST_AID] > 12500)
            return HSS_FIRST_AID;
       
        if((int)ourHero->second_skill[HSS_ARTILLERY] > 0)
        if((int)ourHero->second_skill[HSS_ARTILLERY] < 3 && ourHero->DoesHasArtifact(AID_BALLISTA) == false)
         if((double)armyAISum(ourHero) / pow((double)(second_skill[HSS_ARTILLERY] * attack), 0.8) > 3000.0)
            return HSS_ARTILLERY;
         
        if((int)ourHero->second_skill[HSS_PATHFINDING] > 0)
        if((int)ourHero->second_skill[HSS_PATHFINDING] < 3)
            return HSS_PATHFINDING;

        if((int)ourHero->second_skill[HSS_MYSTICISM] > 0)
        if((int)ourHero->second_skill[HSS_MYSTICISM] < 3)
            return HSS_MYSTICISM;
     
        if((int)ourHero->second_skill[HSS_FIRST_AID] > 0)
        if((int)ourHero->second_skill[HSS_FIRST_AID] < 3)
        if(armyAISum(ourHero) / second_skill[HSS_FIRST_AID] > 25000)
            return HSS_FIRST_AID;

        if((int)ourHero->second_skill[HSS_ARTILLERY] > 0)
        if((int)ourHero->second_skill[HSS_ARTILLERY] < 3)
        if((double)armyAISum(ourHero) / pow((double)(second_skill[HSS_ARTILLERY] * attack), 0.8) > 6000.0)
    }
   
    if(ourHero->level >= 30)
    {       
        if((int)ourHero->second_skill[HSS_EAGLE_EYE] >0)
            return HSS_EAGLE_EYE;
       
        if((int)ourHero->second_skill[HSS_SCOUTING] >0)
            return HSS_SCOUTING;
     
        if((int)ourHero->second_skill[HSS_FIRST_AID] > 0 && ourHero->DoesHasArtifact(AID_FIRST_AID_TENT) == false)
         if(armyAISum(ourHero) / second_skill[HSS_FIRST_AID] > 10000)
            return HSS_FIRST_AID;
       
        if((int)ourHero->second_skill[HSS_ARTILLERY] > 0 && ourHero->DoesHasArtifact(AID_BALLISTA) == false)
         if((double)armyAISum(ourHero) / pow((double)(second_skill[HSS_ARTILLERY] * attack), 0.8) > 2000.0)
            return HSS_ARTILLERY;
     
        if((int)ourHero->second_skill[HSS_PATHFINDING] >0
            return HSS_PATHFINDING;

        if((int)ourHero->second_skill[HSS_MYSTICISM] >0)
            return HSS_MYSTICISM;
     
        if((int)ourHero->second_skill[HSS_FIRST_AID] >0)
         if(armyAISum(ourHero) / second_skill[HSS_FIRST_AID] > 20000)
            return HSS_FIRST_AID;
       
        if((int)ourHero->second_skill[HSS_ARTILLERY] >0)
         if((double)armyAISum(ourHero) / pow((double)(second_skill[HSS_ARTILLERY] * attack), 0.8) > 4000.0)
            return HSS_ARTILLERY;
    }
         
    return 29;
}

...
// New game
_PI->WriteLoHook(0x4FDF90, setIsWaterMap);
// Load game
_PI->WriteLoHook(0x4BD91F, setIsWaterMap);

Вернуться к началу

offlineRoseKavalier  
Мастер
Мастер
 
Сообщения: 331
Зарегистрирован: 23 сен 2017, 17:00
Пол: Не указан
Поблагодарили: 234 раз.

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

Сообщение RoseKavalier » 06 ноя 2017, 02:08

I will look a bit tomorrow, not sure how busy this week will be.
Only thing I spotted at a glance is that Artillery should also take HotA cannon into consideration.

Weight function can be placed at 0x528546 like HotA's. I have not looked at AI weight functions much, except for teleporters :smile7:
Вернуться к началу

Пред.След.

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

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

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3