AMHS (Anti Map Hack System)

General discussion of Warcraft 3. Threads may may be posted here if they don't fit into the other sections.

Moderator: Cheaters

User avatar
qweasd011
Forum Addict
Posts: 451
Joined: November 21st, 2008, 9:36 am
Title: Coleen!

AMHS (Anti Map Hack System)

Post by qweasd011 »

Credits to PandaMine & Strilanc- its a good protection to protect your map to Map Hacks :D

AMHS (Anti Map Hack System) created by PandaMine
Current Version: 5.2

IT IS HIGHLY RECOMMENDED THAT YOU READ THROUGH EVERY README/MANUAL IN THE AMHS v5.x - THE WHOLE SYSTEM HAS CHANGED

Many thanks to Strilanc who's suggestions greatly increased the speed and efficiency of the system

Advantages
- First AMH system that works with replays, fully (thanks to my replay detect function, credits to Toadcop and Captain Griffein)
- Counters all the major features of ALL and I mean ALL public map hacks (there isnt much I can do for private ones). Check the MH List trigger in the map for more info
- Prevents any MH from revealing units on the screen
- Prevents any MH from revealing units on the minimap
- Prevents any MH from revealing special effects on the screen
Disadvantages
- The replay detect function (used to disable the system when viewing replays) uses up one pause and makes a noticable message.
- With the new AMHS v5.x, you need to input the data for every unit that the map uses into the engine since there unfortunately isn't any known method for WE/JASS to read/write data to the Object Editor
- JassNewGen (vJASS) is mandatory, there is not going to be any non JassNewGen releases

How does the system work?
The current version of the system works by hiding units/minimap icons/destructables/effects if they are not visible by a player so any MH will not reveal them
Fog Protect and Shadow Engine
This a huge engine that fully replaces the default Blizzard engine for managing shadows and UnitVertexColor/UnitScale. The system works by completely and graphically hiding a unit if it is not visible (determined by IsUnitVisible) to a player. It also adds many more options, too many to go through in this post (read the Readme).

This also works with Invisible Units
Spoiler:

Code: Select all

library FogProtectShadowEngine needs ReplayDetectEngine, AMHSCache
//*************************************************************************
//*                                                                       *                                          *
//*                      FOG PROTECT & SHADOW ENGINE v1.20                *
//*                      CONFIGURATION SETTINGS START HERE                *                     *
//*                                                                       *                                          *
//*************************************************************************
globals

// This is the default alpha value used for shadows. From visual experimentation the alpha
// value of Blizzards shadows appear to be 180. If desire you can change the value
// NOTE: If you wish you can change the alpha value of a shadow using the SetShadowAlpha
// method at any time, this is just the default value when the shadow is created
private constant integer shadowalpha_default = 180

// This is the interval period used by the system. 0.025 should be the LOWEST value, anything
// lower is pointless since 0.025 matches Wc3's maximum FPS (60 fp/s). If the system is
// causing lag then you should increase it to a value between 0.025 and 0.05. Anything higher
// then 0.05 is seriously not recommended since it will look visually choppy.
// NOTE: The system is INCREDIBLY efficient and it uses the struct-loop system (no H2I/attach
// methods are used for the timer interval) so in 99% of cases you should never have to increase
// the period
private constant real period = 0.025

// By default Blizzard shadows are disabled when a unit dies (note when a unit dies, this doesn't
// necessarily mean when its removed from the game. If a unit is removed from the by killunit
// or removeunit the shadow is destroyed, however should a hero die then the shadow will not
// be removed, instead it will be disabled. A units death is evaluated by the 
// GetUnitState(u,UNIT_STATE_MAX_LIFE) <= 0.405. Should the unit be revived by a spell such
// as reincarnation then its shadow will return back to what it was before it died

// Setting this to false will mean the shadow will still remain even if the unit dies. NOTE: If
// hideshadowondeath is enabled it can be detect with the GetShadowVisibility method, so this
// means you would need to take care of when a unit dies when dealing with showing/hiding shadows
 
private constant boolean hideshadowondeath = true

endglobals
//*************************************************************************
//*                                                                       *                                          *
//*                            FOG PROTECT & SHADOW ENGINE v1.20          *                       *
//*                            CONFIGURATION SETTINGS END HERE            *                        *
//*                                                                       *                                          *
//*************************************************************************

// Create has used to store buffs

globals
    private gamecache fp_datacache
    private boolean cachefirst = true
    private trigger RegisterUnit = CreateTrigger()
    private group g = CreateGroup()
    
    //Stack for shadow struct
    private integer array s_StructStack
    private integer array s_StructFreeStack
    private integer s_StructNumber = 0
    private integer s_StructFreeNumber = -1
    //Stack for  unit/graphic struct
    private integer array gp_StructStack
    private integer array gp_StructFreeStack
    private integer gp_StructNumber = 0
    private integer gp_StructFreeNumber = -1    
endglobals

private function H2I takes handle h returns integer
    return h
    return 0
endfunction

private function InitializeDataCache takes nothing returns nothing
call FlushGameCache(InitGameCache("fp_datacache"))
set fp_datacache=InitGameCache("fp_datacache")
endfunction

//! runtextmacro AMHS_HandleInit()

//Shadow Struct -> Public Use
struct shadow
    readonly real x
    readonly real y
    readonly real centrex
    readonly real centrey
    readonly real width
    readonly real height
    readonly integer r
    readonly integer g
    readonly integer b
    readonly integer a
    readonly unit u
    readonly string path
    readonly image i
    readonly boolean enabled = true
    readonly boolean deadunit = false
    readonly integer position //position in relation to struct stack

    
    static method Create takes unit u, real centrex, real centrey, real width, real height, integer alpha, string path returns shadow
    local shadow s = shadow.create()
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    set s.x = x
    set s.y = y
    set s.width = width
    set s.height = height
    set s.a = alpha
    set s.u = u
    set s.centrex = centrex
    set s.centrey = centrey
    set s.path = path
    
    if path == "normal" or path == "Normal" or path == "NORMAL" or path == "Shadow" or path == "shadow" or path == "SHADOW" then
        set s.path = "ReplaceableTextures\\Shadows\\Shadow.blp"
    elseif path == "flyer" or path == "Flyer" or path == "FLYER" or path == "ShadowFlyer" or path == "shadowflyer" or path == "SHADOWFLYER" then
        set s.path = "Textures\\Shadow.blp"
    elseif path == "none" or path == "None" or path == "NONE" then
        set s.path = ""
    endif
    set s.i = CreateImage(s.path, width, height, 0, x - (width / 2), y - (height / 2), 0, centrex, centrey, 0, 2) // image type indicator
    call SetImageRenderAlways(s.i, true)
    call ShowImage(s.i, true)
    call SetImageColor(s.i,255,255,255,alpha)
    set s.r = 255
    set s.g = 255
    set s.b = 255
    set s.a = 180
    //Update Struct Stack
    if s_StructFreeNumber<0 then
        set s.position = s_StructNumber
        set s_StructStack[s_StructNumber] = s
        set s_StructNumber = s_StructNumber+1
    else
        set s.position = s_StructFreeStack[s_StructFreeNumber]
        set s_StructStack[s.position] = s
        set s_StructFreeStack[s_StructFreeNumber] = -1
        set s_StructFreeNumber = s_StructFreeNumber-1
    endif
    //! runtextmacro AMHS_StoreStructShadow("s.u","s")
    return s
    endmethod
    
    public method ChangeDeadUnit takes boolean flag returns nothing
        set this.deadunit = flag
    endmethod
    
    method GetShadowPath takes nothing returns string
        return this.path
    endmethod
    
    method GetShadowAlpha takes nothing returns integer
        return this.a
    endmethod
    
    method GetShadowRed takes nothing returns integer
        return this.r
    endmethod
    
    method GetShadowGreen takes nothing returns integer
        return this.g
    endmethod
    
    method GetShadowBlue takes nothing returns integer
        return this.b
    endmethod
    
    method GetShadowCentreX takes nothing returns real
        return this.centrex
    endmethod
    
    method GetShadowCentreY takes nothing returns real
        return this.centrey
    endmethod
    
    method GetShadowHeight takes nothing returns real
        return this.height
    endmethod
    
    method GetShadowWidth takes nothing returns real
        return this.width
    endmethod
    
    method GetShadowUnit takes nothing returns unit
        return this.u
    endmethod
    
    method GetDefaultShadowCentreX takes nothing returns real
        local string s = UnitId2String(GetUnitTypeId(this.u))
        if GetStoredBoolean(fp_datacache,s,"exist") == true then
            return GetStoredReal(fp_datacache,s,"centrex")
        else
            return I2R(0)
        endif
    endmethod
    
    method GetDefaultShadowCentreY takes nothing returns real
        local string s = UnitId2String(GetUnitTypeId(this.u))
        if GetStoredBoolean(fp_datacache,s,"exist") == true then
            return GetStoredReal(fp_datacache,s,"centrey")
        else
            return I2R(0)
        endif
    endmethod
    
    method GetDefaultShadowHeight takes nothing returns real
        local string s = UnitId2String(GetUnitTypeId(this.u))
        if GetStoredBoolean(fp_datacache,s,"exist") == true then
            return GetStoredReal(fp_datacache,s,"height")
        else
            return I2R(0)
        endif
    endmethod
    
    method GetDefaultShadowWidth takes nothing returns real
        local string s = UnitId2String(GetUnitTypeId(this.u))
        if GetStoredBoolean(fp_datacache,s,"exist") == true then
            return GetStoredReal(fp_datacache,s,"width")
        else
            return I2R(0)
        endif
    endmethod
    
    method GetDefaultShadowPath takes nothing returns string
        local string s = UnitId2String(GetUnitTypeId(this.u))
        if GetStoredBoolean(fp_datacache,s,"exist") == true then
            return GetStoredString(fp_datacache,s,"path")
        else
            return ""
        endif
    endmethod
    
    method SetShadowColor takes integer red, integer green, integer blue, integer alpha returns nothing
        call SetImageColor(this.i,red,green,blue,alpha)
        set this.r = red
        set this.g = green
        set this.b = blue
        set this.a = alpha
    endmethod
    
    method SetShadowAlpha takes integer alpha returns nothing
        call SetImageColor(this.i,this.r,this.g,this.b,alpha)
        set this.a = alpha
    endmethod
    
    method SetShadowVisibility takes boolean visibility returns nothing
        call ShowImage(this.i,visibility)
        set this.enabled = visibility
    endmethod
    
    method SetShadowImage takes string path returns nothing
        local string truepath = path
        call DestroyImage(this.i)
        set this.i = null
        if path == "normal" or path == "Normal" or path == "NORMAL" then
            set truepath = "ReplaceableTextures\\Shadows\\Shadow.blp"
        elseif path == "flyer" or path == "Flyer" or path == "FLYER" then
            set truepath = "Textures\\Shadow.blp"
        elseif path == "none" or path == "None" or path == "NONE" then
            set truepath = ""
        endif
        set this.i = CreateImage(truepath, this.width, this.height, 0, this.x - (this.width / 2), this.y - (this.height / 2), 0, this.centrex, this.centrey, 0, 2) // image type indicator
        set this.path = truepath
        call SetImageRenderAlways(this.i, true)
        call ShowImage(this.i, true)
        call SetImageColor(this.i,this.r,this.g,this.b,this.a)
     endmethod
     
    method SetShadowImageEx takes string path, real centrex, real centrey, real width, real height returns nothing
        local string truepath = path
        call DestroyImage(this.i)
        set this.i = null
        if path == "normal" or path == "Normal" or path == "NORMAL" then
            set truepath = "ReplaceableTextures\\Shadows\\Shadow.blp"
        elseif path == "flyer" or path == "Flyer" or path == "FLYER" then
            set truepath = "Textures\\Shadow.blp"
        elseif path == "none" or path == "None" or path == "NONE" then
            set truepath = ""
        endif
        set this.i = CreateImage(truepath, width, height, 0, this.x - (width / 2), this.y - (height / 2), 0, centrex, centrey, 0, 2) // image type indicator
        set this.path = truepath
        set this.centrex = centrex
        set this.centrey = centrey
        set this.width = width
        set this.height = height
        call SetImageRenderAlways(this.i, true)
        call ShowImage(this.i, true)
        call SetImageColor(this.i,this.r,this.g,this.b,this.a)    
     endmethod
     
    method SetShadowDimeansions  takes real centrex, real centrey, real width, real height returns nothing
        call DestroyImage(this.i)
        set this.i = null
        set this.i = CreateImage(this.path, width, height, 0, this.x - (width / 2), this.y - (height / 2), 0, centrex, centrey, 0, 2) // image type indicator
        set this.centrex = centrex
        set this.centrey = centrey
        set this.width = width
        set this.height = height
        call SetImageRenderAlways(this.i, true)
        call ShowImage(this.i, true)
        call SetImageColor(this.i,this.r,this.g,this.b,this.a)
    endmethod
    
    method onDestroy takes nothing returns nothing
    call DestroyImage(this.i)
    set this.i = null
    set s_StructStack[this.position] = -1
    if (this.position>=(s_StructNumber-1)) then
        set s_StructNumber = s_StructNumber-1
    else
        set s_StructFreeNumber = s_StructFreeNumber+1
        set s_StructFreeStack[s_StructFreeNumber] = this.position
    endif
    //! runtextmacro AMHS_DestroyStructShadow("this.u")
    set this.u = null
    set this.position = -1
    endmethod
     
endstruct

//Struct for managing SetUnitVertexColor/SetUnitScale
struct unitgraphic
    readonly unit u
    readonly integer r
    readonly integer g
    readonly integer b
    readonly integer a
    readonly real x
    readonly real y
    readonly real z
    readonly boolean enabled
    readonly integer position //position in relation to struct stack
    
    static method Create takes unit u, integer red, integer green, integer blue, integer alpha, real x, real y, real z returns unitgraphic
    local unitgraphic gp = unitgraphic.create()
    set gp.r = red
    set gp.g = green
    set gp.b = blue
    set gp.a = alpha
    set gp.x = x
    set gp.y = y
    set gp.z = z
    set gp.u = u
    set gp.enabled = true
    //Update Struct Stack
    if gp_StructFreeNumber<0 then
        set gp.position = gp_StructNumber
        set gp_StructStack[gp_StructNumber] = gp
        set gp_StructNumber = gp_StructNumber+1
    else
        set gp.position = gp_StructFreeStack[gp_StructFreeNumber]
        set gp_StructStack[gp.position] = gp
        set gp_StructFreeStack[gp_StructFreeNumber] = -1
        set gp_StructFreeNumber = gp_StructFreeNumber-1
    endif
    //! runtextmacro AMHS_StoreStructUnitGraphic("gp.u","gp")
    set u = null
    return gp
    endmethod
    
    method SetVertexColor takes integer red, integer green, integer blue, integer alpha returns nothing
    set this.r = red
    set this.g = green
    set this.b = blue
    set this.a = alpha
    endmethod
    
    method SetVertexColorBJ takes real red, real green, real blue, real transparency returns nothing
    call this.SetVertexColor(PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
    endmethod
    
    method SetScale takes real scaleX, real scaleY, real scaleZ returns nothing
    set this.x = scaleX
    set this.y = scaleY
    set this.z = scaleZ
    endmethod
    
    method SetScalePercent takes real percentScaleX, real percentScaleY, real percentScaleZ returns nothing
    call this.SetScale(percentScaleX * 0.01, percentScaleY * 0.01, percentScaleZ * 0.01)
    endmethod

    method SetGraphicVisibility takes boolean visibility returns nothing
        set this.enabled = visibility
    endmethod
    
    method GetScaleX takes nothing returns real
        return this.x
    endmethod
    
    method GetScaleY takes nothing returns real
        return this.y
    endmethod
    
    method GetScaleZ takes nothing returns real
        return this.z
    endmethod
    
    method GetVertexColorRed takes nothing returns integer
        return this.r
    endmethod
    
    method GetVertexColorGreen takes nothing returns integer
        return this.g
    endmethod
    
    method GetVertexColorBlue takes nothing returns integer
        return this.b
    endmethod
    
    method GetVertexColorAlpha takes nothing returns integer
        return this.a
    endmethod
    
    method GetGraphicVisibility takes nothing returns boolean
        return this.enabled
    endmethod
    
    method onDestroy takes nothing returns nothing
    set gp_StructStack[this.position] = -1
    if (this.position>=(gp_StructNumber-1)) then
        set gp_StructNumber = gp_StructNumber-1
    else
        set gp_StructFreeNumber = gp_StructFreeNumber+1
        set gp_StructFreeStack[gp_StructFreeNumber] = this.position
    endif   
    set this.position = -1
    //! runtextmacro AMHS_DestroyStructUnitGraphic("this.u")
    set this.u = null
    endmethod
   
endstruct

//Public Functions

function RegisterUnitShadow takes integer UnitID, real centrex, real centrey, real height, real width, string ShadowType returns nothing
local string s
if cachefirst then
    call InitializeDataCache()
    set cachefirst = false
endif
set s = UnitId2String(UnitID)
call StoreBoolean(fp_datacache,s,"exist",true)
call StoreReal(fp_datacache,s,"height",height)
call StoreReal(fp_datacache,s,"width",width)
call StoreReal(fp_datacache,s,"centrex",centrex)
call StoreReal(fp_datacache,s,"centrey",centrey)
call StoreString(fp_datacache,s,"path",ShadowType)
endfunction

function RegisterUnitTintEx takes integer UnitID, integer red, integer green, integer blue, integer alpha returns nothing
local string s
if cachefirst then
    call InitializeDataCache()
    set cachefirst = false
endif
set s = UnitId2String(UnitID)
call StoreBoolean(fp_datacache,s,"customtint",true)
call StoreInteger(fp_datacache,s,"tintred",red)
call StoreInteger(fp_datacache,s,"tintgreen",green)
call StoreInteger(fp_datacache,s,"tintblue",blue)
call StoreInteger(fp_datacache,s,"tintalpha",alpha)
endfunction

function RegisterUnitTint takes integer UnitID, integer red, integer green, integer blue returns nothing
call RegisterUnitTintEx(UnitID,red,green,blue,255)
endfunction

function RegisterUnitScaleEx takes integer UnitID, real scaleX, real scaleY, real scaleZ returns nothing
local string s
if cachefirst then
    call InitializeDataCache()
    set cachefirst = false
endif
set s = UnitId2String(UnitID)
call StoreBoolean(fp_datacache,s,"customscale",true)
call StoreReal(fp_datacache,s,"scalex",scaleX)
call StoreReal(fp_datacache,s,"scaley",scaleY)
call StoreReal(fp_datacache,s,"scalez",scaleZ)
endfunction

function RegisterUnitScale takes integer UnitID, real scale returns nothing
call RegisterUnitScaleEx(UnitID,scale,scale,scale)
endfunction

globals
    private integer array bs_StructStack
    private integer array bs_StructFreeStack
    private integer bs_StructNumber = 0
    private integer bs_StructFreeNumber = -1  
endglobals

private struct buffstruct
    integer BuffID
    real x = 0
    real y = 0 
    real z = 0
    real increasex
    real increasey
    real increasez
    integer increasecount
    real SizeDurationIncrease = 0
    integer position
    real Duration
    integer Level = 0
    
    static method Create takes integer BuffID, real x, real y, real z, real SizeDurationIncrease, real Duration, integer Level returns buffstruct
    local buffstruct bs = buffstruct.create()
    set bs.x = x
    set bs.y = y
    set bs.z = z
    set bs.SizeDurationIncrease = SizeDurationIncrease
    set bs.BuffID = BuffID
    set bs.Duration = Duration
    set bs.Level = Level
    if SizeDurationIncrease > 0 then
        set bs.increasecount = R2I(SizeDurationIncrease/period)
        set bs.increasex = bs.x/bs.increasecount
        set bs.increasey = bs.y/bs.increasecount
        set bs.increasez = bs.z/bs.increasecount
    endif
    //Update Struct Stack
    if bs_StructFreeNumber<0 then
        set bs.position = bs_StructNumber
        set bs_StructStack[bs_StructNumber] = bs
        set bs_StructNumber = bs_StructNumber+1
    else
        set bs.position = bs_StructFreeStack[bs_StructFreeNumber]
        set bs_StructStack[bs.position] = bs
        set bs_StructFreeStack[bs_StructFreeNumber] = -1
        set bs_StructFreeNumber = bs_StructFreeNumber-1
    endif
    return bs
    endmethod
    
endstruct

    
function RegisterBuffScaleEx takes integer BuffID, real scaleX, real scaleY, real scaleZ, real SizeDurationIncrease, real Duration, integer Level returns nothing
local buffstruct bs
set bs = buffstruct.Create(BuffID,scaleX,scaleY,scaleZ,SizeDurationIncrease,Duration,Level)
endfunction

function RegisterBuffScale takes integer BuffID, real scale,real SizeDurationIncrease, real Duration, integer Level returns nothing
call RegisterBuffScaleEx(BuffID,scale,scale,scale,SizeDurationIncrease,Duration,Level)
endfunction

function SetUnitVertexColorAMHS takes unit whichUnit, integer red, integer green, integer blue, integer alpha returns nothing
local unitgraphic gp
if whichUnit != null then
    //! runtextmacro AMHS_GetStructUnitGraphic("whichUnit","gp")
    call gp.SetVertexColor(red,green,blue,alpha)
endif
endfunction

function SetUnitVertexColorBJAMHS takes unit whichUnit, real red, real green, real blue, real transparency returns nothing
    call SetUnitVertexColorAMHS(whichUnit, PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
endfunction

function SetUnitScaleAMHS takes unit whichUnit, real scaleX, real scaleY, real scaleZ returns nothing
local unitgraphic gp
if whichUnit != null then
    //! runtextmacro AMHS_GetStructUnitGraphic("whichUnit","gp")
    call gp.SetScale(scaleX,scaleY,scaleZ)
endif
endfunction

function SetUnitScalePercentAMHS takes unit whichUnit, real percentScaleX, real percentScaleY, real percentScaleZ returns nothing
    call SetUnitScaleAMHS(whichUnit, percentScaleX * 0.01, percentScaleY * 0.01, percentScaleZ * 0.01)
endfunction

function GetUnitShadow takes unit u returns integer
    local shadow sh
    if u == null then
        return 0
    endif
    //! runtextmacro AMHS_GetStructShadow("u","sh")
    return sh
endfunction

function GetUnitGraphic takes unit u returns integer
    local unitgraphic gp
    if u == null then
        return 0
    endif
    //! runtextmacro AMHS_GetStructUnitGraphic("u","gp")
    return gp
endfunction

//End Public Functions

private function AddUnits takes unit u returns nothing
    local string s
    local string path
    local real centrex
    local real centrey
    local real height
    local real width
    local integer red = 255
    local integer green = 255
    local integer blue = 255
    local integer alpha = 255
    local real x = 1
    local real y = 1
    local real z = 1
    local shadow sh
    local unitgraphic gp
    set s = UnitId2String(GetUnitTypeId(u))
    if GetStoredBoolean(fp_datacache,s,"exist") == true then
        set path = GetStoredString(fp_datacache,s,"path")
        set centrex = GetStoredReal(fp_datacache,s,"centrex")
        set centrey = GetStoredReal(fp_datacache,s,"centrey")
        set height = GetStoredReal(fp_datacache,s,"height")
        set width = GetStoredReal(fp_datacache,s,"width")
        set sh = shadow.Create(u,centrex,centrey,width,height,shadowalpha_default,path)
    else
        call BJDebugMsg("|cFFFF0000AMHS ERROR: Unable to create shadow for unit with UnitType ID " + s)
    endif

    if GetStoredBoolean(fp_datacache,s,"customtint") then
        set red = GetStoredInteger(fp_datacache,s,"tintred")
        set green = GetStoredInteger(fp_datacache,s,"tintgreen")
        set blue = GetStoredInteger(fp_datacache,s,"tintblue")
        set alpha = GetStoredInteger(fp_datacache,s,"tintalpha")
    endif
    if GetStoredBoolean(fp_datacache,s,"customscale") then
        set x = GetStoredReal(fp_datacache,s,"scalex")
        set y = GetStoredReal(fp_datacache,s,"scaley")
        set z = GetStoredReal(fp_datacache,s,"scalez")
    endif
    set gp = unitgraphic.Create(u,red,green,blue,alpha,x,y,z)
    set u = null
endfunction

private function ShadowGraphicManager takes nothing returns nothing
    local unitgraphic gp
    local shadow s
    local integer counter = 0
    local real l1 = GetRandomReal(1000,10000000000)
    local real l2 = GetRandomReal(1000,10000000000)
    local real l3 = GetRandomReal(1000,10000000000)
    local player p = GetLocalPlayer()
    loop
        set gp = gp_StructStack[counter]
        if integer(gp) > -1 then
            if GetUnitTypeId(gp.u) == 0 then
                call gp.destroy()
            else
                if IsUnitVisible(gp.u, p) then
                    if gp.enabled then
                        call SetUnitVertexColor(gp.u,gp.r,gp.g,gp.b,gp.a)
                        call SetUnitScale(gp.u,gp.x,gp.y,gp.z)
                    else
                        call SetUnitVertexColor(gp.u,0,0,0,0)
                        call SetUnitScale(gp.u,-l1,-l2,-l3)
                    endif
                elseif InGame and GetLocalPlayer() == p then
                    call SetUnitVertexColor(gp.u,0,0,0,0)
                    call SetUnitScale(gp.u,-l1,-l2,-l3)
                endif
            endif
        endif
        set counter = counter + 1
        exitwhen counter >= gp_StructNumber
    endloop
        
    set counter = 0
    loop
        set s = s_StructStack[counter]
        if integer(s) > -1 then
            if GetUnitTypeId(s.u) == 0 then
                call s.destroy()
            else
                if GetUnitState(s.u,UNIT_STATE_MAX_LIFE) > 0.405 and s.deadunit then
                    call s.ChangeDeadUnit(false)
                    call s.SetShadowVisibility(true)
                endif
                if IsUnitVisible(s.u, p) then
                    if s.enabled then
                        call ShowImage(s.i,true)
                    else
                        call ShowImage(s.i,false)
                    endif
                elseif InGame and GetLocalPlayer() == p then
                    call ShowImage(s.i,false)
                endif
                call SetImagePosition(s.i,GetUnitX(s.u),GetUnitY(s.u),0)
            endif
        endif
        set counter = counter + 1
        exitwhen counter >= s_StructNumber
    endloop
endfunction

private function GroupAdder takes nothing returns nothing
    call AddUnits(GetEnumUnit())
endfunction

private function TriggerAdder takes nothing returns boolean
    call AddUnits(GetTriggerUnit())
    return true
endfunction

private function AntiLeak takes nothing returns boolean
    return true
endfunction

private function FinalGroup takes nothing returns nothing
    call GroupAddUnit(g,GetEnumUnit())
endfunction

globals
    private integer array bc_StructStack
    private integer array bc_StructFreeStack
    private integer bc_StructNumber = 0
    private integer bc_StructFreeNumber = -1  
endglobals

private struct buffcheck
    unit u
    integer position
    integer buffstructid
    integer unitgraphicid
    integer counter
    boolean increasing
    boolean decreasing
    real timeelapsed

    static method Create takes unit u, integer buffstructid, integer unitgraphicid returns buffcheck
    local buffcheck bc = buffcheck.create()
    local buffstruct bs = buffstructid
    set bc.u = u
    set bc.buffstructid = buffstructid
    set bc.unitgraphicid = unitgraphicid
    set bc.counter = 0
    set bc.timeelapsed = 0
    if bs.SizeDurationIncrease > 0 then
        set bc.increasing = true
    else
        set bc.increasing = false
    endif
    //Update Struct Stack
    if bc_StructFreeNumber<0 then
        set bc.position = bc_StructNumber
        set bc_StructStack[bc_StructNumber] = bc
        set bc_StructNumber = bc_StructNumber+1
    else
        set bc.position = bs_StructFreeStack[bc_StructFreeNumber]
        set bc_StructStack[bc.position] = bc
        set bc_StructFreeStack[bc_StructFreeNumber] = -1
        set bc_StructFreeNumber = bc_StructFreeNumber-1
    endif
    return bc
    endmethod
    
    method onDestroy takes nothing returns nothing
    set bc_StructStack[this.position] = -1
    if (this.position>=(bc_StructNumber-1)) then
        set bc_StructNumber = bc_StructNumber-1
    else
        set bc_StructFreeNumber = bc_StructFreeNumber+1
        set bc_StructFreeStack[bc_StructFreeNumber] = this.position
    endif
    //! runtextmacro AMHS_DestroyStructShadow("this.u")
    set this.u = null
    set this.position = -1
    endmethod
endstruct

private function BuffManager takes nothing returns nothing
local unit u = GetEnumUnit()
local integer counter = 0
local integer lastbuffid = 0
local buffstruct bs
local buffcheck bc
local unitgraphic gp
loop
    if (bs_StructStack[counter]) > -1 then
        set bs = bs_StructStack[counter]

        if GetUnitAbilityLevel(u, bs.BuffID) == bs.Level and bs.BuffID != lastbuffid then
            set lastbuffid = bs.BuffID
            //! runtextmacro AMHS_GetStructBuff("u", "bc")
            if bc <= 0 then
                //! runtextmacro AMHS_GetStructUnitGraphic("u","gp")
                if bs.SizeDurationIncrease == 0 then
                    call gp.SetScale(gp.x + bs.x,gp.y + bs.y,gp.z + bs.z)
                endif
                set bc = buffcheck.Create(u,bs,gp)
                //! runtextmacro AMHS_StoreStructBuff("u", "bc")
            endif
        endif
    endif
    set counter = counter + 1
    exitwhen counter >= bs_StructNumber
endloop
endfunction

private function BuffEnumerator takes nothing returns nothing
local group g = CreateGroup()
local integer counter = 0
local buffcheck bc
local buffstruct bs
local unitgraphic gp
call GroupEnumUnitsInRect(g,bj_mapInitialPlayableArea,Condition(function AntiLeak))
call ForGroup(g,function BuffManager)
call DestroyGroup(g)
set g = null
loop
    if (bc_StructStack[counter]) > -1 then
        set bc = bc_StructStack[counter]
        set bs = bc.buffstructid
        set gp = bc.unitgraphicid
        set bc.timeelapsed = bc.timeelapsed + period
        if GetUnitAbilityLevel(bc.u, bs.BuffID) == bs.Level then
            if bs.Duration - bc.timeelapsed <= bs.SizeDurationIncrease then
                set bc.decreasing = true
            endif
            if bc.increasing == true then
                if (bc.counter != bs.increasecount) then
                    call gp.SetScale(gp.x + bs.increasex,gp.y + bs.increasey,gp.z + bs.increasez)
                    set bc.counter = bc.counter + 1
                else
                    set bc.increasing = false
                    set bc.counter = 0
                endif
            endif
            elseif (bc.decreasing == true) then
                if (bc.counter != bs.increasecount) then
                    call gp.SetScale(gp.x - bs.increasex,gp.y - bs.increasey,gp.z - bs.increasez)
                    set bc.counter = bc.counter + 1
                else
                    set bc.decreasing = false
                endif
        else
            call bc.destroy()
        endif
    endif
    set counter = counter + 1
    exitwhen counter >= bc_StructNumber
endloop    

endfunction

private function HideUnitOnDeath takes nothing returns nothing
    local shadow sh
    //! runtextmacro AMHS_GetStructShadow("GetTriggerUnit()","sh") 
    call sh.SetShadowVisibility(false)
    call sh.ChangeDeadUnit(true)
endfunction

function Trig_Shadow_Engine_Actions takes nothing returns nothing
    local timer t = CreateTimer()
    local timer t2 = CreateTimer()
    local integer i = 0
    local group tempgroup
    local trigger hideondeath
    //! runtextmacro AMHS_StructInitializeLine()
    if cachefirst then
        call InitializeDataCache()
        set cachefirst = false
    endif
    loop
        exitwhen i > 15
        set tempgroup = CreateGroup()
        call GroupEnumUnitsOfPlayer(tempgroup, Player(i), Filter( function AntiLeak))
        call ForGroup(tempgroup, function FinalGroup)
        call DestroyGroup(tempgroup)
        set tempgroup = null
        set i = i + 1
    endloop
    call ForGroup(g,function GroupAdder)
    call DestroyGroup(g)
    call TriggerRegisterEnterRectSimple(RegisterUnit, bj_mapInitialPlayableArea)
    call TriggerAddCondition(RegisterUnit, Condition (function TriggerAdder))
    call TimerStart(t,period,true,function ShadowGraphicManager)
    call TimerStart(t2,period,true, function BuffEnumerator)
    if hideshadowondeath then
        set hideondeath = CreateTrigger()
        call TriggerAddAction(hideondeath, function HideUnitOnDeath)
        call TriggerRegisterAnyUnitEventBJ(hideondeath, EVENT_PLAYER_UNIT_DEATH )
    endif
    set t = null
    set tempgroup = null
    set hideondeath = null
endfunction

//===========================================================================
function InitTrig_Fog_Protect_and_Shadow_Engine takes nothing returns nothing
    set gg_trg_Fog_Protect_and_Shadow_Engine = CreateTrigger(  )
    call TriggerRegisterTimerEventSingle(gg_trg_Fog_Protect_and_Shadow_Engine, 0.00)
    call TriggerAddAction( gg_trg_Fog_Protect_and_Shadow_Engine, function Trig_Shadow_Engine_Actions )
endfunction
endlibrary

MiniMap Protect

Unlike the other systems the MiniMap protect does not crash wc3, instead it prevents MH's from revealing unseen units on the MiniMap (the fog will be lifted but beneath the fog there wont be any units seen, only the terrain). This works by setting an alternate MiniMap Icon which is blank/invisible and then using local code the system cycles through each player and for every unit that player cannot see it applies this MiniMap icon so it cannot be seen on the MiniMap
Spoiler:

Code: Select all

library MiniMapProtectEngine needs ReplayDetectEngine
//*************************************************************************
//*                                                                       *                                         *
//*                       MINIMAP PROTECT ENGINE v3.10                    *
//*                    CONFIGURATION SETTINGS START HERE                  *                       *
//*                                                                       *                                          *
//*************************************************************************
globals
    // The MiniMap engine requires you to provide the path to the MiniMMap - Blank.blp file. This
    // shouldn't change in between maps if you use the default string, remember use '//' instead of
    // '/' (double dash instead of single dash).
    // As noted in the readme, its a very good idea to randomize the filename and the location
    // to the file.
    private constant string MiniMapPath = "HGVGWEO4NV\\435983460.blp"
    
    // This is the interval period used by the system. 0.025 should be the LOWEST value, anything
    // lower is pointless since 0.025 matches Wc3's maximum FPS (60 fp/s). If the system is
    // causing lag then you should increase it to a value between 0.025 and 0.05. Anything higher
    // then 0.05 is seriously not recommended since it will look visually choppy.
    // NOTE: The system is INCREDIBLY efficient and it uses the struct-loop system (no H2I/attach
    // methods are used for the timer interval) so in 99% of cases you should never have to increase
    // the period
    private constant real period = 0.025

//*************************************************************************
//*                                                                       *                                         *
//*                       MINIMAP PROTECT ENGINE v3.10                    *
//*                    CONFIGURATION SETTINGS END HERE                    *                       *
//*                                                                       *                                          *
//*************************************************************************
    
endglobals


globals
    private trigger RegisterUnit = CreateTrigger()
    private gamecache mm_datacache
    private gamecache mm_handlecache
    private boolean cachefirst = true
    real test = 0
    private group g = CreateGroup()
   //Stack for minimaphandler struct
    private integer array StructStack
    private integer array StructFreeStack
    private integer StructNumber = 0
    private integer StructFreeNumber = -1

endglobals

private function H2I takes handle h returns integer
return h
return 0
endfunction

private function InitializeHandleCache takes nothing returns nothing
call FlushGameCache(InitGameCache("mm_handlecache"))
set mm_handlecache=InitGameCache("mm_handlecache")
endfunction

private function InitializeDataCache takes nothing returns nothing
call FlushGameCache(InitGameCache("mm_datacache"))
set mm_datacache=InitGameCache("mm_datacache")
endfunction

//Public Functions
function GetUnitMiniMapIcon takes unit u returns integer
if u == null then
    return 0
else
    return GetStoredInteger(mm_handlecache,I2S(H2I(u)),"0")
endif
endfunction

struct minimapicon
    readonly boolean enabled = true
    readonly unit u
    readonly integer position //position in relation to struct stack
    
    static method Create takes unit u returns minimapicon
        local minimapicon mm = minimapicon.create()
        set mm.u = u
        if StructFreeNumber<0 then
            set mm.position = StructNumber
            set StructStack[StructNumber] = mm
            set StructNumber = StructNumber+1
        else
            set mm.position = StructFreeStack[StructFreeNumber]
            set StructStack[mm.position] = mm
            set StructFreeStack[StructFreeNumber] = -1
            set StructFreeNumber = StructFreeNumber-1
        endif
        call StoreInteger(mm_handlecache,I2S(H2I(mm.u)),"0",mm)
        return mm
    endmethod
    
    method SetMiniMapIconDisplay takes boolean enabled returns nothing
        set this.enabled = enabled
    endmethod
    
    method GetMiniMapIconDisplay takes nothing returns boolean
        return this.enabled
    endmethod
    
    method onDestroy takes nothing returns nothing
        set StructStack[this.position] = -1
        if (this.position>=(StructNumber-1)) then
            set StructNumber = StructNumber-1
        else
            set StructFreeNumber = StructFreeNumber+1
            set StructFreeStack[StructFreeNumber] = this.position
        endif   
        set this.position = -1
        call StoreInteger(mm_handlecache,I2S(H2I(this.u)),"0",0)
        set this.u = null
    endmethod
endstruct

//Public Functions
function RegisterMiniMapIconDisplay takes integer UnitID, boolean enabled returns nothing
local string s
if cachefirst then
    call InitializeDataCache()
    set cachefirst = false
endif
set s = UnitId2String(UnitID)
call StoreBoolean(mm_datacache,s,"exist",true)
call StoreBoolean(mm_datacache,s,"enabled",enabled)
endfunction

private function MiniMapManager takes nothing returns nothing
local integer i = 0
local minimapicon mm
local player p = GetLocalPlayer()
    loop
        set mm = StructStack[i]
        if integer(mm) > -1 then
            if GetUnitTypeId(mm.u) == 0 then
                call mm.destroy()
            else
                if IsUnitVisible(mm.u, p) then
                    if mm.enabled then
                        call UnitSetUsesAltIcon(mm.u,false)
                    else
                        call UnitSetUsesAltIcon(mm.u,true)
                    endif
                elseif InGame and GetLocalPlayer() == p then
                    call UnitSetUsesAltIcon(mm.u,true)
                endif
            endif
        endif
        set i = i + 1
        exitwhen i >= StructNumber
endloop
endfunction

private function AddUnits takes unit u returns nothing
local boolean enabled = true
local minimapicon mm
local string s
set s = UnitId2String(GetUnitTypeId(u))
if GetStoredBoolean(mm_datacache,s,"exist") == true then
    set enabled = GetStoredBoolean(mm_datacache,s,"enabled")
endif
set mm = minimapicon.Create(u)
endfunction

private function TriggerAdder takes nothing returns boolean
    call AddUnits(GetTriggerUnit())
    return true
endfunction

private function GroupAdder takes nothing returns nothing
    call AddUnits(GetEnumUnit())
endfunction

private function AntiLeak takes nothing returns boolean
    return true
endfunction

private function FinalGroup takes nothing returns nothing
    call GroupAddUnit(g,GetEnumUnit())
endfunction

private function Trig_MiniMap_Protect_Engine_Actions takes nothing returns nothing
    local timer t = CreateTimer()
    local integer i = 0
    local group tempgroup
    local trigger enginestart = GetTriggeringTrigger()
    call DestroyTrigger(enginestart)
    set enginestart=null
    call SetAltMinimapIcon(MiniMapPath)
    call InitializeHandleCache()
    if cachefirst then
        call InitializeDataCache()
        set cachefirst = false
    endif
    loop
        exitwhen i > 15
        set tempgroup = CreateGroup()
        call GroupEnumUnitsOfPlayer(tempgroup, Player(i), Filter( function AntiLeak))
        call ForGroup(tempgroup, function FinalGroup)
        call DestroyGroup(tempgroup)
        set tempgroup = null
        set i = i + 1
    endloop
    call ForGroup(g,function GroupAdder)
    call DestroyGroup(g)
    call TriggerRegisterEnterRectSimple(RegisterUnit, bj_mapInitialPlayableArea)
    call TriggerAddCondition(RegisterUnit, Condition (function TriggerAdder))
    call TimerStart(t,period,true,function MiniMapManager)
    set t = null
    set tempgroup = null
endfunction

    
public function StartPreload takes nothing returns nothing
    call Preload(MiniMapPath)
endfunction

//===========================================================================
function InitTrig_MiniMap_Protect_Engine takes nothing returns nothing
    set gg_trg_MiniMap_Protect_Engine = CreateTrigger(  )
    call TriggerRegisterTimerEventSingle( gg_trg_MiniMap_Protect_Engine, 0.00)
    call TriggerAddAction( gg_trg_MiniMap_Protect_Engine, function Trig_MiniMap_Protect_Engine_Actions )
endfunction

endlibrary

AddSpecialEffect Emulator

This is an emulator designed to replace AddSpecialEffect so that the FogProtect and Shadow Engine has the ability to pick up effects and hide them if they are not visible to a player (done by using AddSpecialEffectTarget on an invisible dummy unit)
Spoiler:

Code: Select all

library AddSpecialEffectEx
//*************************************************************************
//*                                                                       *                                         *
//*                       AddSpecialEffect EMULATOR v1.10                    *
//*                    CONFIGURATION SETTINGS START HERE                  *                       *
//*                                                                       *                                          *
//*************************************************************************
globals
    //This is the rawcode for the dummy unit, make sure you update it as it changes between
    //maps. Also make sure that the model file for the AMHS (Dummy Unit) is the dummy.mdx
    //file which you should have also imported into your map
    private integer Dummy_UnitId = 'h000'
    
    // This is the Maximum time of any spell effect. You must designate a default time, so the
    // system at one point can clean up the dummy units used. 15 seconds is a good amount
    //(I seriously doubt any spell effect will last longer then 10 seconds)
    private real MaxSpellEffectTime = 15
    
    // This is the interval period used by the system. 0.025 should be the LOWEST value, anything
    // lower is pointless since 0.025 matches Wc3's maximum FPS (60 fp/s). If the system is
    // causing lag then you should increase it to a value between 0.025 and 0.05. Anything higher
    // then 0.05 is seriously not recommended since it will look visually choppy.
    // NOTE: The system is INCREDIBLY efficient and it uses the struct-loop system (no H2I/attach
    // methods are used for the timer interval) so in 99% of cases you should never have to increase
    // the period
    private real period = 0.25
    
//*************************************************************************
//*                                                                       *                                         *
//*                       AddSpecialEffect EMULATOR v1.10                    *
//*                    CONFIGURATION SETTINGS END HERE                   *                       *
//*                                                                       *                                          *
//*************************************************************************
endglobals


globals
    private timer t
    private integer array StructStack
    private integer array StructFreeStack
    private integer StructNumber = 0
    private integer StructFreeNumber = -1
endglobals

struct specialeffectex
    string effectpath
    real timeout
    real x
    real y
    effect e
    unit u
    real customdeathtime = 0
    integer position
    
    static method Create takes string modelname, real x , real y, boolean showdeath, real customdeathtime returns specialeffectex
        local specialeffectex se = specialeffectex.create()
        set se.x = x
        set se.y = y
        set se.u = CreateUnit(Player(15),Dummy_UnitId,x,y,0)
        call SetUnitX(se.u,x)
        call SetUnitY(se.u,y)
        set se.effectpath = modelname
        if showdeath then
            call DestroyEffect(AddSpecialEffectTarget(modelname,se.u,"origin"))
        else
            set se.e = AddSpecialEffectTarget(modelname,se.u,"origin")
        endif
        set se.customdeathtime = customdeathtime
        set se.timeout = TimerGetElapsed(t)
        if StructFreeNumber<0 then
            set se.position = StructNumber
            set StructStack[StructNumber] = se
            set StructNumber = StructNumber+1
        else
            set se.position = StructFreeStack[StructFreeNumber]
            set StructStack[se.position] = se
            set StructFreeStack[StructFreeNumber] = -1
            set StructFreeNumber = StructFreeNumber-1
        endif
        return se
    endmethod
    
    method GetSpecialEffectExPath takes nothing returns string
        return this.effectpath
    endmethod
    
    method GetSpecialEffectExX takes nothing returns real
        return this.x
    endmethod
    
    method GetSpecialEffectExY takes nothing returns real
        return this.y
    endmethod
    
    method onDestroy takes nothing returns nothing
        set StructStack[this.position] = -1
        if (this.position>=(StructNumber-1)) then
            set StructNumber = StructNumber-1
        else
            set StructFreeNumber = StructFreeNumber+1
            set StructFreeStack[StructFreeNumber] = this.position
        endif   
        set this.position = -1
        call ShowUnit(this.u,false)
        call SetUnitExploded(this.u, true)
        call KillUnit(this.u)
        set this.u = null
        if this.e != null then
            call DestroyEffect(this.e)
        endif
        set this.e = null
    endmethod
    
    endstruct

function AddSpecialEffectEx takes string modelName, real x, real y returns integer
    local specialeffectex sf = specialeffectex.Create(modelName,x,y,false,0)
    return sf
endfunction

function AddSpecialEffectAdvancedEx takes string modelName, real x, real y, boolean ShowDestroy, real CustomDeathTime returns integer
    local specialeffectex sf = specialeffectex.Create(modelName,x,y,ShowDestroy,CustomDeathTime)
    return sf
endfunction

private function SpecialEffectExManager takes nothing returns nothing
local specialeffectex se
local integer counter = 0
local timer t = GetExpiredTimer()
loop
    if (StructStack[counter]) > -1 then
        set se = StructStack[counter]
        if se.customdeathtime != 0 then
            if (TimerGetElapsed(t) - se.timeout)  >= MaxSpellEffectTime then
                call se.destroy()
            endif
        else
             if (TimerGetElapsed(t) - se.timeout)  >= se.customdeathtime then
                call se.destroy()
            endif
        endif
    endif
    set counter = counter + 1
    exitwhen counter >= StructNumber
endloop
endfunction

function Trig_AddSpecialEffect_Emulator_Actions takes nothing returns nothing
    set t = CreateTimer()
    call TimerStart(t,period,true,function SpecialEffectExManager)
endfunction

//===========================================================================
function InitTrig_AddSpecialEffect_Emulator takes nothing returns nothing
    set gg_trg_AddSpecialEffect_Emulator = CreateTrigger(  )
    call TriggerRegisterTimerEventSingle( gg_trg_AddSpecialEffect_Emulator, 0.00 )
    call TriggerAddAction( gg_trg_AddSpecialEffect_Emulator, function Trig_AddSpecialEffect_Emulator_Actions )
endfunction
endlibrary
Changelog
Spoiler for hidden information:
v5.2
- Fixed how the system cleans up removed units and greatly increased its
efficiency (thanks to Strilac)
- Methods are now truely readonly, the members inside the shadow/unitgraphic/minimapicon structs cannot be changed apart from using the methods
- Fixed an issue with the minimap protect not working properly in multiplayer
- Added a feature which allows you to change the struct attachment system
used by AMHS (default is gamecache, so far you can use HSAS/PUI/HAIL
as an alternative)
- Added a feature that allowed you to register buffs which increase the unit scale
- Destructable Protect has been removed due to the fact that the system was so inefficient that it created lag in big maps. Although this was a problem with the systems fault, it was the only way to program the engine (unfortunatley there is no way of detecting when destructables are created apart from replacing all CreateDestructable instances with another function, this means that the system had to go through every destructable using H2I in an interval). It is unlikely the system will be re-introduced in the near future unless an alternate method is found
- A feature in Fog Protect and Shadow Engine has been added which disables shadows when a unit dies (this happens normally with Blizzards shadow engine). You however have to option to disable this or make a units shadow visible when dead using the SetShadowVisibility method
- The Manual has been updated with the recent changes
- Mentioned that if you specify an incorrect raw code the map crashes
- Added a GUI Installation explanation written by PIGGY to make it easier for the GUI users to use the system

v5.1
- A minor bug in AddSpecialEffect Emulator has been fixed
- Forgot to add the sentry ward in the test map to the Shadow Configuration

v5.00
- JassNewGen is REQUIRED for this version, and there will be no non JassNewGen releases
- Fog Crasher system has been deleted and changed. It has now been replaced with a much more reliable and effective Fog Protect Engine which works the same way MiniMap Protect works (preventing Map Hacks from revealing units on the minimap).
- Destructable Protect has been added, which works the exact same way as Mini Map protect
- This version adds a lot of functionality, giving you full control of unit shadows and many other things
- RE-READ EVERYTHING BECAUSE ALMOST EVERYTHING HAS CHANGED

v4.40
- Fixed an issue with the map randomly crashing due to FogDetect (it was an issue with the dummy unit)
- Since the DummyUnit has been changed and nothing else, to upgrade from v4.30 simply delete the old dummy unit and replace it with the new one in this map
- The test map lets you initialize all systems at once, as well as seperatly

v4.30
- When installing this version it is highly recommended that you fully delete the old system (including all triggers/global variables (start with AMHS) and the custom script section) however you don't need to delete the dummy unit or Splats\LightningData.slk or MiniMap-Blank.blp or modelcrash.mdx
- Readme's have been updated
- An issue with v4.10 not detecting replays anymore has been fixed (replay detect function has been recoded)
- An issue with MiniMap Protect not revealing the minimap icons of units after they were hidden has been fixed
- An issue with the corrupted model where it would only crash if it was rendered in screen view
- Due to this the Invis/FogDetect has been completely recoded and uses local code, for this reason in InvisDetect you no longer need to specify a point
- Forgot to mention how to initialize Minimap protect
- Added extra functionality for testing
- Improved and changed issues with the Disable functions, they have been remade and now you can disable the AMHS for a specific player, for each engine
- There is now a JassNewGen version, apart from being slightly more efficient it is much easier to install (you just copy the dimmy unit and the triggers, no need for custom script/required variable triggers)

v4.10
- Various fixes have been done from the previous version
- An issue with the point searching system in both the InvisDetect and FogDetect has been fixed
- Multiplayer problems have been fixed due to values not being synced (Fog detect no longer desyncs, InvisDetect works for all players and MiniMap protect works for all players)
- Mentioned that it is impossible to hide the "Pause Game" message created by the Replay detect function

v4.00
- NOTE: In this version it is HIGHLY recommended that you fully delete any old version of AMHS (including the variables) and then install the new system
- A very silly error that sometimes causes the map to unintentionally crash in certain situations has been fixed (FogDetect)
- The system now counters all the major features of all public Map Hacks (read MH List trigger)
- FogDetect has completely been reworked, now uses corrupted models (please read the readmes and configuration settings). It also uses a buffer and efficiency greatly improved
- InvisDetect has been completely reworked, now only uses corrupted models (please read the readmes and configuration settings), it is also much much more efficient so you can increase the buffer to insane levels
- The system no longer uses rectangles at all, it now uses points (read the readme's for more info)
- MiniMap detect has been introduced which prevents the Mini-Map from revealing units that are not visible
- 2 extra files need to be copied into your map, modelcrash.mdx (for both FogDetect/InvisDetect) and MiniMap-Blank.blp for MiniMap protect
- Test map has been greatly improved, in order to create test Units use computers (or real players). You can now test the systems seperatly to see how they work

v3.20
- This will be the last release before v4, which will contain pure jass methods of detecting MH and all MH's, not just the popular ones
- An issue with desyncs (only in replays, not in actualy gameplay) has been fixed
- Another issue with the map un-intentionally crashing when a flame-strike based spell is cast on trees in the area where the corrupted lightning is. This has been fixed, which means the FogDetect system also uses a buffer like InvisDetect (it no longer uses fog to conceal a visible point, it will search for another location on the map that is not visible to the player)
- A missing variable (AMHS_InGameOutPut) has been put into the Required Variable triggers
- Handle leaks have been fixed

v3.0
- THIS IS INCREDIBLY IMPORTANT. Since cinematic mode removes fog, it will cause the map to crash if you view the lightning rectangle. In the new version there is an option to enable/disable the Fog Detect and Invis Detect engines if you are in cinematic mode
- I recommend this version for public use, after extensive testing it seems all
bugs and desync problems have been fixed :)
- Now I really mean it, the function properly uses GetLocalPlayer method without desyncs, no dummy units and the function is a lot less noticable
- The InGameFunction is only called once to save on efficiency
- You now have a choice if you want to save replays at the cost of initializing
the replay engine which is very noticable (can be hidden if done during a cinematic)
- The readmes are generally clearer to understand
- Properly updated the Required Variable triggers (in previous version some
variables were missing)
- Quick Tips have been added to make it easier for people to install the system

v2.20
- The sync method used by the function to detect replays was too noticable in the game (dummy units and such could actually be seen), the function now uses GetLocalPlayer to sync the cameras properly

- The info in the map descriptions and loading screens have been fixed

v2.10
- Accidentally left a boolean named udg_temp in the map

- ExecuteFunc error in the Fog Detect engine caused the map to crash when
Fog Detect was initialized (fixed)

- the temp used to create the fog is now checked if it exists before destroyed

- Fixed what could be some possible leaks with the dummy units in InvisDetect

v2.00 (Major Changes This Version)
- Finally a 100% fail proof function was found that could detect replays, so the system is now compatible with replays even in multiplayer (thx heaps to Toad Cop, Captain Griffein and PyroGasm)
- Because of the replay detection function, when the engine's initilize they will create a very slight pause (which can be noticable in game play)
- The AMHS system has been seperated into different modules so not only is it a lot easier for myself to edit but also easier for users to modify the configuration settings
- Finally the InvisDetect system is fully functional and even more a hell of a lot more efficient, it searches manually for each force which means substancially less searches, which means you can have your buffer set to 20 and in 99% of situations it will never go higher. On the downside this means it has to create more units (handles), however previously in some situations there was a huge amount of lag because simply put a point wasn't found that satisfied all forces. This way the maximum amount of searches required is usually around 5, and for a few more units thats a very good invalid to pay

v1.20b
- The function to determine if the game was a replay does not work in multiplayer, in fact it disabled the system altogether in mutiplayer. Because of this the function has been removed which means yet again turning off fog in replays will cause Wc3 to crash (sorry)

v1.20
- A possible abuse for the replay bug has now been fixed (issue with full Gamecache)
- Efficiency of the map has increased (checks if player exists before executing code etc)
- Problem with InvisDetect system were it did more random checks then it needed to is now fixed


v1.10
- The replay bug is now fixed, you can view your map in replays even with Fog Of War turned off
- A new system that detects when maphack reveals invisible units (check the readme and configuration for more info

v1.00 Initial Release
NEEDED .7zip to extract the files
You do not have the required permissions to view the files attached to this post.
Image
User avatar
Risen
Forum Staff
Posts: 811
Joined: January 1st, 2008, 12:58 am

Re: AMHS (Anti Map Hack System)

Post by Risen »

I don't really see the point in using this now.. the script file is huge, and warden now operates..so it's pretty useless in most cases.
Image
Wanna learn to hack maps? --> Guide