• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Accessing memory from the script - it's time of the revolution

Status
Not open for further replies.
It doesn't need to be running, OllyDbg has the option to open a dll file directly for analysis, so you don't need to run wc3 at all, you can open game.dll directly with OllyDbg and see everything.

But it's possible to use it with the game running too! You can launch WC3 directly from OllyDbg, or launch it from WE and attach the debugger to it. But keep in mind that the game must ALWAYS be running in window mode if you're going to do that. If you're using NewGen it's better, as it can already launch WC3 in window mode.

If you forget to run in window mode, and the game gets paused by the debugger, you'll be unable to ALT-TAB out of the game screen, and you'll be forced to restart your computer! So don't make that mistake.

Okay, thanks for that! :)

Also, what do you mean by "index of natives"? I didn't understand.

When you're calling the natives, how did you know which numbers correspond to them? (Like 623 for GetPlayers...)
 
Level 9
Joined
Jul 30, 2012
Messages
156
When you're calling the natives, how did you know which numbers correspond to them? (Like 623 for GetPlayers...)

Those ids come from the string table. Aniki had dumped the string table (see JASM - Let's dive into bytecode) so you can use those ids when referencing anything from common.j or blizzard.j. For stuff in the main map script, you need to manually obtain the id (via memory reading).
 
Level 9
Joined
Jul 30, 2012
Messages
156
New version of libraries have been released. Mouse functions are back and working in all versions, ObjectData library can now get AbilityData too (don't forget to use GetObjectName if the ability has not been loaded by the game yet).

Development of automatic detection engine has been finished. I've rushed it in the last few days since I'm gonna be absent for some time (I'm getting married). So the progress is probably gonna be slower now. But the code has already reached a stable version, so feel free to use it in production environment, I've tested it under all versions up to 1.28.5 and it worked flawlessly.

However I am unable to test it under Mac. I wrote the detection code for Mac environment by looking at the mac executables from patches 1.26, 1.27a and 1.27b. But I never got the chance to actually run the code, so I don't know if it's working or if I made any mistakes there. I'd be happy if Mac users could test it for me (@Bribe, @PurgeandFire?).
 
  • Like
Reactions: pyf
Level 18
Joined
Nov 21, 2012
Messages
835
hey, thanks for great update,
Your ObjectData requires this library by Bribe: [Snippet] New Table ?

ps All the best for you and your family ;)

@MyPad
GetUnitBaseDamage, GetUnitAttackSpeed crashes the game when used on unit Fountain od Power (no attacks enabled, attack speed=0.00, base damage=0.00)

moreover GetUnitAttackSpeed(u) returns wrong values for footman/knight for example
 
Last edited:

Yeah, I observed that GetUnitAttackSpeed function will only return 0 if you perform a division operation, more specifically like this:


JASS:
// Regard as null and void
function GetUnitAttackSpeed takes unit u returns real
    return RMemory[GetUnitAttackAbility(u)/4 + 0x1B0/4]
endfunction

function GetUnitAttackSpeedSec takes unit u returns real
    local real r = GetUnitAttackSpeed(u)
    return 1 / r
endfunction

My assumption is that the Memory array still treats the value internally as an integer, which will lead to wrong values (if the unit can attack but does not have the attack ability).

I did not check if the pointer Unit's attack data exists. If it cannot attack, then the pointer to the unit's attack data will be 0.
Perhaps this will fix it:
JASS:
function GetUnitBaseDamage takes unit u returns integer
    local integer i = GetUnitAttackAbility(u)
    if i == 0x0 then
        return 0
    endif
    return Memory[i/4 + 0xA0/4]
endfunction
  
function GetUnitAttackSpeed takes unit u returns real
    local integer i = GetUnitAttackAbility(u)
    if i == 0x0 then
        return 0.
    endif
    return RMemory[i/4 + 0x1B0/4]
endfunction

function GetUnitAttackSpeedSec takes unit u returns real
    local real r = GetUnitAttackSpeed(u)
    if r == 0. then
         return 0.
    endif
    return 1/r
endfunction

function GetUnitAttackBackswing takes unit u returns real
    local integer i = GetUnitAttackAbility(u)
    if i == 0x0 then
        return 0.
    endif
    return RMemory[i/4 + 0x190/4]
endfunction
 
Level 2
Joined
Oct 3, 2017
Messages
26
There are also a special AS penalty @ 0x1C0, the value is alwways negative or 0. You can see it when affected by poison attack. IDK why it uses separate field but it's worthy to know for non-dota too. Basially u need to sum both fields to get proper value.
 
Level 2
Joined
Oct 3, 2017
Messages
26
Does anyone got new ConvertHandle to work? This opt doesn't work for me as ~20-30 seconds ingame offset with [+412] changes it's value, causing access error instnantly. Can't really understand what causes that. Also, value is different when loading screen enabled and right after that. IDK whats so special about that.
 
Level 9
Joined
Jul 30, 2012
Messages
156
Does anyone got new ConvertHandle to work? This opt doesn't work for me as ~20-30 seconds ingame offset with [+412] changes it's value, causing access error instnantly. Can't really understand what causes that. Also, value is different when loading screen enabled and right after that. IDK whats so special about that.

Could you please upload a testmap that reproduces this problem? I tested it here and it was working just fine, but I got a similar problem when I tried to optimize GetStringAddress with the same method (because address of StringHandle table changes when new strings are inserted). Maybe the same is happenning with handles, I tried to spam handle creation and it still worked properly, but if you can upload a map where the problem is happening, I'll try to find the cause.
 
Level 2
Joined
Oct 3, 2017
Messages
26
Could you please upload a testmap that reproduces this problem? I tested it here and it was working just fine, but I got a similar problem when I tried to optimize GetStringAddress with the same method (because address of StringHandle table changes when new strings are inserted). Maybe the same is happenning with handles, I tried to spam handle creation and it still worked properly, but if you can upload a map where the problem is happening, I'll try to find the cause.
No need, I investigated it myself. 26a, as always
sub_6F42CB50 gets called, like, on every handle creation? Takes environment
JASS:
RMem(RMem(GameState) + 28)  + 404
(readmem == non-divided)
everytime handle counter getting 1k bigger than before, it asks for sub_6F42B060 to re-allocate memory for storage.
0Arb7zA.png

In case when we need to increase size ReAlloc returns 0, which leads to a new MemAlloc with known result - table get moved.
So, there are no way to relate on this opt, unless you're 100% sure you allocated as many handles as you could ever have in map, and it's really hard to say so as counter doesnt seem to decrease.
 
Last edited:
Level 9
Joined
Jul 30, 2012
Messages
156
Things ppl can play with memhack. Thanks god.

Actually Endemium doesn't use memhack, it uses RenderEdge which is just a 3rd party dll injected into WC3. In theory it can be made to work on all patches, without memhack, the only drawback is that the user would be required to download the library themselves, while memhack allows the developer to distrbute the dll inside the map (or even download it from the web) and automatically inject it into WC3 without user interaction.

The same applies to any map that is currently using memhack. One can easily make a custom DLL that exposes functions like ReadMemory and WriteMemory and achieve memhack-like functionality on the latest WC3 patches. It will be less user-friendly though.
 
Level 8
Joined
Nov 29, 2014
Messages
191
Actually Endemium doesn't use memhack, it uses RenderEdge which is just a 3rd party dll injected into WC3.
You're wrong. All functions for interface editing are available without DLL injection. RenderEdge_mini.dll adds only functions like GetMouseX, GetTriggerKey and TriggerRegisterKeyEvent.

[RenderEdge] Memory Hack

JASS:
library Interface initializer Init uses FpCall, Utils

    globals
        constant integer ANCHOR_TOPLEFT = 0
        constant integer ANCHOR_TOP = 1
        constant integer ANCHOR_TOPRIGHT = 2
        constant integer ANCHOR_LEFT = 3
        constant integer ANCHOR_CENTER = 4
        constant integer ANCHOR_RIGHT = 5
        constant integer ANCHOR_BOTTOMLEFT = 6
        constant integer ANCHOR_BOTTOM = 7
        constant integer ANCHOR_BOTTOMRIGHT = 8
 
        constant integer FRAME_WorldFrameWar3 = 239
        constant integer FRAME_Minimap = 240
        constant integer FRAME_InfoBar = 241
        constant integer FRAME_CommandBar = 242
        constant integer FRAME_ResourceBarFrame = 243
        constant integer FRAME_UpperButtonBarFrame = 244
        constant integer FRAME_Unknown1 = 245 // ?
        constant integer FRAME_ClickableBlock = 246
        constant integer FRAME_HeroBar = 247
        constant integer FRAME_PeonBar = 248
        constant integer FRAME_Message = 249
        constant integer FRAME_UnitMessage = 250
        constant integer FRAME_ChatMessage = 251
        constant integer FRAME_TopMessage = 252
        constant integer FRAME_Portrait = 253
        constant integer FRAME_TimeOfDayIndicator = 254
        constant integer FRAME_ChatEditBar = 255
        constant integer FRAME_CinematicPanel = 256
        constant integer FRAME_Unknown2 = 257 // ?
        constant integer FRAME_MinimapButton1 = 258
        constant integer FRAME_MinimapButton2 = 259
        constant integer FRAME_MinimapButton3 = 260
        constant integer FRAME_MinimapButton4 = 261
        constant integer FRAME_MinimapButton5 = 262
        constant integer FRAME_FrameB = 263
        constant integer FRAME_MouseBorders = 264
        constant integer FRAME_FrameA = 265
        constant integer FRAME_SimpleConsole = 266
 
        integer address_GetGameUI = 0
        integer address_SetFramePoint = 0
        integer address_SetFramePoint2 = 0
        integer address_SetFrameWidth = 0
        integer address_SetFrameHeight = 0
        integer address_GetFrameTextAddress = 0
        integer address_GetFrameItemAddress = 0
        integer address_GetFrameSkinAddress = 0
        integer address_UpdateFrameText = 0
 
        integer pGameUI = 0
    endglobals
 
    // =================================================
 
    function GetGameUI takes integer a1, integer a2 returns integer
        return fast_call2(address_GetGameUI, a1, a2)
    endfunction
 
    function ReadGameUIStruct takes integer element returns integer
        return Memory[pGameUI/4 + element]
    endfunction
 
    function GetRootFrame takes nothing returns integer
        return pGameUI + 180
    endfunction
 
    function SetFramePoint takes integer pFrame, integer point, integer pParentFrame, integer relativePoint, real offsetX, real offsetY returns nothing
        call this_call7(address_SetFramePoint, pFrame, point, pParentFrame, relativePoint, SetRealIntoMemory(offsetX), SetRealIntoMemory(offsetY), 1)
    endfunction
 
    function SetFramePoint2 takes integer pFrame, integer point, real offsetX, real offsetY returns nothing
        call this_call5(address_SetFramePoint2, pFrame, point, SetRealIntoMemory(offsetX), SetRealIntoMemory(offsetY), 1)
    endfunction
 
    function SetFrameWidth takes integer pFrame, real width returns nothing
        call this_call2(address_SetFrameWidth, pFrame, SetRealIntoMemory(width))
    endfunction
 
    function SetFrameHeight takes integer pFrame, real height returns nothing
        call this_call2(address_SetFrameHeight, pFrame, SetRealIntoMemory(height))
    endfunction
 
    function GetFrameWidth takes integer pFrame returns real
        return GetRealFromMemory(Memory[pFrame/4 + 22])
    endfunction
 
    function GetFrameHeight takes integer pFrame returns real
        return GetRealFromMemory(Memory[pFrame/4 + 23])
    endfunction
 
    function GetFramePointParent takes integer pFrame, integer point returns integer
        return Memory[Memory[pFrame/4 + point + 2]/4 + 1]
    endfunction
 
    function GetFramePointRelativePoint takes integer pFrame, integer point returns integer
        return Memory[Memory[pFrame/4 + point + 2]/4 + 2]
    endfunction
 
    function GetFramePointX takes integer pFrame, integer point returns real
        return GetRealFromMemory(Memory[Memory[pFrame/4 + point + 2]/4 + 3])
    endfunction
 
    function GetFramePointY takes integer pFrame, integer point returns real
        return GetRealFromMemory(Memory[Memory[pFrame/4 + point + 2]/4 + 4])
    endfunction
 
    function GetFrameTextAddress takes string name, integer id returns integer
        return fast_call2(address_GetFrameTextAddress, GetStringAddress(name), id)
    endfunction
 
    function GetFrameItemAddress takes string name, integer id returns integer
        return fast_call2(address_GetFrameItemAddress, GetStringAddress(name), id)
    endfunction

    function GetFrameSkinAddress takes string name, integer id returns integer
        return fast_call2(address_GetFrameSkinAddress, GetStringAddress(name), id)
    endfunction
 
    function GetFrameTextString takes string name, integer id returns string
        local integer FrameAddr = GetFrameTextAddress(name, id)
        if FrameAddr == 0 then
            return ""
        endif
        return ConvertNullTerminatedStringToString(ReadRealMemory(FrameAddr + 0x9C))
    endfunction
 
    function SetFrameTextAddress takes integer addr, string str returns nothing
        call this_call2(address_UpdateFrameText, addr, GetStringAddress(str))
    endfunction

    // =================================================
 
    function GetPanelButton takes integer pFrame, integer row, integer column returns integer
        return Memory[Memory[4 * row + Memory[pFrame/4 + 85]/4 + 2]/4 + column]
    endfunction
 
    function GetMinimapButton takes integer id returns integer // id = [0; 4]
        return ReadGameUIStruct(FRAME_MinimapButton1 + id)
    endfunction

    function GetUpperButtonBarButton takes integer id returns integer // id = [0; 3]
        local integer pUpperButtonBar = ReadGameUIStruct(FRAME_UpperButtonBarFrame)
        if (id == 0) then
            return Memory[pUpperButtonBar/4 + 78]
        elseif (id == 1) then
            return Memory[pUpperButtonBar/4 + 76]
        elseif (id == 2) then
            return Memory[pUpperButtonBar/4 + 77]
        elseif (id == 3) then
            return Memory[pUpperButtonBar/4 + 88]
        endif
        return 0
    endfunction
 
    function GetCommandBarButton takes integer row, integer column returns integer // row = [0; 2]  column = [0; 3]
        local integer pCommandBar = ReadGameUIStruct(FRAME_CommandBar)
        return GetPanelButton(pCommandBar, row, column)
    endfunction

    function GetItemBarButton takes integer id returns integer // id = [0; 5]
        local integer pInfoBar = ReadGameUIStruct(FRAME_InfoBar)
        local integer pItemBar = Memory[pInfoBar/4 + 82]
        return Memory[Memory[pItemBar/4 + 76]/4 + 2 * id + 1]
    endfunction
 
    function GetHeroBarButton takes integer id returns integer // id = [0; 6]
        local integer pHeroBar = ReadGameUIStruct(FRAME_HeroBar)
        return GetPanelButton(pHeroBar, id, 0)
    endfunction
 
    // =================================================
 
    function HideInterface takes nothing returns nothing
        local integer pRootFrame = GetRootFrame()

        call SetFramePoint(ReadGameUIStruct(FRAME_UpperButtonBarFrame), ANCHOR_TOPLEFT, pRootFrame, ANCHOR_TOPLEFT, 0.0, 1.0)
        call SetFramePoint(ReadGameUIStruct(FRAME_ResourceBarFrame), ANCHOR_TOPRIGHT, pRootFrame, ANCHOR_TOPRIGHT, 0.0, 1.0)

        call SetFramePoint(ReadGameUIStruct(FRAME_SimpleConsole), ANCHOR_TOPLEFT, pRootFrame, ANCHOR_TOPLEFT, 10.0, 0.0)
        call SetFramePoint(ReadGameUIStruct(FRAME_SimpleConsole), ANCHOR_TOPRIGHT, pRootFrame, ANCHOR_TOPRIGHT, -10.0, 0.0)

        call SetFramePoint(ReadGameUIStruct(FRAME_Portrait) + 180, ANCHOR_BOTTOMLEFT, pRootFrame, ANCHOR_BOTTOMLEFT, 1.0, 1.0)
        call SetFramePoint(ReadGameUIStruct(FRAME_Minimap) + 180, ANCHOR_BOTTOMLEFT, pRootFrame, ANCHOR_BOTTOMLEFT, 1.0, 1.0)

        call SetFramePoint(ReadGameUIStruct(FRAME_PeonBar), ANCHOR_BOTTOMLEFT, pRootFrame, ANCHOR_BOTTOMLEFT, 1.0, 1.0)
        call SetFramePoint(ReadGameUIStruct(FRAME_HeroBar), ANCHOR_TOPLEFT, pRootFrame, ANCHOR_TOPLEFT, 0.0, 1.0)

        call SetFramePoint(ReadGameUIStruct(FRAME_TimeOfDayIndicator) + 180, ANCHOR_BOTTOMLEFT, pRootFrame, ANCHOR_BOTTOMLEFT, 1.0, 1.0)
        call SetFramePoint(Memory[ReadGameUIStruct(FRAME_TimeOfDayIndicator)/4 + 108] + 180, ANCHOR_TOP, pRootFrame, ANCHOR_TOP, 1.0, 0.0) // TimeOfDayIndicator UBERTIP

        call SetFramePoint(Memory[ReadGameUIStruct(FRAME_InfoBar)/4 + 83], ANCHOR_BOTTOMRIGHT, pRootFrame, ANCHOR_TOPLEFT, 1.0, 0.0) // ConsoleInventoryCoverTexture
    endfunction

    function EditBlackBorders takes real upperHeight, real bottomHeight returns nothing
        local integer pWorldFrameWar3 = ReadGameUIStruct(FRAME_WorldFrameWar3) + 180
        local integer pRootFrame = GetRootFrame()

        call SetFramePoint(pWorldFrameWar3, ANCHOR_TOPRIGHT, pRootFrame, ANCHOR_TOPRIGHT, 0.0, -upperHeight)
        call SetFramePoint(pWorldFrameWar3, ANCHOR_BOTTOMLEFT, pRootFrame, ANCHOR_BOTTOMLEFT, 0.0, bottomHeight)
    endfunction
 
    function EditPortrait takes integer anchor, real offsetX, real offsetY, real width, real height returns nothing
        local integer pPortraitFrame = ReadGameUIStruct(FRAME_Portrait) + 180
        local integer pRootFrame = GetRootFrame()
 
        if (width >= 0) then
            call SetFrameWidth(pPortraitFrame, width)
        endif
        if (height >= 0) then
            call SetFrameHeight(pPortraitFrame, height)
        endif
        call SetFramePoint(pPortraitFrame, ANCHOR_BOTTOMLEFT, pRootFrame, anchor, offsetX, -(offsetY + GetFrameHeight(pPortraitFrame)))
    endfunction
 
    function EditMinimap takes integer anchor, real offsetX, real offsetY, real width, real height returns nothing
        local integer pMinimapFrame = ReadGameUIStruct(FRAME_Minimap) + 180
        local integer pRootFrame = GetRootFrame()

        call SetFramePoint(pMinimapFrame, ANCHOR_BOTTOMLEFT, pRootFrame, anchor, offsetX, -(offsetY + height))
        call SetFramePoint(pMinimapFrame, ANCHOR_TOPRIGHT, pRootFrame, anchor, offsetX + width, -offsetY)
    endfunction
 
    function EditCommandBarButton takes integer row, integer column, integer anchor, real offsetX, real offsetY, real width, real height returns nothing
        local integer pButtonFrame = GetCommandBarButton(row, column)
        local integer pRootFrame = GetRootFrame()
 
        if (width >= 0) then
            call SetFrameWidth(pButtonFrame, width)
        endif
        if (height >= 0) then
            call SetFrameHeight(pButtonFrame, height)
        endif
        call SetFramePoint(pButtonFrame, ANCHOR_TOPLEFT, pRootFrame, anchor, offsetX, -offsetY)
    endfunction
 
    function EditItemBarButton takes integer buttonId, integer anchor, real offsetX, real offsetY, real width, real height returns nothing
        local integer pButtonFrame = GetItemBarButton(buttonId)
        local integer pRootFrame = GetRootFrame()
 
        if (width >= 0) then
            call SetFrameWidth(pButtonFrame, width)
        endif
        if (height >= 0) then
            call SetFrameHeight(pButtonFrame, height)
        endif
        call SetFramePoint(pButtonFrame, ANCHOR_TOPLEFT, pRootFrame, anchor, offsetX, -offsetY)
    endfunction
 
    function EditMinimapButton takes integer buttonId, integer anchor, real offsetX, real offsetY, real width, real height returns nothing
        local integer pButtonFrame = GetMinimapButton(buttonId)
        local integer pRootFrame = GetRootFrame()
 
        if (width >= 0) then
            call SetFrameWidth(pButtonFrame, width)
        endif
        if (height >= 0) then
            call SetFrameHeight(pButtonFrame, height)
        endif
        call SetFramePoint(pButtonFrame, ANCHOR_TOPLEFT, pRootFrame, anchor, offsetX, -offsetY)
    endfunction
 
    function EditUpperButtonBarButton takes integer buttonId, integer anchor, real offsetX, real offsetY, real width, real height returns nothing
        local integer pButtonFrame = GetUpperButtonBarButton(buttonId)
        local integer pRootFrame = GetRootFrame()
 
        if (width >= 0) then
            call SetFrameWidth(pButtonFrame, width)
        endif
        if (height >= 0) then
            call SetFrameHeight(pButtonFrame, height)
        endif
 
        if (buttonId == 0) then
            call SetFramePoint(pButtonFrame, ANCHOR_TOPLEFT, pRootFrame, anchor, offsetX, -offsetY)
        else
            call SetFramePoint(pButtonFrame, ANCHOR_LEFT, pRootFrame, anchor, offsetX, -(offsetY + GetFrameHeight(pButtonFrame)/2))
        endif
    endfunction
 
    function EditHeroBarButton takes integer buttonId, integer anchor, real offsetX, real offsetY, real width, real height returns nothing
        local integer pButtonFrame = GetHeroBarButton(buttonId)
        local integer pRootFrame = GetRootFrame()
 
        if (width >= 0) then
            call SetFrameWidth(pButtonFrame, width)
        endif
        if (height >= 0) then
            call SetFrameHeight(pButtonFrame, height)
        endif
        call SetFramePoint(pButtonFrame, ANCHOR_TOPLEFT, pRootFrame, anchor, offsetX, -offsetY)
    endfunction
 
    function EditHeroBarHealthBar takes integer buttonId, integer anchor, real offsetX, real offsetY, real width, real height returns nothing
        local integer pHealthFrame = Memory[GetHeroBarButton(buttonId)/4 + 115]
        local integer pRootFrame = GetRootFrame()
 
        if (width >= 0) then
            call SetFrameWidth(pHealthFrame, width)
        endif
        if (height >= 0) then
            call SetFrameHeight(pHealthFrame, height)
        endif
        call SetFramePoint(pHealthFrame, ANCHOR_TOP, pRootFrame, anchor, offsetX + GetFrameWidth(pHealthFrame)/2, -offsetY)
    endfunction
 
    function EditHeroBarManaBar takes integer buttonId, integer anchor, real offsetX, real offsetY, real width, real height returns nothing
        local integer pManaFrame = Memory[GetHeroBarButton(buttonId)/4 + 116]
        local integer pRootFrame = GetRootFrame()
 
        if (width >= 0) then
            call SetFrameWidth(pManaFrame, width)
        endif
        if (height >= 0) then
            call SetFrameHeight(pManaFrame, height)
        endif
        call SetFramePoint(pManaFrame, ANCHOR_TOP, pRootFrame, anchor, offsetX + GetFrameWidth(pManaFrame)/2, -offsetY)
    endfunction
 
    // =================================================
 
 
    private function Init takes nothing returns nothing
        set address_GetGameUI = address_GameBase + 0x300710
        set address_SetFramePoint = address_GameBase + 0x606770
        set address_SetFramePoint2 = address_GameBase + 0x6061B0
        set address_SetFrameWidth = address_GameBase + 0x605D90
        set address_SetFrameHeight = address_GameBase + 0x605DB0
        set address_GetFrameTextAddress = address_GameBase + 0x61C7B0
        set address_GetFrameItemAddress = address_GameBase + 0x5FA970
        set address_GetFrameSkinAddress = address_GameBase + 0x31F530
        set address_UpdateFrameText = address_GameBase + 0x60CA10
 
        set pGameUI = GetGameUI(0, 0)
    endfunction
 
endlibrary
 
Last edited:
Level 9
Joined
Jul 30, 2012
Messages
156
You're wrong. All functions for interface editing are available without DLL injection. RenderEdge_mini.dll adds only functions like GetMouseX, GetTriggerKey and TriggerRegisterKeyEvent.

I see. But I suppose you were developing RenderEdge much before Memhack was released, and you were certainly using an injected DLL back then. My point is, it's totally possible to make everything via injected DLL, without making use of an exploit.
 
Level 2
Joined
Oct 3, 2017
Messages
26
I see. But I suppose you were developing RenderEdge much before Memhack was released, and you were certainly using an injected DLL back then. My point is, it's totally possible to make everything via injected DLL, without making use of an exploit.
just like the sharpcraft, which provided some extra functions but never made it popular as nobody ever would DL anything but the map itself. exploit is must have to make map popular, thats it.
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
@leandrotp
I tested my map just now. Someone still experience crashes on loading, he tried both patch 1.26 and 1.27b, with exactly same result: crash. And it wasn't caused by texture quality issue btw. It never happened to me tho, with whatever patch version I tested it with: it works perfectly fine, and most people too as far as I know. Do you know what probably caused it?
 
Level 3
Joined
Jan 16, 2013
Messages
11
Your code is full of errors, for example: using 'codes' as integers WITHOUT CASTING THEM to integers. Or using function with more than 0 arguments as code. Script parser will never allow you to save map like this, even experimental pjass.exe.
I have my own working memhack, but with lesser set of functions.
errors.png



How did you even made this work?
 
Status
Not open for further replies.
Top