HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Some Coding Feedback, please.

06-30-2010, 08:49 AM#1
KillStr34kz[MK]
So, i made a spell and wanted to check if it is possible to make faster and efficient. So here's the code. Im new here, so i dont really know where to post this.
You can choose the poll options. Good code, or Bad code.

Collapse JASS:
library StrengthAura initializer Init

globals
    // CLOSE_RANGE_BONUS = How much strength you get when in Close Range
    private constant integer    CLOSE_RANGE_BONUS       = 15
    // MEDIUM_RANGE_BONUS = How much strength you get when in Medium Range
    private constant integer    MEDIUM_RANGE_BONUS      = 10
    // LONG_RANGE_BONUS = How much strength you get when in Long Range
    private constant integer    LONG_RANGE_BONUS        = 5
    // CLOSE_RANGE = Indicates how long Close Range is.
    private constant real       CLOSE_RANGE             = 200
    // MEDIUM_RANGE = Indicates how long Medium Range is.
    private constant real       MEDIUM_RANGE            = 400
    // LONG_RANGE = Indicates how long Long Range is.
    private constant real       LONG_RANGE              = 600
    // FULL_STR = Should it Include Bonuses from strength gain??
    private constant boolean    FULL_STR                = TRUE
    // SPELL_ID = ...
    private constant integer    SPELL_ID                = 'A000'
    // BUFF_ID = ...
    private constant integer    BUFF_ID                 = 'B000'
    // TIMERTICK = Every X seconds ticks, checking and adding strength. ( A tip, dont have it below 0.05.
    private constant real       TIMERTICK               = .05
    
//Dont Touch. Just dont do it.
//**==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*=|
/*          */private real globX                        //=|
/*          */private real globY                        //=|
/*          */private group tmpGrp = CreateGroup()      //=|
/*          */private unit picked                       //=|
/*          */private unit Owner                        //=|
/*          */private timer ti                          //=|
/*          */private hashtable table = InitHashtable() //=|
/*          */private unit array HeroWithAura           //=|
/*          */private integer HeroWithAuraCount = 0     //=|
//**==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*=|
endglobals

private constant function TYPES takes nothing returns boolean
return IsUnitType(picked, UNIT_TYPE_HERO) and not/* Picked unit is a Hero
    */ IsUnitType(picked, UNIT_TYPE_ANCIENT) and not/* The picked unit is not an Ancient
    */ IsUnitType(picked, UNIT_TYPE_ETHEREAL) and not/* The picked unit is not etheral
    */ IsUnitType(picked, UNIT_TYPE_MAGIC_IMMUNE) and not/* The picked unit is not magic immune
    */ IsUnitType(picked, UNIT_TYPE_SUMMONED) and/* The picked unti is Not summoned
    */ IsUnitInGroup(picked, tmpGrp) // And the picked unit is in the group.
endfunction

private constant function CLOSE takes integer lvl returns integer
    return 15 * lvl
endfunction

private constant function MEDIUM takes integer lvl returns integer
    return 10 * lvl
endfunction

private constant function FAR takes integer lvl returns integer
    return 5 * lvl
endfunction
//==================================================================================================================

private struct Data
    private real x
    private real y
    private real range
    private real xx
    private real yy
    private real r
    private unit Enum

   private method ApplyBonus takes unit u, integer bonus returns nothing
    //As name, the function used to add bonuses.
        if HaveSavedInteger(table, GetHandleId(u), 1) then
            call SetHeroStr(u, GetHeroStr(u, FULL_STR)-LoadInteger(table, GetHandleId(u), 1), FULL_STR)
            if bonus == 0 then
                call RemoveSavedInteger(table, GetHandleId(u), 1)
            else
                call SaveInteger(table, GetHandleId(u), 1, bonus)
            endif
        else
            if bonus != 0 then
                call SaveInteger(table, GetHandleId(u), 1, bonus)
            endif
        endif
        call SetHeroStr(u, GetHeroStr(u, FULL_STR)+bonus, FULL_STR)
endmethod

    static method GetUnitAuraBonus takes unit u returns integer 
        //This function "checks" where the unit is, and adds bonus after that condition
        local integer i = 0
        local integer m = 0
        loop
            exitwhen i == HeroWithAuraCount
            if IsUnitInRange(u, HeroWithAura[i], LONG_RANGE) then
            
                if IsUnitInRange(u, HeroWithAura[i], CLOSE_RANGE) then
                    if CLOSE(GetUnitAbilityLevel(HeroWithAura[i],SPELL_ID)) > m then
                        set m = CLOSE(GetUnitAbilityLevel(HeroWithAura[i],SPELL_ID))
                    endif
                elseif IsUnitInRange(u, HeroWithAura[i], MEDIUM_RANGE) then
                    if MEDIUM(GetUnitAbilityLevel(HeroWithAura[i],SPELL_ID)) > m then
                        set m = MEDIUM(GetUnitAbilityLevel(HeroWithAura[i],SPELL_ID))
                    endif
                elseif IsUnitInRange( u ,HeroWithAura[i], LONG_RANGE) then
                    if FAR(GetUnitAbilityLevel(HeroWithAura[i],SPELL_ID)) > m then
                        set m = FAR(GetUnitAbilityLevel(HeroWithAura[i],SPELL_ID))
                    endif
                endif
            endif
            set i = i + 1
        endloop
        return m
    endmethod

    static method loopFuncEnum takes nothing returns nothing
        local thistype this = allocate()
        set Enum = GetEnumUnit()
        call ApplyBonus(Enum, GetUnitAuraBonus(Enum)) //Applies the bonus.
    endmethod
    
endstruct

//==================================================================================================================

private function onLearn takes nothing returns nothing
        set HeroWithAura[HeroWithAuraCount] = GetTriggerUnit()
        set HeroWithAuraCount = HeroWithAuraCount + 1
endfunction

//==================================================================================================================

private function hasBuff takes nothing returns boolean
    return GetUnitAbilityLevel(GetFilterUnit(), BUFF_ID) > 0
    // Filter, which picks all units in the range Which has the buff.
endfunction

//==================================================================================================================

private function Conditions takes nothing returns boolean
    return GetLearnedSkill() == SPELL_ID
    // Gets the Learned Skill.
endfunction

//==================================================================================================================
private function doLoop takes nothing returns nothing
        local rect r = GetWorldBounds()
        call ForGroup(tmpGrp, function Data.loopFuncEnum)
        call GroupEnumUnitsInRect(tmpGrp, r, Filter(function hasBuff))
        call ForGroup(tmpGrp, function Data.loopFuncEnum)
        call RemoveRect(r)
        set r = null
endfunction
//==================================================================================================================
//==================================================================================================================
    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i = 0
        set ti = CreateTimer()
        call TimerStart( ti , TIMERTICK , true , function doLoop )
        //==========================================================
            loop
                exitwhen i == 16
                    call TriggerRegisterPlayerUnitEvent( t , Player(i) , EVENT_PLAYER_HERO_SKILL , null )
                set i = i + 1
            endloop
        call TriggerAddCondition( t , Condition(function Conditions ))
        call TriggerAddAction( t , function onLearn )
        //===========================================================
            
endfunction
//==================================================================================================================
//==================================================================================================================
endlibrary

Thanks

KillStr34kz[MK]
07-04-2010, 04:05 PM#2
Anitarf
The code really doesn't need to run so often, you could multiply TIMERTICK by 10 and players wouldn't really notice any difference. The WC3 auras themselves already update very rarely. Apart from that, the code seems reasonably efficient. It would likely be better if you enumerated units in range of each hero instead of enumerating the entire map, though.

I think this could be further improved to require less code execution if you moved away from checking for a buff from an in-game aura and instead triggered the aura completely. The aura module of my ABuff system does that quite elegantly.