,

Хак на память Warcraft3

» опубликован
» Способ реализации: vJass
» Тип: Наработка
» Версия Warcraft: 1.26 и ниже
Собственно тот знаменитый хак на память который нам радостно предоставил DracoL1ch, который позволяет нам больше не морочится с системами отлова урона, или вовсе узнать координаты курсора без стороннего по.
Для сохранения требуется: экспериментальная версия pjass.exe
Причём не все подходят, меньше всего проблем было с этой версией
В хаке присутствует только 1 пример на изменение белой атаки у героя, остальные готовые функции можно найти на:
Хайве
Гитхабе
Просто копируем саму функцию, все остальное для её работы есть в наработке и сохраняем.
Так же на хайве есть инструкция по созданию собственных функций для чтения\изменения данных в памяти игры.


Просмотров: 48 970



» Лучшие комментарии


ClotPh #301 - 2 года назад 0
DracoL1ch, Clamp просто выше сказал, что может, как захочет.
quq_CCCP, можно.
ClotPh #303 - 2 года назад 0
Clamp, а десинк из-за нее будет? Если нет, то еще приемлемо...
quq_CCCP #304 - 2 года назад 0
ClotPh, разумеется будет если данные с кем то не синхронизируются, придется долго морщить лоб и писать 1005500 проверок, все ли игроки получили данные о координатах или нет?
Тем более никто не развивал набор функций для работы с мышью и прочим, пока авторы хака копают в другую сторону, вам остается либо ждать либо самостоятельно пилить функции с быстрой синхронизацией.
quq_CCCP #305 - 2 года назад (отредактировано ) 6
Новая функция для мемхака старой версии
» код
    function HideCooldownUIById takes unit whichUnit, integer id, boolean hide returns nothing
        local integer pAbility = GetUnitAbilityForAddresss( ConvertHandle( whichUnit ), id )
   
        if pAbility < 1 then
            return
        endif
    
        set pAbility = pAbility + 0x20
    
         if hide and not IsFlagBitSet( ReadRealMemory( pAbility ), 0x400 ) then
            call WriteRealMemory( pAbility, ReadRealMemory( pAbility ) + 0x400 )
        elseif not hide and IsFlagBitSet( ReadRealMemory( pAbility ), 0x400 ) then
            call WriteRealMemory( pAbility, ReadRealMemory( pAbility ) - 0x400 )
        endif

    endfunction
Собственно функция скрывает кулдаун указанной способности, скрывает только визуальный эффект кулдауна, сам кулдаун она не сбивает.
Так же есть проверка скрыт ли кулдаун индикатор у конкретной абилки:
    function IsCooldownUIHided takes integer pAbility returns boolean

        if pAbility < 1 then
            return false
        endif

        return IsFlagBitSet( ReadRealMemory( pAbility + 0x20 ), 0x400 )
    endfunction
Еще 1 функция, на этот раз можем узнать Id абилки которую может выучить герой
    function GetHeroAbilityFromList takes unit uHero, integer list returns integer
        set LastConvertedHandle = ConvertHandle( uHero )
    
        if IsUnitType( uHero, UNIT_TYPE_HERO ) and LastConvertedHandle > 1 and list > 0 then
            return RMem( RMem( LastConvertedHandle + 496 ) + 240 + 4 * list )
        endif

        return 0
    endfunction
Берет героя и номер абилки (см-рисунок)
Возвращает id абилки из списка доступных для изучения способностей, номер абилки это её порядковый номер в списке.
прикреплены файлы
ClotPh #306 - 2 года назад 0
О, насчет узнавания абилки шикарно. А для "старого" мемхака её можно?
Вот бы узнать абилку у юнита в неком слоте и переписать ее в некий слот другому юниту.
Просто шик был бы.
Omg дота же та же реализуется в 100 раз проще, чем все то, что там сейчас, что никак до конца не доходят раскурить мозги, втч потому, что чувствуется, что это дико нерационально.
Вообще раз адрес есть и оттуда можно читать, не вижу, почему бы туда нельзя было и записать =)
quq_CCCP #307 - 2 года назад 0
ClotPh, можно, нужно заменить RMem на ReadMemory.
Не помню я выкладывал функции кое каких эффектов от способностей?
ClotPh #308 - 2 года назад 0
quq_CCCP, и убрать умножение на 4?
UPD - а, нет, скорее все загнать в скобки и поделить на 4.
quq_CCCP #309 - 2 года назад 0
ClotPh, прям так должно заработать.
quq_CCCP #310 - 2 года назад (отредактировано ) 0
Исходники библиотеки DotaHelper
Мб кому то понадобится, лично меня интересуют дабл клики способностей
Ige #311 - 2 года назад 0
Вопрос по DotaHelper
Какие аргументы передавать в функцию?
int __stdcall RawImage_AddCallback(int RawImage, const char * MouseActionCallback, RawImageCallbackData * callbackdata, unsigned int events)
По остальным функциям есть какая-никакая документация, а тут я не возьму в толк, что передавать:(
quq_CCCP #312 - 2 года назад 0
Ige, увы сам Dracolich разработкой не занимается, вопросы только к автору на гитхабе...
Так и не понял где список id абилок для двойного клика
Ige #313 - 2 года назад (отредактировано ) 0
quq_CCCP, судя по всему, вот эта функция добавляет способность в список
int __stdcall AddDoubleClickSkillID( int skillID )

quq_CCCP, не знаешь, автор (Karaulov) появляется здесь?
quq_CCCP #314 - 2 года назад 0
Хз, даже...
Надо будет попробовать вырезать дабл клик да импортнуть себе в карту...
Ige #315 - 2 года назад (отредактировано ) 2
quq_CCCP, работает
» DotaHelper
library DotaHelper initializer onInit uses InjectDLL
{
    #define DOTA_HELPER_DLL = "DotAAllstarsHelper688j.dll"

    bool DOTA_HELPER_DLL_LOADED = false

    int InitDotaHelper(int hexGameVersion)
    {
        int nhandle1 = GetModuleProcAddress(DOTA_HELPER_DLL, "InitDotaHelper")

        if nhandle1 == 0 {
            BJDebugMsg("[" + `FUNCNAME` + "]: неверный адрес!")
            return -1
        }
        
        DOTA_HELPER_DLL_LOADED = true
        return std_call1(nhandle1, hexGameVersion)
    }

    private void onInit()
    {
        if (not ExportDllFromMpqAndInjectToWarcraft(DOTA_HELPER_DLL, DOTA_HELPER_DLL)) {
            BJDebugMsg("Failed to inject " + DOTA_HELPER_DLL)
            return
        }

        InitDotaHelper(GameVersion)
    }
}
» DoubleClickSkill
library DoubleClickSkill initializer onInit uses DotaHelper
{
    int pToggleClickHelper = 0
    int pAddDoubleClickSkillID = 0

    int ToggleClickHelper(bool enable)
    {
        if pToggleClickHelper == 0 {
            BJDebugMsg("[" + `FUNCNAME` + "]: неверный адрес!")
            return -1
        }

        return std_call1(pToggleClickHelper, B2I(enable))
    }

    int AddDoubleClickSkillID(int id)
    {
        if pAddDoubleClickSkillID == 0 {
            BJDebugMsg("[" + `FUNCNAME` + "]: неверный адрес!")
            return -1
        }

        return std_call1(pAddDoubleClickSkillID, id)
    }

    private void onInit()
    {
        pToggleClickHelper = GetModuleProcAddress(DOTA_HELPER_DLL, "ToggleClickHelper")
        pAddDoubleClickSkillID = GetModuleProcAddress(DOTA_HELPER_DLL,"AddDoubleClickSkillID")
    }
}

Пример
//добавляем способности в "список"
AddDoubleClickSkillID('A000')
AddDoubleClickSkillID('A001')

ToggleClickHelper(GetLocalPlayer() == Player(0)) // активируем двойной клик для игрока(0)
ClotPh #316 - 2 года назад (отредактировано ) 0
Так, срочно копошусь, пытаюсь переписать функции чтения и записи полей абил героев на "старый" мемхак
Есть где ошибки?

набросок



    function GetHeroAbilityFromList takes unit uHero, integer list returns integer
        set LastConvertedHandle = ConvertHandle( uHero )
    
        if IsUnitType( uHero, UNIT_TYPE_HERO ) and LastConvertedHandle > 1 and list > 0 then
            return ReadMemory[(LastConvertedHandle + 496 ) + 240 + 4 * list )/4]
        endif

        return 0
    endfunction

Это пока в блокноте пишу
/////////
Или там разные части отдельно на 4 делить? Ну ща проверю
Хотя какая разница-то по идее, лол
ТАК, вот, короче, что пока скомпилировалось, но что оно и откуда куда читать и писать будет и будет ли, один Господь знает:

//ПЕРЕЗАПИСЬ И ЧТЕНИЕ ПОЛЕЙ СПОСОБНОСТЕЙ
    function GetHeroAbilityFromList takes unit uHero, integer list returns integer
        local integer LastConvertedHandle = ConvertHandle( uHero )
    
        if IsUnitType( uHero, UNIT_TYPE_HERO ) and LastConvertedHandle > 1 and list > 0 then
            return Memory[((LastConvertedHandle + 496 ) + 240 + 4 * list )/4]
        endif

        return 0
    endfunction


    function SetHeroAbilityFromListToAbilityOtherHero takes unit uHero, integer list, integer abireadedfromlist returns nothing
        local integer LastConvertedHandle = ConvertHandle( uHero )
    
        if IsUnitType( uHero, UNIT_TYPE_HERO ) and IsUnitType( uHero, UNIT_TYPE_HERO ) and LastConvertedHandle > 1 and list > 0 then
            set Memory[((LastConvertedHandle + 496 ) + 240 + 4 * list )/4] = abireadedfromlist
        endif

    endfunction
//ПЕРЕЗАПИСЬ И ЧТЕНИЕ ПОЛЕЙ СПОСОБНОСТЕЙ - ЗАКРЫТО.
Ну и че это за ерь?... Ничего оно никуда не пишет, а если пишет, то хз что хз куда.
*************!!!!
А так благополучно фаталит...
ПЕРЕЗАПИСЬ И ЧТЕНИЕ ПОЛЕЙ СПОСОБНОСТЕЙ
function GetHeroAbilityFromList takes unit uHero, integer list returns integer
local integer LastConvertedHandle = ConvertHandle( uHero )

if IsUnitType( uHero, UNIT_TYPE_HERO ) and LastConvertedHandle > 1 and list > 0 then
return Memory[((LastConvertedHandle + 496 )/4 + (240 + 4 * list ))/4]
endif
return 0
endfunction
function SetHeroAbilityFromListToAbilityOtherHero takes unit uHero, integer list, integer abireadedfromlist returns nothing
local integer LastConvertedHandle = ConvertHandle( uHero )

if IsUnitType( uHero, UNIT_TYPE_HERO ) and IsUnitType( uHero, UNIT_TYPE_HERO ) and LastConvertedHandle > 1 and list > 0 then
set Memory[((LastConvertedHandle + 496 )/4 + (240 + 4 * list ))/4] = abireadedfromlist
endif
endfunction
ПЕРЕЗАПИСЬ И ЧТЕНИЕ ПОЛЕЙ СПОСОБНОСТЕЙ - ЗАКРЫТО.
//////////
ладно, ну ее к... матери, ща по-другому сделаю
ладно, действительно гребаное издевательство, чтоб еще когда-нибудь так морочиться
//////////
так, а если вот так
это еще если удастся этот гребаный новый мемхак затащить
ПЕРЕЗАПИСЬ И ЧТЕНИЕ ПОЛЕЙ СПОСОБНОСТЕЙ
function GetHeroAbilityFromList takes unit uHero, integer list returns integer
set LastConvertedHandle = ConvertHandle( uHero )

if IsUnitType( uHero, UNIT_TYPE_HERO ) and LastConvertedHandle > 1 and list > 0 then
return RMem( RMem( LastConvertedHandle + 496 ) + 240 + 4 * list )
endif
return 0
endfunction
function SetHeroAbilityFromList takes unit uHero, integer list, integer ability
set LastConvertedHandle = ConvertHandle( uHero )

if IsUnitType( uHero, UNIT_TYPE_HERO ) and LastConvertedHandle > 1 and list > 0 then
WMem( RMem( LastConvertedHandle + 496 ) + 240 + 4 * list ), ability)
endif

endfunction
ПЕРЕЗАПИСЬ И ЧТЕНИЕ ПОЛЕЙ СПОСОБНОСТЕЙ - ЗАКРЫТО.
quq_CCCP #317 - 2 года назад (отредактировано ) 0
Насколько помню, записть листа абилок была нестабильна, норм работает только чтение...
 function GetHeroAbilityFromList takes unit uHero, integer list returns integer
        set LastConvertedHandle = ConvertHandle( uHero )
    
        if IsUnitType( uHero, UNIT_TYPE_HERO ) and LastConvertedHandle > 1 and list > 0 then
            return ReadMemory( ReadMemory( LastConvertedHandle + 496 ) + 240 + 4 * list )
        endif

        return 0
    endfunction
LastConvertedHandle - адресс героя, 496 адрес абилки 'Aher' -герой, в её полях лежат способности для изучения, ну а 240 + каждые 4 байта это адреса абилок. т.е 244 это первая абилка в списке, 248 вторая и так далее....
ClotPh #318 - 2 года назад 0
quq_CCCP, так, жопа. Почему-то при попытке воспользоваться возникает фатал.
Задаю рандомной переменной, например
set i = GetHeroAbilityFromList(u6,1)
и сразу фатал еррор.
Пробовалось и через функцию под "старый" мемхак, и через новый (RMem и WMem вроде уже импортированы).
Кстати, когда u6 - НЕ герой, всё равно фатал, хотя по идее должен был бы быть ноль...
quq_CCCP #319 - 2 года назад 0
ClotPh, Еще можно проверить ReadRealMemory вместо ReadMemory
Ну а фатал при выборе негероя - навреное ConvertHandle Кривая... там больше и фаталить нечему...
ClotPh #320 - 2 года назад 0
quq_CCCP, так-так, а, конверты хэндла в мемхаках же разные, один для функций другого не подходит? Мб именно сейчас дело в этом...
Я пока для начала просто уже прочесть абилку пытаюсь и вывести результат на экран...
quq_CCCP #321 - 2 года назад 0
Еще одно но, адреса абилок в оригинале записываются как F8/FC/100/104
ClotPh #322 - 2 года назад 0
quq_CCCP, это мне не понятно
У меня там в какой-то момент вроде выводилось целочисленной в текст на экране что-то, но вместо равкода абилки какая-то хня из многих цифр, я хочу равкод выкопать
quq_CCCP #323 - 2 года назад 0
ClotPh, ро код и есть много цифр на экране
Чтобы был ро код как в редакторе - Id2String()
ClotPh #324 - 2 года назад 0
quq_CCCP, так, минутку, то есть равкод я не откопаю?
Ок, сейчас хоть цифры попробую снова... жопа =/
А, во, понятно, ок
DracoL1ch #325 - 2 года назад 0
Ни в коем случае не используйте записывание строки через мемхак
Речь о том, чтобы заменить ссылку на строку где-либо своей ссылкой
Хотя смысл и не теряется, но у сборщика мусора явно едет крыша, и без рестарта вк будут рандомно выпадать краши. Так что пока без обновлений строк где-либо вообще
ClotPh #326 - 2 года назад (отредактировано ) 0
DracoL1ch, ну песец, а на что я тогда трачу сегодняшний день =/
Может мне кто-нить тогда хоть посоветовать, как правдами и неправдами с мемхаком и без словить абилу и пропихнуть ее выучивание герою??? Мне нужно, чтобы он чужие абилы мог тырить и обязательно через выучивание, иначе будет ппц геморройная бд
просто у меня другие скиллы многие регают свои триггеры только через выучивание конкретно для выучившего
для оптимизации
т. е. если абилу просто дать, она ниче делать не будет
//////
так, тем временем у меня уже строка ловится и не фаталит (по "классическому" мемхаку уже, не люблю слово "старый", да, у меня там небольшая путаница с конвертхэндл функцией была, они ж для старого и нового мх разные, откат сделан).
1095263859
так, id2string все равно достает не понятно что, не равкод, а какие-то
\x00000041...
sic!!! Ну так или иначе прорыв.
ТАК. Ну вот для начала. Вот ДЕЙСТВУЮЩИЕ (!!!) функции для "классического" мемхака. Все-таки это какая-никакая, а победа ))) Равкод не отловить, но меняют абилу исправно.

function GetHeroAbilityFromList takes unit uHero, integer list returns integer
set LastConvertedHandle = ConvertHandle( uHero )
    
if IsUnitType( uHero, UNIT_TYPE_HERO ) and LastConvertedHandle > 1 and list > 0 then
return ReadMemory( ReadMemory( LastConvertedHandle + 496 ) + 240 + 4 * list )
endif

return 0
endfunction

function SetHeroAbilityFromList takes unit uHero, integer list, integer abi returns nothing
set LastConvertedHandle = ConvertHandle( uHero )
    
if IsUnitType( uHero, UNIT_TYPE_HERO ) and LastConvertedHandle > 1 and list > 0 then
 call WriteMemory( ReadMemory( LastConvertedHandle + 496 ) + 240 + 4 * list, abi )
endif

endfunction
//////////////
Теперь чо там про фаталы... Лично потестирую... Фаталы ведь ловились в "новом" мемхаке? Тупость, но может быть, это влияет?
А если я быстренько махну поле выучиваемых абил, сразу выучу одну и сразу обратно перепишу поле?
Ige #327 - 2 года назад 2
ClotPh:
quq_CCCP, так, минутку, то есть равкод я не откопаю?
Ок, сейчас хоть цифры попробую снова... жопа =/
если я тебя правильно понял, то тебе нужна библиотека Ascii
пример использования
local integer id = 'hfoo'
local string raw = A2S(id) // raw == "hfoo" (строка)
id = S2A(raw) // id == 'hfoo' (число)
DracoL1ch #328 - 2 года назад 2
ClotPh:
=~DracoL1ch, ну песец, а на что я тогда трачу сегодняшний день =/
я не вижу у тебя строк в указанном примере
ClotPh #329 - 2 года назад 0
Ige, спс.
Да в принципе нужно, но не очень, равкод я при выучивании могу поймать.
DracoL1ch, у меня с тобой десинхронизация какая-то
каких строк?
Мои функции выше безопасны?
Пока гоняю в тест-карте, проблем не обнаруживаю, поля исправно переписываются туда и обратно и абилы учатся
ОХ, лол. Хм. Ща Мегамен забрал чародейскую ауру ладдерного архимага, работает и бафф дает вроде нормальный, но почему-то визуально отображается как "доспехи веры". То ли это у меня импорт такой и уже забыто, то ли допереписывалось (это уже XX была геройская способность, которые были переписыванием полей одному герою впихнуты и все через выучивание). Но других побочных эффектов пока не видно.
Лол набор: выучены 4 все свои абилы (но там не отображаются пассивки, специально же расчет на то, что гер абилы тырит), от чародея крови астрал, огонь и феня и от архимага буран, дух воды и аура, вот аура уже даже благополучно на панель не влезла.
///////////
DracoL1ch, а, дошло!!! Т. е. ты говоришь не брать значения из строки при записи в поле?
Ок, не буду, прямо из одного поля в другое, да и не планировалось.
Diaboliko #330 - 2 года назад 0
Будет ли десинк при выделении юнита игроком триггерно по случаю наличия зажатой конкретной клавиши (отлавливаемой мемхаком)? Действие то синхронизируемое.
DracoL1ch #331 - 2 года назад 2
очевидно, что работало раньше, работает и сейчас, выделения синхронизируются автоматически, так что проблемы не будет
Андреич #332 - 2 года назад 0
в чём может быть проблема функции SetUnitBaseDamage...
создаю юнита сразу же устанавливаю случайный показатель к атаке..., но с определённым шансом я получаю фатал...
для теста создал простой триггер, который создаёт юнита каждые 0.1 секунды и изменяет ему атаку через эту ф-цию...
иногда вылетает фатал после 40 созданных юнитов, иногда после 150...
где я мог накосячить..?
прикреплены файлы
quq_CCCP #333 - 2 года назад 0
Андреич, юнита проверили?
Обязательно проверяйте входные аргументы.
Андреич #334 - 2 года назад (отредактировано ) 0
quq_CCCP:
Андреич, юнита проверили?
Обязательно проверяйте входные аргументы.
ну да... юнит как бы не может быть мертв... так как изменение урона идёт один раз сразу после его создания...
DracoL1ch #335 - 2 года назад 0
Ну так покажи код-то, чего стесняешься?
pro100master #336 - 2 года назад 0
DracoL1ch, Они боится делить свои красоту кода =)
Андреич #337 - 2 года назад 0
DracoL1ch:
Ну так покажи код-то, чего стесняешься?
собственно здесь можно посмотреть всё прямо в карте...
функция создающая юнита в процессе самой игры - spawnPlayerUnits() - находится в custom code...
отключённый "Безымянный триггер 001" - делал для теста... собственно тот триггер, что создаёт юнита каждые 0.1 сек...
где я допустил ошибку..?
на всякий выложу сюда...
» code...
void spawnPlayerUnits(){
    for(int i=0;i<12;i++){
        if(GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING and GetWidgetLife(PlayerUnit[i]) < 0.405){
            PlayerUnit[i]=CreateUnit(Player(i),RandomUnit[GetRandomInt(1,RandomUnitMax)],GetRandomReal((size-1)*​-128,(size-1)*128.),GetRandomReal((size-1)*-128,(size-1)*128.),270.)
            PanCameraToForPlayer(Player(i),GetUnitX(PlayerUnit[i]),GetUnitY(PlayerUnit[i]))
            SetUnitScale(PlayerUnit[i],GetRandomReal(0.8,1.5),GetRandomReal(0.8,1.5),GetRandomReal(0.8,1.5))
            UnitAddAbility(PlayerUnit[i],'Asph')
            SetUnitColor(PlayerUnit[i],GetPlayerColor(Player(i)))
            SetUnitMoveSpeed(PlayerUnit[i],GetRandomReal(250.,300.))
            addBonus(PlayerUnit[i])
            UnitAddAbility(PlayerUnit[i],'AInv')
            SetUnitAbilityLevel(PlayerUnit[i],'AInv',GetRandomInt(1,7))
            //add attack
            SetUnitBaseDamage(PlayerUnit[i],GetRandomInt(0,100))
            //add armor
            real armorBonus=GetRandomReal(0.,5.)
            SetUnitArmor(PlayerUnit[i],armorBonus)
            
            //
            if(GetRandomReal(1.,100.)>10.){
                    SetUnitMaxMP(PlayerUnit[i],1.)
            }
            local real hpbonus = GetRandomReal(100.,1000.)
            SetUnitMaxHP(PlayerUnit[i],hpbonus)
            SetUnitState(PlayerUnit[i], UNIT_STATE_LIFE,hpbonus)
            SetUnitState(PlayerUnit[i], UNIT_STATE_MANA,3.)
            SelectUnitForPlayerSingle(PlayerUnit[i], Player(i))
        }
    }
}
» тестовый триггер
int count=0
void Ta(){
timer t = GetExpiredTimer()
int tid = GetHandleId(t)
bj_lastCreatedUnit = LoadUnitHandle(gg_htb_HashData,tid,1)
SetUnitBaseDamage(bj_lastCreatedUnit,1)
DestroyTimer(t)
FlushChildHashtable(gg_htb_HashData,tid)
t=null
}
function Trig_____________________________________001_Actions takes nothing returns nothing
bj_lastCreatedUnit=CreateUnit(Player(1),RandomUnit[GetRandomInt(1,RandomUnitMax)],GetRandomReal((siz​e-1)*-128,(size-1)*128.),GetRandomReal((size-1)*-128,(size-1)*128.),270.)
SetUnitBaseDamage(bj_lastCreatedUnit,0)

timer t=CreateTimer()
int tid = GetHandleId(t)

SetUnitArmor(bj_lastCreatedUnit,0.)
count++
BJDebugMsg(I2S(count))
SaveUnitHandle(gg_htb_HashData,tid,1,bj_lastCreatedUnit)
TimerStart(t,0.01,false,function Ta)
t=null
endfunction
===========================================================================
function InitTrig_____________________________________001 takes nothing returns nothing
set gg_trg_____________________________________001 = CreateTrigger( )
TriggerRegisterTimerEvent(gg_trg_____________________________________001,0.1,true)
call TriggerRegisterPlayerEventEndCinematic( gg_trg_____________________________________001, Player(0) )
call TriggerAddAction( gg_trg_____________________________________001, function Trig_____________________________________001_Actions )
endfunction
Diaboliko #338 - 2 года назад 0
Тут и смещение камеры для ботов и изменение статов мемхаком. Не знаю насколько стабильно работает первое, но второе следовало бы тестировать по отдельности. Поставь период таймера равный нулю и ограничь его использование тысячей раз в секунду, например. Такой стресс-тест покажет больше, имхо
ClotPh #339 - 2 года назад (отредактировано ) 0
*удалено, прошу извинить за невнимательность, тестовый триггер, ок
Андреич #340 - 2 года назад 0
Diaboliko:
Тут и смещение камеры для ботов и изменение статов мемхаком. Не знаю насколько стабильно работает первое, но второе следовало бы тестировать по отдельности. Поставь период таймера равный нулю и ограничь его использование тысячей раз в секунду, например. Такой стресс-тест покажет больше, имхо
до мемхака пользовался костылём через руну, повышающую белую атаку...
и как бы работало всё без фаталов...
со стресс тестом попробую...

потестил... в функцией изменения атаки вылетает сразу... потостил этот же цикл с функцией изменения брони... всё работает...
» test...
...
for(count=0;count<1000;count++){
                BJDebugMsg(I2S(count))
                bj_lastCreatedUnit=CreateUnit(Player(1),RandomUnit[GetRandomInt(1,RandomUnitMax)],GetRandomReal((siz​e-1)*-128,(size-1)*128.),GetRandomReal((size-1)*-128,(size-1)*128.),270.)
                //SetUnitBaseDamage(bj_lastCreatedUnit,0)
                SetUnitArmor(bj_lastCreatedUnit,0.)
            }
ScorpioT1000 #341 - 2 года назад 0
Я бы порекомендовал выделить все магические числа, вычисления и адреса в константы/отдельные функции - так проще вносить правки и дебажить операции. А все SetHeroAbilityFromList и проверки входных данных можно оставить на более высоком слое абстракции.
Андреич #342 - 2 года назад 0
всё ребята вопрос снят... извините за беспокойство...
у меня на карте просто мемхак спаян с RenderEdge_mini... видимо, где-то там ошибку допустил...
сейчас проверил на карте с одним только мемхаком, всё нормально работает...
ClotPh #343 - 2 года назад 0
Сорри за небольшой оффтоп, но переписывание и выучивание чужих абилок жёстко )
Там ща такие открытия ингейм, что ппц )
Например, если clawbfs.ucoz.ru/forum/3-1833-1 сворует у clawbfs.ucoz.ru/forum/3-216-1 способность clawbfs.ucoz.ru/Icons/TarPit/TarPit2.bmp (там станд морф друида ворона) и активирует, получится Смоляной Мегамен :D .
Он не сможет анморфнуться обратно, у него отрубается его активка, он навсегда теряет способность атаковать, чернеет и становится огненным, но при этом сохраняется нормальная скорость перемещения и свои пассивки + добавляется аура Смоляной Ямы в растечённом состоянии. Мутант, короче. В итоге вряд ли профитно (атаки ничто не заменит), но интересно :D
Чую, там еще немало открытий будет. Вообще там на многие морфы чужих абил изначально был фильтр поставлен, что нельзя, но не на все.
Ну это вообще морфы по принципу друида-медведя и друида-ворона так косят чужие. По-моему, морф типа метаморфозы иллидана должен норм работать, во всяком случае, в них у меня для аватаров - т. е. не совсем "своих" героев - исходная форма не переделывалась в большинстве случаев, а морф и анморф все равно проходил исправно.
А вообще это ржач все равно, Мегамен кидает крюк, Мегамен пускает волну пламени Рагнароса, Мегамен саммонит и собирает пчёл, Мегамен пускает ножницы Рюко Матой, где еще такого Мегамена встретишь )))
ClotPh #344 - 2 года назад 0
///////////////
//////////////
  1. Есть функция для поля уровня геройской способности, требуемого для ее изучения? (Ну там ульты требуют в доте обычно 6 уровня и обычные спеллы 1). Интересно читать и писать в это поле
  1. Напомните, кулдаун глобально я давно меняю заклинаниям, а есть возможность локально поменять действующий кулдаун только конкретному заклинанию конкретного героя? Не запустить, запустить-то понятно, что можно любой кулдаун, а именно чтобы вот у этого героя у фаерболла была перезарядка 2, а у всех остальных 8. (Прим. - ещё идея - это могло бы быть использовано как счётчик для чего-нибудь с любой скрытой спеллбучной 1уровневой способностью)
quq_CCCP #345 - 2 года назад 0
ClotPh, можно, но это несколько не очень, клонировать данные спелла и изменять, помню в начале ты жаловался что оно фаталило через раз.
Сделай лучше нулевой кулдаун, а стартом кулдауна делай нужный тебе кд. А так есть функции редактирования кулдауна, уже не помню фиксились ли их проблемы или нет.
DracoL1ch #346 - 2 года назад 4
function GetAbilityLevelRequired takes integer abil returns integer
	local integer a
	if abil!=0 then
		set a=GetAbilityDataDefByIdCaching(abil)
		if a>0 then
			return RMem(a+0x40)
		endif
	endif
	return 0
endfunction
ClotPh #347 - 2 года назад 0
quq_CCCP, да мне там не только для этого
я просто все думаю, есть ли возможность на юнита легко повесить счетчик без использования custom value, глобальных переменных и редактирования параметров объекта
просто мог бы быть у него некий спелл с перезарядкой вообще в спрятанном спеллбуке, перезарядка меняться и от нее считаться что-то другое
DracoL1ch, ага, спасибо
ClotPh #348 - 2 года назад 0
По поводу xgm.guru/p/wc3/196821
Есть по чтению и записи в строчки, редактирующие тип оружия у первой и второй атаки?
pro100master #349 - 2 года назад 0
Обязятельно ли мемхак инизиализировать после 1 сек ??? или можно сразу инизиализация???
quq_CCCP #350 - 2 года назад 0
pro100master, по вашему желанию, просто нужно смотреть что к чему, там вроде юзаются бж переменные, нужно чтобы инит прошел после них, а не в самом майне, да и это защита от оптимизаторов, ибо если инитить как библиотеку, они вынесут все из инит функций в майн, могут быть проблемы с обрывом потока.