| feanor   
 Posts: 624
 
 | 
			| 
 
				Quote:Вообще польза от использования патчера в этом конкретном случае достаточно сомнительна. 
Чтоб не на ассемблере писать, тащемта
			 |  | 
	| 11.03.2015 16:00 |  | 
	
		| major   
 Posts: 147
 
 | 
			| 
 
				Вроде бы немного разобрался, спасибо.
			 
				
(This post was last modified: 15.03.2015 19:12 by major.)
 |  | 
	| 13.03.2015 21:30 |  | 
	
		| major   
 Posts: 147
 
 | 
			| 
 
				Немного переделал регенерацию. 
Code:
 // dllmain.cpp: определяет точку входа для приложения DLL.#include "stdafx.h"
 
 #include "..\..\include\patcher_x86_commented.hpp"
 #include "..\..\include\HotA\HoMM3.h"
 #include "..\..\include\era.h"
 
 Patcher * globalPatcher;
 PatcherInstance *patcher;
 
 int __stdcall RegenerationCheck (LoHook* h, HookContext* c)
 {
 if (((_BattleStack_*)c->esi)->count_current < ((_BattleStack_*)c->esi)->count_at_start)
 {
 c->return_address = 0x446BD3;
 }
 else
 {
 if (((_BattleStack_*)c->esi)->lost_hp > 0)
 {
 c->return_address = 0x446BD3;
 }
 else
 {
 c->return_address = 0x446DF1;
 }
 }
 return NO_EXEC_DEFAULT;
 }
 
 int __stdcall RegenerationFull (LoHook* h, HookContext* c)
 {
 int regen = *(int*)0x2846BC8;
 int number = ((_BattleStack_*)c->esi)->count_current;
 int bnumber = ((_BattleStack_*)c->esi)->count_at_start;
 int lowhp = ((_BattleStack_*)c->esi)->lost_hp;
 int hp = ((_BattleStack_*)c->esi)->full_hp;
 if (regen <= lowhp)
 {
 lowhp -= regen;
 ((_BattleStack_*)c->esi)->lost_hp = lowhp;
 }
 else
 {
 regen -= lowhp;
 int count = 1;
 while (regen > hp)
 {
 regen -= hp;
 count += 1;
 }
 number += count;
 if (number > bnumber)
 {
 number = bnumber;
 lowhp = 0;
 }
 else
 {
 lowhp = hp - regen;
 }
 ((_BattleStack_*)c->esi)->lost_hp = lowhp;
 ((_BattleStack_*)c->esi)->count_current = number;
 }
 
 c->return_address = 0x446C3F;
 return NO_EXEC_DEFAULT;
 }
 
 int __stdcall Regeneration (LoHook* h, HookContext* c)
 {
 int unit = c->eax;
 int regenhp = 0;
 if (unit == 4 || unit == 46 || unit == 47 || unit == 61)
 {
 regenhp += 40;
 }
 if (unit == 5)
 {
 regenhp += 50;
 }
 if (unit == 60)
 {
 regenhp += 30;
 }
 if (unit == 80 || unit == 81 || unit == 144)
 {
 regenhp += 80;
 }
 if (unit == 110 || unit == 193)
 {
 regenhp += 100;
 }
 if (unit == 111 || unit == 168)
 {
 regenhp += 150;
 }
 if (unit == 157)
 {
 regenhp += 200;
 }
 //    if (unit == 159)
 //    {
 //        regenhp += 40;
 //    }
 if (regenhp > 0)
 {
 *(int*)0x2846BC8 = regenhp;
 c->return_address = 0x75DF2A;
 }
 else
 {
 c->return_address = 0x75DE8E;
 }
 return NO_EXEC_DEFAULT;
 }
 
 void __stdcall PatchIt (PEvent e)
 {
 patcher->WriteLoHook(0x75DE66,(void*)Regeneration);
 patcher->WriteLoHook(0x446BCD,(void*)RegenerationCheck);
 patcher->WriteLoHook(0x446C2B,(void*)RegenerationFull);
 }
 
 BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
 {
 if (ul_reason_for_call == DLL_PROCESS_ATTACH)
 {
 globalPatcher = GetPatcher();
 patcher =  globalPatcher->CreateInstance("abilities");
 ConnectEra();
 RegisterHandler(PatchIt,"OnAfterCreateWindow");
 }
 return TRUE;
 }
 
Подскажите по двум вопросам. 
1. Как добавить проверку на эликсир жизни, чтоб он добавлял еще 50 хп к регену. 
2. Регенерация от опыта существ работает как-то по-другому? Этот хук не срабатывает, реген проходит без воскрешения. Как это можно исправить?
			 |  | 
	| 15.03.2015 19:16 |  | 
	
		| feanor   
 Posts: 624
 
 | 
			| 
 
				Quote:1. Как добавить проверку на эликсир жизни, чтоб он добавлял еще 50 хп к регену. 
o_BattleMgr->hero[((_BattleStack_*)c->esi)->side]->DoesWearArtifact(ID), как-то так
			 |  | 
	| 15.03.2015 19:30 |  | 
	
		| gamecreator   
   Posts: 7107
 
 | 
			| 
 
				1. Что-то типа (с указанием героя, конечно) 
Code:
 Era::ExecErmCmd("HE:A2/131/?v1/?v1;");if (Era::v[1]>0) ...
 
2. Выдержка из исходников Вога:
 
Code:
 void IsTroll(void){
 __asm{
 mov    IT_Mon,esi
 mov    edx,50 // умолчательное восстановление здоровья
 mov    IT_Edx,edx
 cmp    eax,0x3C
 je     l_Ok
 cmp    eax,0x3D
 je     l_Ok
 cmp    eax,0x90
 je     l_Ok
 cmp    eax,157 // гидра
 je     l_Ok_check
 //    jmp   l_Exit
 pusha
 }
 __asm mov IDummy,eax
 #include "templ.h"
 IT_Ret=CanNPCRegenerate(IDummy,IT_Mon);
 if(IT_Ret!=-1){
 IT_Ret=CrExpBon::Regenerate(IT_Mon,*(int *)&IT_Mon[0x58]);
 if(IT_Ret==0){ // no reg
 IT_Ret=0;
 }else{ // yes
 IT_Edx=IT_Ret;
 IT_Ret=-1;
 }
 }
 STOP
 __asm{
 popa
 mov    eax,IT_Ret
 //    je    _Ok_check
 jmp    l_Exit
 }
 l_Ok_check:
 CalcRand100();
 __asm{
 cmp    eax,40  // 40%
 ja     l_Exit
 }
 l_Ok:
 __asm mov    eax,-1
 l_Exit:
 __asm mov    edx,IT_Edx
 }
 
Это та функция, что перезаписывается по 0x446BD6. 
CrExpBon::Regenerate - это стандартная регенерация от опыта.
			
 When all gods have burnt to ashes in eternity of sorrow,
 Demons gonna tear your soul because there is no tomorrow.
 |  | 
	| 15.03.2015 20:15 |  | 
	
		| feanor   
 Posts: 624
 
 | 
			| 
 
				Как можно перебрать все объекты определенного типа/подтипа кодом?ну, то бишь, как это делает Вог в UN:U?)
 
 ..эм
 пробегать всю карту каждый раз? серьезно?
 
				
(This post was last modified: 17.03.2015 03:45 by feanor.)
 |  | 
	| 17.03.2015 03:41 |  | 
	
		| Дьякон   
 Posts: 395
 
 | 
			| 
 
				feanor, думаю серьезно.  ------------------------------------------------------------------
 63E9B8 - % для навыков некромантии/чародейства (массив из 4 dword)
 476DA0 - воскрешение нечести после боя
 4E3F40 - расчет % чародейства(некромантии) с учетом артефактов и специальностей
 
 Страус труп (с) Бьерн
 |  | 
	| 17.03.2015 12:56 |  | 
	
		| gamecreator   
   Posts: 7107
 
 |  | 
	| 17.03.2015 13:36 |  | 
	
		| Дьякон   
 Posts: 395
 
 | 
			| 
 
				Через UN:C забиваешь для всех уровней некромантии 0, соответственно воскрешаться никто не будет. 
Хотя не, нужно еще артефакты все отключать, т.к. там абсолютное приращение идет к %. Если нужно, то найду и выложу все адреса по некромантии.
			
 Страус труп (с) Бьерн
 
				
(This post was last modified: 17.03.2015 17:13 by Дьякон.)
 |  | 
	| 17.03.2015 17:06 |  | 
	
		| Дьякон   
 Posts: 395
 
 | 
			| 
 
				
Code:
 0x63EAE4 - амулет гробовщика 5%0x63B8D0 - мантия и усилители 10%
 0x63EB28 - сапоги 15%
 0x63B8B4 - грааль 20%
 0x63EB24 - плащ 30%
 
Все обнулить и по идее будет счастье 
Хотя можно сделать еще проще. Задать максимальный % воскресших 0%, который сейчас 100%. Но возможно с ним могут быть проблемы, т.к. данная константа может использоваться и в других расчетах, например как 0x63B8D0 одновременно отвечает и за мантию и за усилители.
			 
 Страус труп (с) Бьерн
 
				
(This post was last modified: 17.03.2015 17:23 by Дьякон.)
 |  | 
	| 17.03.2015 17:20 |  | 
	
		| Дьякон   
 Posts: 395
 
 | 
			| 
 
				Вот так будет (должно) работать и не нужно трогать константы: 
И да константы универсальные и их правка не рекомендуется.
			
 Страус труп (с) Бьерн
 
				
(This post was last modified: 17.03.2015 21:05 by Дьякон.)
 |  | 
	| 17.03.2015 17:40 |  | 
	
		| Дьякон   
 Posts: 395
 
 | 
			| 
 
				4A7530 - jmp определяющий вступят в бой или другие условия присоединиться. Отключение jmp - отключает дипломатию,т.е.
 Страус труп (с) Бьерн
 |  | 
	| 19.03.2015 15:16 |  |