Собственно небольшая библиотека требующая немного модифицированный мемхак второй версии (прилагается в тест карте), ну и немного терпения, которая добавить возможность проверять тип урона, атаки, типа атаки, флагов атаки, начального урона без резистов во всех триггерах вашей карты срабатывающих на событие EVENT_UNIT_DAMAGED.
Так же в этой версии включена система восстановления памяти при выходе из игры, фаталить не будет.
А так же добавлена система отображения зарядов на иконке.
Код библиотеки
include "cj_types_priv.j"

library MHDamage /*initializer init*/ requires Memory, Utils

define
{
    PAGE_EXECUTE           = 0x10
    PAGE_EXECUTE_READ      = 0x20
    PAGE_EXECUTE_READWRITE = 0x40
    PAGE_EXECUTE_WRITECOPY = 0x80
    PAGE_NOACCESS          = 0x01
    PAGE_READONLY          = 0x02
    PAGE_READWRITE         = 0x04
    PAGE_WRITECOPY         = 0x08
    PAGE_TARGETS_INVALID   = 0x40000000
    PAGE_TARGETS_NO_UPDATE = 0x40000000
    PAGE_GUARD             = 0x100
    PAGE_NOCACHE           = 0x200
    PAGE_WRITECOMBINE      = 0x400
}

define pointer = int
define sizeof_pointer_ = $04
define NULL = 0

define 
{
    KB = 1024
    MB = KB * 1024
}

// Максимальное количество одновременных событий урона.
private constant int MAX_DAMAGE_STACK_SIZE = 1024

private pointer pDamageStack = NULL
private pointer pDamageHook = NULL

pointer GetDamageEventData()
{
	int Length = RMem(pDamageStack)
	
	if (Length > 0)
	{
		return RMem(pDamageStack + $04 + sizeof_pointer_ * (Length - 1))
	}
	
	return NULL
}

public void init()
{
    pDamageStack = malloc($04 + $04 * MAX_DAMAGE_STACK_SIZE)
    pDamageHook = AllocateExecutableMemory(1 * KB)
    
    // hook
    
    pointer CUnit_VMT = GameDLL + $931934
    pointer pSlot72 = CUnit_VMT + (sizeof_pointer_ * 72)
    
    int OldProtection = ChangeOffsetProtection(pSlot72, 4, PAGE_READWRITE)
    
    pointer PreviousMethod = RMem(pSlot72)
    WMem(pSlot72, pDamageHook)
    
    ChangeOffsetProtection(pSlot72, 4, OldProtection)
    
    // init code
    
    //WMem(pDamageHook + $00, $8DE58955)
    //WMem(pDamageHook + $04, $53F82464)
    //WMem(pDamageHook + $08, $B8F84D89)
    //WMem(pDamageHook + $0C, pDamageStack)
    //WMem(pDamageHook + $10, $89044D8D)
    //WMem(pDamageHook + $14, $89138BC3)
    //WMem(pDamageHook + $18, $8304904C)
    //WMem(pDamageHook + $1C, $4D8B0103)
    //WMem(pDamageHook + $20, $1475FFF8)
    //WMem(pDamageHook + $24, $8B1075FF)
    //WMem(pDamageHook + $28, $8B500C45)
    //WMem(pDamageHook + $2C, $B8500845)
    //WMem(pDamageHook + $30, PreviousMethod)
    //WMem(pDamageHook + $34, $4589D0FF)
    //WMem(pDamageHook + $38, $012B83FC)
    //WMem(pDamageHook + $3C, $5BFC458B)
    //WMem(pDamageHook + $40, $0010C2C9)
    
    WMem(pDamageHook + $00, $8DE58955)
    WMem(pDamageHook + $04, $53E82464)
    WMem(pDamageHook + $08, $B8F84D89)
    WMem(pDamageHook + $0C, pDamageStack)
    WMem(pDamageHook + $10, $890C558B)
    WMem(pDamageHook + $14, $558BE855)
    WMem(pDamageHook + $18, $10528B0C)
    WMem(pDamageHook + $1C, $8BEC5589)
    WMem(pDamageHook + $20, $55891055)
    WMem(pDamageHook + $24, $14558BF0)
    WMem(pDamageHook + $28, $8DF45589)
    WMem(pDamageHook + $2C, $C389E84D)
    WMem(pDamageHook + $30, $4C89138B)
    WMem(pDamageHook + $34, $03830490)
    WMem(pDamageHook + $38, $4D8B9001)
    WMem(pDamageHook + $3C, $1475FFF8)
    WMem(pDamageHook + $40, $8B1075FF)
    WMem(pDamageHook + $44, $8B500C45)
    WMem(pDamageHook + $48, $B8500845)
    WMem(pDamageHook + $4C, PreviousMethod)
    WMem(pDamageHook + $50, $4589D0FF)
    WMem(pDamageHook + $54, $012B83FC)
    WMem(pDamageHook + $58, $5BFC458B)
    WMem(pDamageHook + $5C, $0010C2C9)
}

endlibrary
Как видим библиотака с несколькими функциями, после её запуска можно будет делать так:
function Trig_Damage_Test_Conditions takes nothing returns boolean
    return GetEventDamage() > 0.00
endfunction

function Trig_Damage_Test_Actions takes nothing returns nothing
    local integer EventData = GetDamageEventESPData()
    local integer Data = RMem(EventData + $00)
    local real InitialAmount = mI2R( RMem(EventData + $04) )
    local integer UnkBool = RMem(EventData + $08)
    local integer Flags = RMem(Data + 0x0C ) 
    local real Amount = mI2R( RMem(Data + $10) )
    local integer WeaponType = RMem(Data + $04)
    local integer DamageType = RMem(Data + $14)
    local integer AttackType = RMem(Data + $20)
    
    call BJDebugMsg("*** Damage info ***")
    call BJDebugMsg("Target: " + GetUnitName(GetTriggerUnit()))
    call BJDebugMsg("Source: " + GetUnitName(GetEventDamageSource()))
    call BJDebugMsg("Amount: " + R2S(Amount))
    call BJDebugMsg("Initial Amount: " + R2S(InitialAmount))
    call BJDebugMsg("Weapon Type: " + I2S(WeaponType))
    call BJDebugMsg("Damage Type: " + I2S(DamageType))
    call BJDebugMsg("Attack Type: " + I2S(AttackType))
    call BJDebugMsg("Flags - " + I2S(Flags) )
    call BJDebugMsg("Bool - " + I2S(UnkBool)  )
    
    if IsFlagBitSet(Flags, 0x100) then
        call BJDebugMsg("урон от атаки ближнего боя")
    endif
endfunction

//===========================================================================
function InitTrig_Damage_Test takes nothing returns nothing
    set gg_trg_Damage_Test = CreateTrigger(  )
    call TriggerAddCondition( gg_trg_Damage_Test, Condition( function Trig_Damage_Test_Conditions ) )
    call TriggerAddAction( gg_trg_Damage_Test, function Trig_Damage_Test_Actions )
endfunction
Рассмотрим по подробнее:
    local integer ESP = GetDamageEventESPData()
    local integer Data = RMem(ESP + $08) // second argument
Это получения структуры в которой хранятся все данные об уроне на это событие урона.
 local real Amount = mI2R( RMem(Data + $10) )
Урон без учета резиста, все просто...
local integer WeaponType = RMem(Data + $04)
Это тип оружия, это вот тут используется:
native UnitDamageTarget takes unit whichUnit, widget target, real amount, boolean attack, boolean ranged, attacktype attackType, damagetype damageType, !!weapontype weaponType!! returns boolean 
Вот их столько:
Обратите внимание, weapontype в данном случаи получается в виде целочисленной переменной, их соотсветсвие можно глянуть в common.j или использовать ConverWeaponType
Идем далее:
local integer DamageType = RMem(Data + $14)
В данном случаи тип урона тоже представлен в виде целочисленной переменной, для преобразование в хендл damagetype модно юзать данный код:
D2DT
function DT2DT takes integer k returns integer
    local integer i = 1
    if k == 0 then
        return 0
    endif
    loop
        exitwhen k / 2 <= 1
        set i = i + 1
        set k = k / 2
    endloop
    return i
endfunction

	//пример использования:
	ConvertDamageType(DT2DT(dmgTypeHex))==DAMAGE_TYPE_FIRE
local integer AttackType = RMem(Data + $20)
Это тип атаки юнита, причем тоже не хендл а целое чило, но тут все просто:
7 видов атаки, от 0 до 6, числовые значения можно превратить в хендлы с помощью нативки:
	constant native ConvertAttackType takes integer i returns attacktype
Ну и наконец флаги атаки:
 local integer Flags = RMem( Data + 0x0C )
Это целое число, а точнее сразу несколько слепленных в кучу, где каждое является флагом который что то означает, если Flags == 0x100 то это урон от атаки ближнего боя, 0х101 урон от атаки дальнего боя, многие способности ставят свои флаги на атаку, к примеру Стремительность ('AOwk' - windwalk ) - ставит флаг 0x500.
Ссылка на тестмап тут

Отображение зарядов

Вы когда-нибудь видели способности 'Afla' (Осветительная ракета) и 'Asen' (Сторожевая сова)? Вспомните эти красивые циферки с кол-вом зарядов на иконке, но увы таких способностей всего 2 на весь варкравт, но спс DracoL1ch, теперь мы можем рисовать заряды на иконке практически любой способности, в тестовой карте у мастера клинка при изучении способности "Стремительность" на иконке видны заряды, равные уровню способности, они конечно не тратятся сами как у "Ракет" и "Сов" но с помощью кода мы можем задавать способности любое кол-во зарядов а так же включать и отключать отображение зарядов на иконке.
Функционал довольно прост:
    function InitChargesHook takes unit u, integer id returns nothing // вешает хук на отображение зарядов для указанной способности.
    function InitCharges takes unit u, integer id returns nothing //активирует отображение зарядов на этом id на этом юните
    function RemoveCharges takes unit u, integer id returns nothing  //отключает отображение зярядов
    function SetCharges takes unit u, integer id, integer charges returns nothing //записывает юниту в абилку кол-во зарядов
    function GetCharges takes unit u, integer id returns integer //показывает  кол - во зарядов
Есть вопросы? Задавайте.
В карте примере код на vjass
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
21
должно возвращать урон без учета резистов
Да, но возвращает урон после учёта всех резистов. Можно как-то исправить:?
32
ScopteRectuS, нужно спрашивать IseFog, он автор идеи этого хака, мб ошибся в реализации, были ошибки и до этого, но вроде поправили все, а оказалось нет.
Изменить урон до нанесения в триггере срабатывающем на урон нельзя, только внутри класса вижетов с помощью внедрения своего асм кода.
ScopteRectuS, ну как успехи?
33
Заценил досрочно, но вот по восстановлению памяти вопросы, оно автоматически не работает? Я не понял как использовать восстановление памяти к событию выхода из игры приписать его? нужно восстанавливать только только то что было изменено?
Не совсем понятно, я новый ещё не использовал, но скажу что на стартом карта фаталила почти сразу, если не перезапустит вар.
Просто у меня бездумное применение, я не в состоянии особо вникнуть в работу каждой строчки
32
Там все уже сделано, в карте все настроено в папке с мемхаком, берите и юзайте, копируя целиком.
27
quq_CCCP, а бонусы зеленые на атаку работают? спрашивали недавно
32
Steal nerves, я этим не занимался, я только сделал новый хук на восстановление памяти, новый детект урона - дмг изначальный ловит как надо, и заряды на иконки, теперь визуальнов мх все оформлено, каждая система в отдельном "триггере" чтобы было удобнее, а так же чтобы можно было удалить то что вам не надо.
21
В связи со скорым выходом WC3 Reforged третей версии мемхака, наверное, уже не будет, да?
32
PT153, что именно? Детект урона или какие отдельные фишки этой системы?
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.