Increase Hero's Strength; No Stacking

Discussion in 'JASS Zone' started by WolfieeifloW, Jun 17, 2011.

  1. WolfieeifloW

    WolfieeifloW WEHZ Helper

    Ratings:
    +372 / 0 / -0
    Hey there!, I have two questions today TH.net (Yay :rolleyes:)!
    My first, is to 'fix' this trigger I have.

    I have a passive spell that has a chance on attacking to increase Strength by 15% for 5 seconds.
    I've found one of my old spells, and re-learned timers (I think :p).

    The Strength increase works great, but if the spell procs again, it just increases the hero's Strength further (30%).
    Whereas I only want the heroes Strength to be able to increase a maximum of 15%.

    How would I go about changing this to only allow a maximum of 15%?
    I've thought of a few different ways, but I want to see what other people think.
    I'd like a method that is easy (Coding wise, prefer not to add 100 variables or something), and efficient (Not as important).
    Here's my code:
    JASS:
    scope ROTFC initializer ROTFCInit
    
        globals
            private constant string rotfcString = "innerfire"
        endglobals
        
        private struct data
            unit attacker
            unit dummy
            integer str
            timer t
            
            method onDestroy takes nothing returns nothing
                call ReleaseTimer(.t)
            endmethod
        endstruct
    
        private function Chance takes integer level returns integer
            return 100//level * 1
        endfunction
        
        private function RemoveStr takes nothing returns nothing
            local data d = GetTimerData(GetExpiredTimer())
            
            call BJDebugMsg("Running!")
            call SetHeroStr(d.attacker, d.str, true)
            call d.destroy()
        endfunction
        
        private function Conditions takes nothing returns boolean
            local data d = data.create()
            set d.attacker = GetAttacker()
            set d.str = GetHeroStr(d.attacker, true)
                    
            if (GetUnitAbilityLevel(d.attacker, rotfc) > 0 and GetRandomInt(0, 100) <= Chance(GetUnitAbilityLevel(d.attacker, rotfc))) then
                call BJDebugMsg(I2S(R2I(d.str * 1.15)))
                set d.dummy = CreateUnit(GetOwningPlayer(d.attacker), dummyID, GetUnitX(d.attacker), GetUnitY(d.attacker), bj_UNIT_FACING)
                call UnitAddAbility(d.dummy, rotfcBuff)
                call SetUnitAbilityLevel(d.dummy, rotfcBuff, 1)
                call IssueTargetOrder(d.dummy, rotfcString, d.attacker)
                call UnitApplyTimedLife(d.dummy, 'BTLF', 0.01)
                call SetHeroStr(d.attacker, R2I(d.str * 1.15), false)
                set d.t = NewTimer()
                call SetTimerData(d.t, d)
                call TimerStart(d.t, 5., false, function RemoveStr)
            endif
            return false
        endfunction
        
    
        private function ROTFCInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            local integer index = 0
            
            loop
                call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_ATTACKED, null)
                set index = index + 1
                exitwhen index == bj_MAX_PLAYER_SLOTS
            endloop
            call TriggerAddCondition(t, Condition(function Conditions))
            set t = null
        endfunction
        
    endscope


    Also, for my second question.
    I've only relearned structs/timers a bit ago, so I'm asking if someone can give me any pointers to optimize/fix my code up.
     
  2. WolfieeifloW

    WolfieeifloW WEHZ Helper

    Ratings:
    +372 / 0 / -0
    Hmm, I just had another thought after I posted this.
    Using a boolean.
    Here's how I changed it:
    JASS:
    scope ROTFC initializer ROTFCInit
    
        globals
            private constant string rotfcString = "innerfire"
            private boolean inc = false
        endglobals
        
        private struct data
            unit attacker
            unit dummy
            integer str
            timer t
            
            method onDestroy takes nothing returns nothing
                call ReleaseTimer(.t)
            endmethod
        endstruct
    
        private function Chance takes integer level returns integer
            return 100//level * 1
        endfunction
        
        private function RemoveStr takes nothing returns nothing
            local data d = GetTimerData(GetExpiredTimer())
            
            call SetHeroStr(d.attacker, d.str, true)
            set inc = false
            call d.destroy()
        endfunction
        
        private function Conditions takes nothing returns boolean
            local data d = data.create()
            set d.attacker = GetAttacker()
            set d.str = GetHeroStr(d.attacker, true)
                    
            if (GetUnitAbilityLevel(d.attacker, rotfc) > 0 and GetRandomInt(0, 100) <= Chance(GetUnitAbilityLevel(d.attacker, rotfc)) and inc == false) then
                set inc = true
                set d.dummy = CreateUnit(GetOwningPlayer(d.attacker), dummyID, GetUnitX(d.attacker), GetUnitY(d.attacker), bj_UNIT_FACING)
                call UnitAddAbility(d.dummy, rotfcBuff)
                call SetUnitAbilityLevel(d.dummy, rotfcBuff, 1)
                call IssueTargetOrder(d.dummy, rotfcString, d.attacker)
                call UnitApplyTimedLife(d.dummy, 'BTLF', 0.01)
                call SetHeroStr(d.attacker, R2I(d.str * 1.15), false)
                set d.t = NewTimer()
                call SetTimerData(d.t, d)
                call TimerStart(d.t, 5., false, function RemoveStr)
            endif
            return false
        endfunction
        
    
        private function ROTFCInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            local integer index = 0
            
            loop
                call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_ATTACKED, null)
                set index = index + 1
                exitwhen index == bj_MAX_PLAYER_SLOTS
            endloop
            call TriggerAddCondition(t, Condition(function Conditions))
            set t = null
        endfunction
        
    endscope

    That works, but I still have the question of if anyone can give me points to optimize/'fix' my code up.
     
  3. emjlr3

    emjlr3 Change can be a good thing Staff Member

    Ratings:
    +396 / 0 / -0
    for MUI use a unit group
     
  4. WolfieeifloW

    WolfieeifloW WEHZ Helper

    Ratings:
    +372 / 0 / -0
    Ah, yes.
    Forgot about MUI, :p
    Here's the new code:
    JASS:
    scope ROTFC initializer ROTFCInit
    
        globals
            private constant string rotfcString = "innerfire"
            private group inc = CreateGroup()
        endglobals
        
        private struct data
            unit attacker
            unit dummy
            integer str
            real heal
            timer t
            
            method onDestroy takes nothing returns nothing
                call ReleaseTimer(.t)
            endmethod
        endstruct
    
        private function Chance takes integer level returns integer
            return 100//level * 1
        endfunction
        
        private function Heal takes nothing returns real
            return 0.03
        endfunction
        
        private function RemoveStr takes nothing returns nothing
            local data d = GetTimerData(GetExpiredTimer())
            
            call SetHeroStr(d.attacker, d.str, true)
            call GroupRemoveUnit(inc, d.attacker)
            call d.destroy()
        endfunction
        
        private function Conditions takes nothing returns boolean
            local data d = data.create()
            set d.attacker = GetAttacker()
            set d.str = GetHeroStr(d.attacker, true)
            set d.heal = GetUnitState(d.attacker, UNIT_STATE_MAX_LIFE) * Heal()
                    
            if (GetUnitAbilityLevel(d.attacker, rotfc) > 0 and GetRandomInt(0, 100) <= Chance(GetUnitAbilityLevel(d.attacker, rotfc)) and IsUnitInGroup(d.attacker, inc) == false) then
                call GroupAddUnit(inc, d.attacker)
                set d.dummy = CreateUnit(GetOwningPlayer(d.attacker), dummyID, GetUnitX(d.attacker), GetUnitY(d.attacker), bj_UNIT_FACING)
                call UnitAddAbility(d.dummy, rotfcBuff)
                call SetUnitAbilityLevel(d.dummy, rotfcBuff, 1)
                call IssueTargetOrder(d.dummy, rotfcString, d.attacker)
                call UnitApplyTimedLife(d.dummy, 'BTLF', 0.01)
                call SetHeroStr(d.attacker, R2I(d.str * 1.15), false)
                call BJDebugMsg(R2S(d.heal))
                call SetUnitState(d.attacker, UNIT_STATE_LIFE, GetUnitState(d.attacker, UNIT_STATE_LIFE) + d.heal)
                set d.t = NewTimer()
                call SetTimerData(d.t, d)
                call TimerStart(d.t, 5., false, function RemoveStr)
            endif
            return false
        endfunction
        
    
        private function ROTFCInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            local integer index = 0
            
            loop
                call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_ATTACKED, null)
                set index = index + 1
                exitwhen index == bj_MAX_PLAYER_SLOTS
            endloop
            call TriggerAddCondition(t, Condition(function Conditions))
            set t = null
        endfunction
        
    endscope

    Anything else that could be optimized/fixed up?
     
  5. dudeim

    dudeim New Member

    Ratings:
    +22 / 0 / -0
    You use GetUnitAbilityLevel twice so think you need to make a variable off it for maximum efficiency, for the rest it looks good.
     
  6. luorax

    luorax Invasion in Duskwood

    Ratings:
    +67 / 0 / -0
    Nope, calling GetUnitAbilityLevel() twice instead of a local variable is fine.
     
  7. WolfieeifloW

    WolfieeifloW WEHZ Helper

    Ratings:
    +372 / 0 / -0
    I'd have to make it an integer in the struct;
    So I think an extra struct member would be less efficient then calling a native twice, no?
     
  8. luorax

    luorax Invasion in Duskwood

    Ratings:
    +67 / 0 / -0
    Yes, I think it'd be still less efficient. (I'm not sure - someone's already benchamrked these things, but I really forgot the results) But it doesn't matter, the difference is not noticeable.
     

Share This Page