Sign in to follow this  
Followers 0
Smorg

Proper code style.

5 posts in this topic

What is the most correct way to modify a variable through a function under various conditions? Usually when i am feeding a function some paramaters i will use a regular return to give the function's result back to the variable I want. However, what if i want to return multiple parts to multiple variables? its not very efficient to run the whole function twice just to give say, an x & y to two variables for instance. In this case i will sometimes return an array, but then after the array is returned i still need a few extra lines to convert that array back into two separate variables.

Is it generally considered okay to just assign a global variable within a function rather than using a return at all? This is particularly easy to do when the returned variable is never used as a function paramater but is simply the result of the function.

I am also confused as to the usage of ByRef... What is it exactly? After re-reading this sentance several times my head was spinning... "The ByRef keyword is optional and means: (1) the parameter must a variable, and (2) the variable could be changed by the function. By default, a parameter is passed by value which means that a copy of the parameter's value is manipulated by the function." (seems to be the only reference to byref in the manual)

This is my specific application... This is a script for tracking life for the game diablo II. d2 uses vertical bars as life indicators. The bars are actually textured and shaded so i read each base pixel of the full bar to a reference file which is then read to arrays and matched up with the current bar status. The script tracks the movments of the top edge of the bar to determine a percent life remaining. It can then use this info to automatically heal itself and can exit the game as a last ditch if it gets too low.

Take a look at the Func GetLife($Direction). Since it seems you can't conditionally declare loops since i get a bunch of 'next without corresponding for' blah, the whole thing had to be copied for one to step forwards, and the other step backwards. As you can see since several variables are conditionally modified, I can't very well return the result to a var. And the paramater is already used up by the $direction, so it wouldn't make much sense to add more paramaters to return from...

Whole script:

;------------------------------------------------
;----------------PotThread by Smorg--------------
;------------------------------------------------
;Version 3.0
;#NoTrayIcon
#Include <Array.au3>
opt("PixelCoordMode", 2)
opt("MouseCoordMode", 2)
opt("ColorMode", 1)
WinActivate("Diablo II")
WinMove("Diablo II", "", 0, 0)
;------------------------------------------------
;User Vars
$ExtraDebug = "No"                               ;Show Extra pixel info, for debugging purposes only
$File = "OrbReference.ini"                       ;Pixel Reference file to read from
$Top = IniRead($File, "Stats", "Top", "")        ;Top of the health/mana orbs
$Bottom = IniRead($File, "Stats", "Bottom", "")  ;Bottom of the health/mana orbs
$HealthX = IniRead($File, "Stats", "Health", "") ;Xcoord to scan the health orb
$ManaX = IniRead($File, "Stats", "Mana", "")     ;Xcoord to scan the mana orb
$BeltX = 437                                     ;Left Belt Slot pixel reference
$BeltY = 582                                     ;Left Belt Slot pixel reference
$MercBarLeft = 15                                ;Left side of the merc bar
$MercBarRight = 60                               ;Right side of the merc bar
$MercBarY = 18                                   ;Merc bar Y coord
$beltfrjchecksum = 713163619                     ;belt checksum for full rejuvs
$beltrjchecksum = 1805125736                     ;belt checksum for regular rejuvs
$ChickenTimeout = 1000                           ;Time to wait for sucessful chicken before retrying
$ChickenRetries = 3                              ;Times to retry chicken
Global $HealthRef[ ($Bottom - $Top) + 1]         ;Array to conatin health color data read from the ini file
Global $ManaRef[ ($Bottom - $Top) + 1]           ;Array to contain mana color data read from the ini file
Global $PsnRef[ ($Bottom - $Top) + 1]            ;Poisoned Health Color data
Global $BeltData[4]                              ;Potions info. 0 = no pot, 1 = full rejuv pot, 2 = regular rejuv pot
Dim $DrinkType                                   ;Type of drink. 0 = Regular rejuv, 1 = Full rejuv, 2 = Merc
Dim $LifePercent                                 ;The returned percent from the health orb
Dim $ManaPercent                                 ;The returned percent from the mana orb
Dim $HealthPixel                                 ;Current Health Pixel y coord
Dim $HealthColor                                 ;Health pixelcolor result to check against healthref and psnref
Dim $ManaPixel                                   ;Current Mana Pixel y coord
Dim $MercPercent                                 ;Percent health remaining calculated from the merc bar
Dim $MercPixel                                   ;Current merc bar pixel
Dim $MercColor                                   ;Current merc bar color
Dim $Check                                       ;Belt checksum result
Dim $Char_Key_PotionsRow[5]                      ;Potion drink keys
Dim $Timer = 0                                   ;Timer flag, weather or not the drink timer is active
Dim $Sleep                                       ;Drink Delay Timestamp
;------------------------------------------------
;Importing Vars
$CurrentDir = StringSplit(@ScriptDir, "\")
_ArrayPop($CurrentDir)
$BotDir = $CurrentDir[1]

For $Rebuild = 2 to ($CurrentDir[0] - 1)
    $BotDir = $BotDir & "\" & $CurrentDir[$Rebuild]
Next

$Char_Key_PotionsRow[1] = IniRead($BotDir & "\Config\mm.BOT.ini", "Character", "Char_Key_PotionsRow1", "")
$Char_Key_PotionsRow[2] = IniRead($BotDir & "\Config\mm.BOT.ini", "Character", "Char_Key_PotionsRow2", "")
$Char_Key_PotionsRow[3] = IniRead($BotDir & "\Config\mm.BOT.ini", "Character", "Char_Key_PotionsRow3", "")
$Char_Key_PotionsRow[4] = IniRead($BotDir & "\Config\mm.BOT.ini", "Character", "Char_Key_PotionsRow4", "")
$PauseBot = IniRead($BotDir & "\Config\mm.BOT.ini", "Advanced Settings", "Bot_PAUSE_HotKey", "")
$PauseBot = "{" & $PauseBot & "}"
$ClearScreen = IniRead($BotDir & "\Config\mm.BOT.ini", "Character", "Char_Key_ClearScreen", "")
$ClearScreen = "{" & $ClearScreen & "}"
$D2WinTitle = IniRead($BotDir & "\Config\mm.BOT.ini", "Advanced Settings", "D2_WName", "")
$LifeRpotDrinkPercent = IniRead($BotDir & "\Config\mm.LifeCheck.ini", "Settings", "Rpot_Life_Percent", "")
$LifeFpotDrinkPercent = IniRead($BotDir & "\Config\mm.LifeCheck.ini", "Settings", "FRJ_Life_Percent", "")
$ManaRpotDrinkPercent = IniRead($BotDir & "\Config\mm.LifeCheck.ini", "Settings", "Rpot_Mana_Percent", "")
$ManaFpotDrinkPercent = IniRead($BotDir & "\Config\mm.LifeCheck.ini", "Settings", "FRJ_Mana_Percent", "")
$ChickenPercent = IniRead($BotDir & "\Config\mm.LifeCheck.ini", "Settings", "Chicken_Percent", "")
$ScanDelay = IniRead($BotDir & "\Config\mm.LifeCheck.ini", "Settings", "Scan_Delay", "")
$DrinkDelay = IniRead($BotDir & "\Config\mm.LifeCheck.ini", "Settings", "Drink_Delay", "")
$MaxLife = IniRead($BotDir & "\Config\mm.LifeCheck.ini", "Settings", "Max_Life", "")
$MaxMana = IniRead($BotDir & "\Config\mm.LifeCheck.ini", "Settings", "Max_Mana", "")
$UseMerc = IniRead($BotDir & "\Config\mm.LifeCheck.ini", "Merc", "Use_Merc", "")
$MercChicken = IniRead($BotDir & "\Config\mm.LifeCheck.ini", "Merc", "Merc_Chicken", "")
$MercHealPercent = IniRead($BotDir & "\Config\mm.LifeCheck.ini", "Merc", "Merc_Heal_Percent", "")
$MercChickenPercent = IniRead($BotDir & "\Config\mm.LifeCheck.ini", "Merc", "Merc_Chicken_Percent", "")

;Build arrays from OrbReference.ini
For $Health = 0 To $Bottom - $Top
    $HealthRef[$Health] = IniRead($File, "Health", $Health, "")
Next

For $Mana = 0 To $Bottom - $Top
    $ManaRef[$Mana] = IniRead($File, "Mana", $Mana, "")
Next

For $Psn = 0 To $Bottom - $Top
    $PsnRef[$Psn] = IniRead($File, "Psn", $Psn, "")
Next
;------------------------------------------------
GetBaseStats()
If $UseMerc = "No" Then $MercPercent = "None"
While 1
    Sleep($ScanDelay)
    If PixelGetColor(481, 535) <> 5406092 Then
        If (PixelGetColor(320, 537) <> 6521492) OR (WinActive($D2WinTitle) = 0) Then SuspendCheck()
    EndIf
    
    ;Check if life has moved either up or down
    $HealthColor = PixelGetColor($HealthX, $HealthPixel)
    If ($HealthColor <> $HealthRef[$HealthPixel - $Top]) And ($HealthColor <> $PsnRef[$HealthPixel - $Top]) Then
        GetLife("down")
    ElseIf $LifePercent <> 100 Then
        $HealthColor = PixelGetColor($HealthX, $HealthPixel - 1)
        If ($HealthColor = $HealthRef[ ($HealthPixel - $Top) - 1]) Or ($HealthColor = $PsnRef[ ($HealthPixel - $Top) - 1]) Then GetLife("up")
    EndIf
    
    ;Check if mana has moved either up or down
    If PixelGetColor($ManaX, $ManaPixel) <> $ManaRef[$ManaPixel - $Top] Then
        GetMana("down")
    ElseIf $ManaPercent <> 100 Then
        If PixelGetColor($ManaX, $ManaPixel - 1) = $ManaRef[ ($ManaPixel - $Top) - 1] Then GetMana("up")
    EndIf
    
    ;Check if merc's life has changed & merc chicken check
    If $UseMerc = "Yes" Then
        If PixelGetColor($MercPixel, $MercBarY) = 0 Then
            GetMerc("down")
        ElseIf $MercPercent <> 100 Then
            If PixelGetColor($MercPixel + 1, $MercBarY) <> 0 Then GetMerc("up")
        EndIf
        If ($MercPercent < $MercChickenPercent) And $MercChicken = "Yes" Then Chicken()
    EndIf
    
    ;Drink pots, Chicken, and tooltip
    If $LifePercent < $ChickenPercent Then Chicken()
    If $Timer = 1 And TimerDiff($Sleep) > $DrinkDelay Then $Timer = 0
    If $Timer = 0 Then
        Select
            Case $LifePercent < $LifeRpotDrinkPercent And $LifePercent > $LifeFpotDrinkPercent
                Drink(1)
            Case $LifePercent < $LifeFpotDrinkPercent
                Drink(0)
            Case $ManaPercent < $ManaRpotDrinkPercent And $ManaPercent > $ManaFpotDrinkPercent
                Drink(1)
            Case $ManaPercent < $ManaFpotDrinkPercent
                Drink(0)
            Case ($MercPercent < $MercHealPercent) And $UseMerc = "Yes"
                Drink(2)
        EndSelect
    EndIf
WEnd

Exit (1)

Func GetLife($Direction)
    Select
        Case $Direction = "up"
            For $Search = $HealthPixel - $Top To 0 Step - 1
                $HealthColor = PixelGetColor($HealthX, $Search + $Top)
                If ($HealthColor <> $HealthRef[$Search]) And ($HealthColor <> $PsnRef[$Search]) Or $Search = 0 Then
                    Global $LifePercent = Round(100 * (($Bottom - ($Search + $Top)) / ($Bottom - $Top)))
                    If $Search = 0 Then
                        Global $HealthPixel = $Top
                    Else
                        Global $HealthPixel = $Search + $Top + 1
                    EndIf
                    ExitLoop
                EndIf
            Next
        Case $Direction = "down"
            For $Search = $HealthPixel - $Top To $Bottom - $Top
                $HealthColor = PixelGetColor($HealthX, $Search + $Top)
                If ($HealthColor = $HealthRef[$Search]) Or ($HealthColor = $PsnRef[$Search]) Or $Search = $Bottom - $Top Then
                    Global $LifePercent = Round(100 * (($Bottom - ($Search + $Top)) / ($Bottom - $Top)))
                    Global $HealthPixel = $Search + $Top
                    ExitLoop
                EndIf
            Next
    EndSelect
    ShowTip()
EndFunc   ;==>GetLife

Func GetMana($Direction)
    Select
        Case $Direction = "up"
            For $Search = $ManaPixel - $Top To 0 Step - 1
                If (PixelGetColor($ManaX, $Search + $Top) <> $ManaRef[$Search]) Or $Search = 0 Then
                    Global $ManaPercent = Round(100 * (($Bottom - ($Search + $Top)) / ($Bottom - $Top)))
                    If $Search = 0 Then
                        Global $ManaPixel = $Top
                    Else
                        Global $ManaPixel = $Search + $Top + 1
                    EndIf
                    ExitLoop
                EndIf
            Next
        Case $Direction = "down"
            For $Search = $ManaPixel - $Top To $Bottom - $Top
                If (PixelGetColor($ManaX, $Search + $Top) = $ManaRef[$Search]) Or $Search = $Bottom - $Top Then
                    Global $ManaPercent = Round(100 * (($Bottom - ($Search + $Top)) / ($Bottom - $Top)))
                    Global $ManaPixel = $Search + $Top
                    ExitLoop
                EndIf
            Next
    EndSelect
    ShowTip()
EndFunc   ;==>GetMana

Func GetMerc($Direction)
    Select
        Case $Direction = "up"
            For $Search = $MercPixel To $MercBarRight
                If (PixelGetColor($Search, $MercBarY) = 0) Or $Search = $MercBarRight Then
                    Global $MercPercent = Round(100 * (($Search - $MercBarLeft) / ($MercBarRight - $MercBarLeft)))
                    If $Search = $MercBarRight Then
                        Global $MercPixel = $MercBarRight
                    Else
                        Global $MercPixel = $Search - 1
                    EndIf
                    ExitLoop
                EndIf
            Next
        Case $Direction = "down"
            For $Search = $MercPixel To $MercBarLeft Step - 1
                If (PixelGetColor($Search, $MercBarY) <> 0) Or $Search = $MercBarLeft Then
                    Global $MercPercent = Round(100 * (($Search - $MercBarLeft) / ($MercBarRight - $MercBarLeft)))
                    Global $MercPixel = $Search
                    ExitLoop
                EndIf
            Next
    EndSelect
    ShowTip()
EndFunc   ;==>GetMerc

Func GetBaseStats()
    Global $HealthPixel = $Top
    Global $ManaPixel = $Top
    Global $MercPixel = $MercBarRight
    GetLife("down")
    GetMana("down")
    If $UseMerc = "Yes" Then GetMerc("down")
EndFunc   ;==>GetBaseStats

Func ShowTip()
    If $ExtraDebug = "No" Then
        ToolTip("Life: " & Round($MaxLife * ($LifePercent / 100)) & " / " & $MaxLife & " - " & Round($LifePercent) & "%" & @CRLF _
                 & "Mana: " & Round($MaxMana * ($ManaPercent / 100)) & " / " & $MaxMana & " - " & Round($ManaPercent) & "%" & @CRLF _
                 & "Merc: " & Round($MercPercent) & "%", 252, 578)
    ElseIf $ExtraDebug = "Yes" Then
        ToolTip("Life: " & $MaxLife * ($LifePercent / 100) & " / " & $MaxLife & " - " & $LifePercent & "%" & @CRLF _
                 & "Mana: " & $MaxMana * ($ManaPercent / 100) & " / " & $MaxMana & " - " & $ManaPercent & "%" & @CRLF _
                 & "Merc: " & $MercPercent & "%" & @CRLF _
                 & "HealthPix: " & $HealthPixel - $Top & " ManaPix: " & $ManaPixel - $Top & @CRLF _
                 & "MercPix: " & $MercPixel, 252, 578)
    EndIf
EndFunc   ;==>ShowTip

Func Drink($DrinkType)
    For $N = 0 To 3
        $Check = PixelChecksum(($BeltX + ($N * 31)) - 1, $BeltY - 1, ($BeltX + ($N * 31)) + 1, $BeltY + 1, 1)
        If $Check = $beltfrjchecksum Then
            $BeltData[$N] = 1
        ElseIf $Check = $beltrjchecksum Then
            $BeltData[$N] = 2
        Else
            $BeltData[$N] = 0
        EndIf
    Next
    $A = 0
    Select
        Case $DrinkType = 0                      ;Prioritize regular rejuves
            For $N = 0 To 3
                If $BeltData[$N] = 1 Then
                    Send($Char_Key_PotionsRow[$N + 1])
                    $A = 1
                    ExitLoop
                EndIf
            Next
            If $A = 0 Then
                For $N = 0 To 3
                    If $BeltData[$N] = 2 Then
                        Send($Char_Key_PotionsRow[$N + 1])
                        $A = 1
                        ExitLoop
                    EndIf
                Next
            EndIf
            If $A = 0 Then Chicken()
        Case $DrinkType = 1                      ;Prioritize Full rejuves
            For $N = 0 To 3
                If $BeltData[$N] = 2 Then
                    Send($Char_Key_PotionsRow[$N + 1])
                    $A = 1
                    ExitLoop
                EndIf
            Next
            If $A = 0 Then
                For $N = 0 To 3
                    If $BeltData[$N] = 1 Then
                        Send($Char_Key_PotionsRow[$N + 1])
                        $A = 1
                        ExitLoop
                    EndIf
                Next
            EndIf
            If $A = 0 Then Chicken()
        Case $DrinkType = 2                      ;Send a pot to the merc, Prioritize regular rejuves
            Send("{SHIFTDOWN}")
            For $N = 0 To 3
                If $BeltData[$N] = 2 Then
                    Send($Char_Key_PotionsRow[$N + 1])
                    $A = 1
                    ExitLoop
                EndIf
            Next
            If $A = 0 Then
                For $N = 0 To 3
                    If $BeltData[$N] = 1 Then
                        Send($Char_Key_PotionsRow[$N + 1])
                        $A = 1
                        ExitLoop
                    EndIf
                Next
            EndIf
            Send("{SHIFTUP}")
            If $A = 0 Then Chicken()
    EndSelect
    Global $Sleep = TimerInit()
    Global $Timer = 1
    GetBaseStats()
EndFunc   ;==>Drink

Func Chicken()
    ToolTip("")
    Send($PauseBot)
    For $Retries = 1 To $ChickenRetries
        Send($ClearScreen)
        MouseUp("Right")
        MouseUp("Left")
        Send("{ESC}")
        $Timeout = TimerInit()
        While 1
            If (PixelGetColor(481, 535) <> 5406092) AND (PixelGetColor(320, 537) <> 6521492) Then 
                ExitLoop
            ElseIf TimerDiff($Timeout) > 500 Then
                ContinueLoop 2
            EndIf
            Sleep(100)
        WEnd
        MouseClick("Left", 400, 280, 1, 0)
        $Timeout = TimerInit()
        While TimerDiff($Timeout) < $ChickenTimeout
            If (PixelGetColor(600, 575) <> 6512995) AND (PixelGetColor(5, 575) <> 2697257) Then ExitLoop 2
            Sleep(100)
        WEnd
    Next
    Send($PauseBot)
    SuspendCheck()
EndFunc   ;==>Chicken

Func SuspendCheck()
    ToolTip("")
    Do
        Sleep(100)
        If WinExists($D2WinTitle) = 0 Then Exit
    Until ((PixelGetColor(481, 535) = 5406092) OR (PixelGetColor(320, 537) = 6521492)) AND (WinActive($D2WinTitle) = 1)
    ShowTip()
EndFunc   ;==>SuspendCheck

Also it seems Select-Case is buggy. A lot of times boolean conditions mess up and don't work with select case, but the same identical thing works with If statements...

Share this post


Link to post
Share on other sites



Personally I don't know why you need to use Return. In every case where I've created a function I just assign the variable(s) within the function and than use them after the function is done. Am I missing something?

As to the issues with Select-Case v. If, I haven't run into the issue you describe, but I've only used Case-Select a few times...


...by the way, it's pronounced: "JIF"... Bob Berry --- inventor of the GIF format

Share this post


Link to post
Share on other sites

Personally I don't know why you need to use Return. In every case where I've created a function I just assign the variable(s) within the function and than use them after the function is done. Am I missing something?

As to the issues with Select-Case v. If, I haven't run into the issue you describe, but I've only used Case-Select a few times...

If you do that, you force your variables to be global...I try to keep my Function Variables Unique and Local as much as possible. This a good reason to use Return.

[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

Right thats the problem. Vars within functions are isolated unless global, which can normally be a good thing unless you run into a situation like this.

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

If you desire to modify multiple variables from within a function, the preferred method is usually by using the ByRef keyword for the variables in question. This allows the original variable(s) to be modified, without forcing said variable(s) to be global in scope.

While global variables are very useful - for assigning constants and other items that are truly Global in nature, in professional code development they are "bad things" in practice -- unexpected (and hard to debug) things happen when you call a function in a loop incrementing $i ; and the called function or a called function of the called function has another loop in it; incrementing or decrementing $i .

While this is a manageable problem if you're the only developer on a one or two file project; it becomes very difficult to control and debug with a multiplicity of developers and hundreds or thousands of files, and thousands or tens of thousands of lines of code.

Edited by flyingboz

Reading the help file before you post... Not only will it make you look smarter, it will make you smarter.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0