• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

BotL - Coding & Systems

Status
Not open for further replies.
Level 18
Joined
Sep 14, 2012
Messages
3,413
Try this :
JASS:
library TimedStats

    globals
        private constant real FPS = 0.0312500
    endglobals
   
    //1 : Strength
    //2 : Agility
    //3 : Intelligence
    struct TimedStats extends array
        private unit targ
        private real temp
        private integer amount
        private integer type
        private thistype prev
        private thistype next
        private static timer period
        private static integer count
       
        private static method periodic takes nothing returns nothing
            local thistype this = thistype(0)
            loop
                set this = this.next
                exitwhen this == 0
                set this.temp = this.temp -FPS
                if this.temp <= 0 then
                    if this.type==1 then
                        call SetHeroStr(this.targ, GetHeroStr(this.targ, false)-this.amount, false)
                    elseif this.type==2 then
                        call SetHeroAgi(this.targ, GetHeroAgi(this.targ, false)-this.amount, false)
                    elseif this.type==3 then
                        call SetHeroInt(this.targ, GetHeroInt(this.targ, false)-this.amount, false)
                    debug else
                        debug call BJDebugMsg("You entered the wrong number for the stats thingy")
                    endif
                    call this.destroy()
                endif
            endloop
        endmethod
       
        static method AddTimedStatBonus takes unit targ, integer i, integer stats, real time returns nothing
            local thistype this
            if thistype(0).prev == 0 then
                set this = thistype(0).prev
                set thistype(0).prev = thistype(0).prev.prev
            else
                set count = count + 1
                set this = count
            endif
            if thistype(0).next == 0 then
                call TimerStart(period, FPS, true, function thistype.periodic)
            else
                set thistype(0).next.prev = this
            endif
            set this.next = thistype(0).next
            set thistype(0).next = this
            set this.prev = thistype(0)
            set this.targ = targ
            set this.amount = i
            set this.type = stats
            set this.temp = time
            if stats==1 then
                call SetHeroStr(targ, GetHeroStr(targ, false)+i, false)
            elseif stats==2 then
                call SetHeroAgi(targ, GetHeroAgi(targ, false)+i, false)
            elseif stats==3 then
                call SetHeroInt(targ, GetHeroInt(targ, false)+i, false)
            debug else
                debug call BJDebugMsg("You're giving wrong number for the stats thingy")
            endif
        endmethod
       
        private method destroy takes nothing returns nothing
                if this.next != 0 then
                    set this.next.prev = this.prev
                endif
                set this.prev.next = this.next
                set this.prev = thistype(0).prev
                set thistype(0).prev = this
                if thistype(0).next == 0 then
                    call PauseTimer(period)
                endif
                set this.targ = null
        endmethod
       
        private static method onInit takes nothing returns nothing
            set count = 0
            set period = CreateTimer()
        endmethod
    endstruct
endlibrary
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
Whatever, I still think pausing is simpler, the guy is an NPC anyway. Go do what you want, I just fucked myself again by answering.
 
Level 18
Joined
Sep 14, 2012
Messages
3,413
Ok the girl went to sleep I'm a bit more here :
JASS:
library DoT
    globals
        private constant real FPS = 0.0100
    endglobals
    
    struct DoT extends array
        private unit caster
        private unit target
        private real interval   
        private real during
        private real dmg
        private real temp
        private static integer count
        private thistype prev
        private thistype next
        private static timer period
        
        private static method iterate takes nothing returns nothing
            local thistype this = thistype(0)
            loop
                set this = this.next
                exitwhen this == 0
                set this.temp = this.temp + FPS
                if this.temp >= this.interval then
                    call UnitDamageTarget(this.caster, this.target, this.dmg, true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, null)
                    set this.temp = this.temp-this.interval
                endif
                set this.during = this.during - FPS
                if this.during <= 0 then
                    call this.destroy()
                endif
            endloop
        endmethod
        
        static method add takes unit cast, unit targ, real dur, real inter, real dm returns nothing
            local thistype this
            
            if thistype(0).prev == 0 then
                set count = count + 1
                set this = count
            else
                set this = thistype(0).prev
                set thistype(0).prev = thistype(0).prev.prev
            endif
            
            if thistype(0).next == 0 then
                call TimerStart(period, FPS, true, function thistype.iterate)
            else
                set thistype(0).next.prev = this
            endif
            
            set this.next = thistype(0).next
            set thistype(0).next = this
            set this.prev = thistype(0)
            
            set this.caster = cast
            set this.target = targ
            set this.interval = inter
            set this.during = dur
            set this.dmg = dm
            set this.temp = 0
        endmethod

        private method destroy takes nothing returns nothing
            if this.next != 0 then
                set this.next.prev = this.prev
            endif
            
            set this.prev.next = this.next
            set this.prev = thistype(0).prev
            set thistype(0).prev = this
        
            if thistype(0).next == 0 then
                call PauseTimer(period)
            endif

            set this.caster = null
            set this.target = null
        endmethod
        
        private static method onInit takes nothing returns nothing
            set count = 0
            set period = CreateTimer()
        endmethod
    endstruct
endlibrary
To call :
call DoT.add(caster, target, duration, interval, dmg)

JASS:
library TimedStats

    globals
        private constant real FPS = 0.0312500
    endglobals
    
    //1 : Strength
    //2 : Agility
    //3 : Intelligence
    struct TimedStats extends array
        private unit targ
        private real temp
        private integer amount
        private integer type
        private thistype prev
        private thistype next
        private static timer period
        private static integer count
        private static HandleTable tab
        
        private static method periodic takes nothing returns nothing
            local thistype this = thistype(0)
            loop
                set this = this.next
                exitwhen this == 0 
                set this.temp = this.temp -FPS
                if this.temp < 0 then
                    if this.type==1 then
                        call SetHeroStr(this.targ, GetHeroStr(this.targ, false)-this.amount, false)
                    elseif this.type==2 then
                        call SetHeroAgi(this.targ, GetHeroAgi(this.targ, false)-this.amount, false)
                    elseif this.type==3 then
                        call SetHeroInt(this.targ, GetHeroInt(this.targ, false)-this.amount, false)
                    debug else
                        debug call BJDebugMsg("You entered the wrong number for the stats thingy")
                    endif
                    call this.destroy()
                endif
            endloop
        endmethod
        
        static method AddTimedStatBonus takes unit targ, integer i, integer stats, real time returns nothing
            local thistype this
            if thistype(0).prev == 0 then
                set this = thistype(0).prev
                set thistype(0).prev = thistype(0).prev.prev
            else
                set count = count + 1
                set this = count
            endif
            if thistype(0).next == 0 then
                call TimerStart(period, FPS, true, function thistype.periodic)
            else
                set thistype(0).next.prev = this
            endif
            set this.next = thistype(0).next
            set thistype(0).next = this
            set this.prev = thistype(0)
            set this.targ = targ
            set this.amount = i
            set this.type = stats
            set this.temp = time
            if i==1 then
                call SetHeroStr(targ, GetHeroStr(targ, false)+amount, false)
            elseif i==2 then
                call SetHeroAgi(targ, GetHeroAgi(targ, false)+amount, false)
            elseif i==3 then
                call SetHeroInt(targ, GetHeroInt(targ, false)+amount, false)
            debug else
                debug call BJDebugMsg("You're giving wrong number for the stats thingy")
            endif
        endmethod
        
        private method destroy takes nothing returns nothing
                if this.next != 0 then
                    set this.next.prev = this.prev
                endif
                set this.prev.next = this.next
                set this.prev = thistype(0).prev
                set thistype(0).prev = this
                if thistype(0).next == 0 then
                    call PauseTimer(period)
                endif
                set this.targ = null
        endmethod
        
        private static method onInit takes nothing returns nothing
            set count = 0
            set period = CreateTimer()
            set tab = HandleTable.create()
        endmethod
    endstruct
endlibrary
To call :
call TimedStats.AddTimedStatBonus(target, amount, statsType, time)
 
Level 18
Joined
Sep 14, 2012
Messages
3,413
You were right :
JASS:
library TimedStats

    globals
        private constant real FPS = 0.100
    endglobals
    
    //1 : Strength
    //2 : Agility
    //3 : Intelligence
    struct TimedStats extends array
        private unit targ
        private real temp
        private integer amount
        private integer type
        private thistype prev
        private thistype next
        private static timer period
        private static integer count
        
        private static method periodic takes nothing returns nothing
            local thistype this = thistype(0)
            loop
                set this = this.next
                exitwhen this == 0 
                set this.temp = this.temp -FPS
                if this.temp <= 0 then
                    if this.type==1 then
                        call SetHeroStr(this.targ, GetHeroStr(this.targ, false)-this.amount, false)
                    elseif this.type==2 then
                        call SetHeroAgi(this.targ, GetHeroAgi(this.targ, false)-this.amount, false)
                    elseif this.type==3 then
                        call SetHeroInt(this.targ, GetHeroInt(this.targ, false)-this.amount, false)
                    debug else
                        debug call BJDebugMsg("You entered the wrong number for the stats thingy")
                    endif
                    call this.destroy()
                endif
            endloop
        endmethod
        
        static method AddTimedStatBonus takes unit targ, integer amount, integer stats, real time returns nothing
            local thistype this
            if thistype(0).prev == 0 then
                set this = thistype(0).prev
                set thistype(0).prev = thistype(0).prev.prev
            else
                set count = count + 1
                set this = count
            endif
            if thistype(0).next == 0 then
                call TimerStart(period, FPS, true, function thistype.periodic)
            else
                set thistype(0).next.prev = this
            endif
            set this.next = thistype(0).next
            set thistype(0).next = this
            set this.prev = thistype(0)
            set this.targ = targ
            set this.amount = amount
            set this.type = stats
            set this.temp = time
            if stats==1 then
                call SetHeroStr(targ, GetHeroStr(targ, false)+amount, false)
            elseif stats==2 then
                call SetHeroAgi(targ, GetHeroAgi(targ, false)+amount, false)
            elseif stats==3 then
                call SetHeroInt(targ, GetHeroInt(targ, false)+amount, false)
            debug else
                debug call BJDebugMsg("You're giving wrong number for the stats thingy")
            endif
        endmethod
        
        private method destroy takes nothing returns nothing
                if this.next != 0 then
                    set this.next.prev = this.prev
                endif
                set this.prev.next = this.next
                set this.prev = thistype(0).prev
                set thistype(0).prev = this
                if thistype(0).next == 0 then
                    call PauseTimer(period)
                endif
                set this.targ = null
        endmethod
        
        private static method onInit takes nothing returns nothing
            set count = 0
            set period = CreateTimer()
        endmethod
    endstruct
endlibrary
 
Level 16
Joined
Jul 31, 2012
Messages
2,217
okay, here is my report on the script:
call TimerStart(period, FPS, true, function thistype.periodic)
in here ^ (Stats) why do you make a periodic timer? make it a one shot and when timer ends, remove the stat bonus

DOT is fixed!
well, it was half my fault, half yours:
when this.temp is checked to be equal or higher than the interval, you should've done this.temp+FPS >= interval
^ that is your side of the fault and it caused the damage to no get triggered
Mine was that the caster damager was a dummy, which was killed/removed so no damager

^^' i'm starting to understand how those stuff work

TimedStat:
JASS:
library TimedStats

    globals
        private constant real FPS = 0.1
    endglobals
   
    //1 : Strength
    //2 : Agility
    //3 : Intelligence
    struct TimedStats extends array
        private unit targ
        private real temp
        private integer amount
        private integer type
        private thistype prev
        private thistype next
        private static timer period
        private static integer count
       
        private static method periodic takes nothing returns nothing
            local thistype this = thistype(0)
            loop
                set this = this.next
                exitwhen this == 0
                set this.temp = this.temp -FPS
                if this.temp <= 0 then
                    if this.type==1 then
                        call SetHeroStr(this.targ, GetHeroStr(this.targ, false)-this.amount, false)
                    elseif this.type==2 then
                        call SetHeroAgi(this.targ, GetHeroAgi(this.targ, false)-this.amount, false)
                    elseif this.type==3 then
                        call SetHeroInt(this.targ, GetHeroInt(this.targ, false)-this.amount, false)
                    debug else
                        debug call BJDebugMsg("You entered the wrong number for the stats thingy")
                    endif
                    call this.destroy()
                endif
            endloop
        endmethod
       
        static method AddTimedStatBonus takes unit targ, integer amount, integer stats, real time returns nothing
            local thistype this
            if thistype(0).prev == 0 then
                set this = thistype(0).prev
                set thistype(0).prev = thistype(0).prev.prev
            else
                set count = count + 1
                set this = count
            endif
            if thistype(0).next == 0 then
                call TimerStart(period, FPS, true, function thistype.periodic)
            else
                set thistype(0).next.prev = this
            endif
            set this.next = thistype(0).next
            set thistype(0).next = this
            set this.prev = thistype(0)
            set this.targ = targ
            set this.amount = amount
            set this.type = stats
            set this.temp = time
            if stats==1 then
                call SetHeroStr(targ, GetHeroStr(targ, false)+amount, false)
            elseif stats==2 then
                call SetHeroAgi(targ, GetHeroAgi(targ, false)+amount, false)
            elseif stats==3 then
                call SetHeroInt(targ, GetHeroInt(targ, false)+amount, false)
            debug else
                debug call BJDebugMsg("You're giving wrong number for the stats thingy")
            endif
        endmethod
       
        private method destroy takes nothing returns nothing
                if this.next != 0 then
                    set this.next.prev = this.prev
                endif
                set this.prev.next = this.next
                set this.prev = thistype(0).prev
                set thistype(0).prev = this
                if thistype(0).next == 0 then
                    call PauseTimer(period)
                endif
                set this.targ = null
        endmethod
       
        private static method onInit takes nothing returns nothing
            set count = 0
            set period = CreateTimer()
        endmethod
    endstruct
endlibrary
DoT:
JASS:
library DoT
    globals
        private constant real FPS = 0.0100
    endglobals
   
    struct DoT extends array
        private unit caster
        private unit target
        private real interval  
        private real during
        private real dmg
        private real temp
        private static integer count
        private thistype prev
        private thistype next
        private static timer period
       
        private static method iterate takes nothing returns nothing
            local thistype this = thistype(0)
            loop
                set this = this.next
                exitwhen this == 0
                set this.temp = this.temp + FPS
                if this.temp+FPS >= this.interval then
                    call UnitDamageTarget(this.caster, this.target, this.dmg, true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, null)
                    set this.temp = 0
                endif
                set this.during = this.during - FPS
                if this.during <= 0 then
                    call this.destroy()
                endif
            endloop
        endmethod
       
        static method add takes unit cast, unit targ, real dur, real inter, real dm returns nothing
            local thistype this
           
            if thistype(0).prev == 0 then
                set count = count + 1
                set this = count
            else
                set this = thistype(0).prev
                set thistype(0).prev = thistype(0).prev.prev
            endif
           
            if thistype(0).next == 0 then
                call TimerStart(period, FPS, true, function thistype.iterate)
            else
                set thistype(0).next.prev = this
            endif
           
            set this.next = thistype(0).next
            set thistype(0).next = this
            set this.prev = thistype(0)
           
            set this.caster = cast
            set this.target = targ
            set this.interval = inter
            set this.during = dur
            set this.dmg = dm
            set this.temp = 0
        endmethod

        private method destroy takes nothing returns nothing
            if this.next != 0 then
                set this.next.prev = this.prev
            endif
           
            set this.prev.next = this.next
            set this.prev = thistype(0).prev
            set thistype(0).prev = this
       
            if thistype(0).next == 0 then
                call PauseTimer(period)
            endif

            set this.caster = null
            set this.target = null
        endmethod
       
        private static method onInit takes nothing returns nothing
            set count = 0
            set period = CreateTimer()
        endmethod
    endstruct
endlibrary
 
Level 16
Joined
Jul 31, 2012
Messages
2,217
Dude don't touch to periodic timers it is the key to reduce lags ;)
well, the stat bonus is still permanent by now
Anyway glad you manage to found the bug (omg I was so bad btw) :)
yes :3
I can do the transparency now.
great !
For the snippet the doc isn't enough xD ?
Nop xD i want the function call and it's arguments :p
Oh shit you'll need to wait a bit
if that's 'a bit' it's ok, i have time, but not hours xD
 
Level 18
Joined
Sep 14, 2012
Messages
3,413
I didn't test it at all :
JASS:
library Transparency requires Table
    globals
        private constant real FPS = 0.100
    endglobals
    
    private struct Transparence extends array
        static HandleTable tab
        
        static method GetUnitAlpha takes unit u returns integer
            if tab.exists(u) then
                return tab[u]
            else
                return 255
            endif
        endmethod
        
        static method cond takes nothing returns boolean
            local unit u = GetTriggerUnit()
            if tab.exists(u) then
                call tab.flush(u)
            endif
            set u = null
            return false
        endmethod
        
        static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
            call TriggerAddCondition(t, Condition(function thistype.cond))
            set tab = HandleTable.create()
            set t = null
        endmethod
    endstruct
    
    struct Transparency extends array
        private unit target
        private real temp
        private integer trans
        private thistype next
        private thistype prev
        private static integer count
        private static timer period 
        
        private static method periodic takes nothing returns nothing
            local thistype this = thistype(0).next
            loop
                exitwhen this == 0
                set this.temp = this.temp - FPS
                if this.temp <= 0 then
                    call SetUnitVertexColor(this.target, 255, 255, 255, Transparence.GetUnitAlpha(this.target) + this.trans)
                    call this.destroy()
                endif
                set this = this.next
            endloop
        endmethod
                    
        static method add takes unit targ, real dur, integer transp returns nothing
            local thistype this
            local integer i = Transparence.GetUnitAlpha(targ)
            if thistype(0).prev == 0 then
                set count = count + 1
                set this = count
            else
                set this = thistype(0).prev
                set thistype(0).prev = thistype(0).prev.prev
            endif
            if thistype(0).next == 0 then
                call TimerStart(period, FPS, true, function thistype.periodic)
            else
                set thistype(0).next.prev = this
            endif
            set this.next = thistype(0).next
            set thistype(0).next = this
            set this.prev = thistype(0).prev
            set this.target = targ
            set this.temp = dur
            set this.trans = transp
            if transp > i then
                debug call BJDebugMsg("You're giving a bad number !")
                return
            else
                call SetUnitVertexColor(targ, 255, 255, 255, i-transp)
                set Transparence.tab[targ] = i-transp
            endif
        endmethod
        
        private method destroy takes nothing returns nothing
            if this.next != 0 then
                set this.next.prev = this.prev
            endif
            set this.prev.next = this.next
            set this.prev = thistype(0).prev
            set thistype(0).prev = this
            if thistype(0).next == 0 then
                call PauseTimer(period)
            endif
            set this.target = null
        endmethod

        private static method onInit takes nothing returns nothing
            set count = 0
            set period = CreateTimer()
        endmethod
    endstruct
endlibrary

It might bugs I'm doing Batch at the same time >_<
 
Level 18
Joined
Sep 14, 2012
Messages
3,413
call Transparency.add(target, duration, transparency)
The higher the transparency factor is the more it will be transparent.
YOU CANNOT USE HIGHER THAN 255.
AND REMEMBER THAT EVERY CHANGEMENT ARE STORED -> If you stack be careful ;)

Oh I'll do a better version by merging the two structs...
Wait 3m
 
Level 18
Joined
Sep 14, 2012
Messages
3,413
JASS:
library Transparency requires Table
    globals
        private constant real FPS = 0.100
    endglobals
    
    struct Transparency extends array
        private unit target
        private real temp
        private integer trans
        private thistype next
        private thistype prev
        private static integer count
        private static timer period
        private static HandleTable tab
        
        static method GetUnitAlpha takes unit u returns integer
            if tab.exists(u) then
                return tab[u]
            else
                return 255
            endif
        endmethod
        
        private static method cond takes nothing returns boolean
            local unit u = GetTriggerUnit()
            if tab.exists(u) then
                call tab.flush(u)
            endif
            set u = null
            return false
        endmethod
        
        private static method periodic takes nothing returns nothing
            local thistype this = thistype(0).next
            loop
                exitwhen this == 0
                set this.temp = this.temp - FPS
                if this.temp <= 0 then
                    call SetUnitVertexColor(this.target, 255, 255, 255, GetUnitAlpha(this.target) + this.trans)
                    call this.destroy()
                endif
                set this = this.next
            endloop
        endmethod
                    
        static method add takes unit targ, real dur, integer transp returns nothing
            local thistype this
            local integer i = GetUnitAlpha(targ)
            if thistype(0).prev == 0 then
                set count = count + 1
                set this = count
            else
                set this = thistype(0).prev
                set thistype(0).prev = thistype(0).prev.prev
            endif
            if thistype(0).next == 0 then
                call TimerStart(period, FPS, true, function thistype.periodic)
            else
                set thistype(0).next.prev = this
            endif
            set this.next = thistype(0).next
            set thistype(0).next = this
            set this.prev = thistype(0).prev
            set this.target = targ
            set this.temp = dur
            set this.trans = transp
            if transp > i then
                debug call BJDebugMsg("You're giving a bad number !")
                return
            else
                call SetUnitVertexColor(targ, 255, 255, 255, i-transp)
                set tab[targ] = i-transp
            endif
        endmethod
        
        private method destroy takes nothing returns nothing
            if this.next != 0 then
                set this.next.prev = this.prev
            endif
            set this.prev.next = this.next
            set this.prev = thistype(0).prev
            set thistype(0).prev = this
            if thistype(0).next == 0 then
                call PauseTimer(period)
            endif
            set this.target = null
        endmethod

        private static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
            call TriggerAddCondition(t, Condition(function thistype.cond))
            set tab = HandleTable.create()
            set count = 0
            set period = CreateTimer()
            set t = null
        endmethod
    endstruct
endlibrary

You can now use this too :
call Transparency.GetUnitAlpha(unit)
 
Status
Not open for further replies.
Top