| 10-29-2011, 03:52 PM | #1 |
JASS://=========================================================================== // This is how you start timer with TT //=========================================================================== call TT_StartEx(function Periodic, DataStruct, PERIOD) //=========================================================================== // This is how you start timer with TimerUtils //=========================================================================== local timer t = NewTimer() call SetTimerData(t, DataStruct) call TimerStart(t, PERIOD, true, function Periodic) JASS://=========================================================================== // This is how you get data with TT //=========================================================================== local Data data = TT_GetData() //=========================================================================== // This is how you get data with TimerUtils //=========================================================================== local Data data = GetTimerData(GetExpiredTimer()) JASS://=========================================================================== // This is how you recycle timer with TT //=========================================================================== return true //=========================================================================== // This is how you recycle timer with TimerUtils //=========================================================================== call ReleaseTimer(GetExpiredTimer()) TimerUtils has Blue, Orange, Red, Purple and Chromatic flavors. A testament to inability of making a right choice. I attribute it's widespread use to general masochistic temperament of wc3 modders. |
| 10-29-2011, 04:04 PM | #2 |
And the rest of us will be developing resources suitable to our needs instead of sitting idle reaping their own statures. Nice to see you around just to make this one troll post. |
| 10-29-2011, 04:41 PM | #3 |
Sorry you don't have enough mana to perform Ad Hominem attack. I am just curious why people still use explicit attaching and explicit recycling. (Pissing Vex off is always a nice side bonus thou) I think we need another timer system... |
| 10-29-2011, 04:47 PM | #4 |
You could start with a proposal... |
| 10-29-2011, 04:49 PM | #5 |
Timer System Design 101 Cohadar claims that this verbose timer attachment is wrong. Why? Because it makes sense. As a periodic event, I am not interested in the idea that this is a timer object running in the background, I am just interested in the idea that this event is happening periodically and that data is attached to it. Bribe (and many others) see that this is too high of a level of abstraction, and working with timers as objects makes far more sense, and the code has much more verbosity. This will forever be a debate amongst programmers. It is reminiscent of C versus C++, in which we must ask, do we want to think of these things as integers or truly as "objects"? I think the best approach is choosing the right tool for the job. While writing something like a weather system, Cohadar's approach may be better. For a spell, Bribe's is better. Because I think consistency is important (hence the idea of conventions) I will go with the verbosity every day. Better for code to be too verbose than too confusing. Systems like Timer2 and Timer Tools just make this timer shit ugly as fuck. Sorry Bribe and Nestharus, but your code can sometimes make me want to throw up. I'll stick to TimerUtils. But I use wrappers, TimerSetData and TimerGetData are much more intuitive and natural looking for me. EDIT: Also, do I even have to mention that "TT_" is a disgusting way to name a function? |
| 10-29-2011, 05:10 PM | #6 |
Behold, timer system that does same shit as TimerUtils with 1/3 lines of code and implicit attaching and recycling. JASS:library Timer uses Table struct Timer private timer tim private integer data // timer -> Timer private static HandleTable timerTable //============================================================================== static method onInit takes nothing returns nothing set .timerTable = HandleTable.create() endmethod //============================================================================== static method start takes code handlerFunc, real period, integer data returns Timer local Timer ret = Timer.allocate() if ret.tim == null then set ret.tim = CreateTimer() endif set ret.data = data set .timerTable[ret.tim] = ret call TimerStart(ret.tim, period, true, handlerFunc) return ret endmethod //============================================================================== // no need to flush timerTable because indexes are recycled by struct //============================================================================== static method stop takes nothing returns nothing local Timer t = .timerTable[GetExpiredTimer()] call PauseTimer(t.tim) call t.destroy() endmethod //============================================================================== static method getData takes nothing returns integer local Timer t = .timerTable[GetExpiredTimer()] return t.data endmethod endstruct endlibrary EDIT: tested and verified. Example of use: JASS://=========================================================================== // Example trigger for using Timer //=========================================================================== scope IntBuff initializer Init globals private constant integer AID_SPELL = 'A004' // spell private constant integer BID_SPELL = 'B000' // buff private constant integer AID_BONUS = 'A003' // int bonus private constant real BUFF_CHECK_PERIOD = 0.2 private constant real DURATION = 20 // sec endglobals //=========================================================================== private struct Data unit whichHero integer ticks //----------------------------------------------------------------------- static method create takes unit whichHero returns Data local Data data = Data.allocate() set data.whichHero = whichHero set data.ticks = R2I(DURATION/BUFF_CHECK_PERIOD) call UnitAddAbility(whichHero, AID_BONUS) return data endmethod //----------------------------------------------------------------------- private method onDestroy takes nothing returns nothing call UnitRemoveAbility(.whichHero, AID_BONUS) call UnitRemoveAbility(.whichHero, BID_SPELL) endmethod endstruct //=========================================================================== private function Periodic takes nothing returns nothing local Data data = Timer.getData() set data.ticks = data.ticks - 1 // if time expires or buff gets removed by some dispell if data.ticks <=0 or GetUnitAbilityLevel(data.whichHero, BID_SPELL) == 0 then call Timer.stop() call data.destroy() endif endfunction //=========================================================================== private function Actions takes nothing returns nothing local unit caster = GetTriggerUnit() local unit target = GetSpellTargetUnit() if GetUnitAbilityLevel(target, AID_BONUS) == 0 then call Timer.start(function Periodic, BUFF_CHECK_PERIOD, Data.create(target)) endif set caster = null set target = null endfunction //=========================================================================== private function Conditions takes nothing returns boolean return GetSpellAbilityId() == AID_SPELL endfunction //=========================================================================== private function Init takes nothing returns nothing local trigger trig = CreateTrigger() call TriggerRegisterAnyUnitEventBJ( trig, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition( trig, Condition( function Conditions ) ) call TriggerAddAction( trig, function Actions ) endfunction endscope |
| 10-29-2011, 05:33 PM | #7 |
>2011 >Not using SpellStruct/xe Let's get real. |
| 10-29-2011, 05:45 PM | #8 | |||
Quote:
Also, that example is kinda horrible, periodically checking if the unit still has the buff is so 2006. Just trigger your dispel, sheesh. Quote:
Quote:
|
| 10-30-2011, 04:28 AM | #9 | |
Quote:
Eh, the main reason why the code is so long is because of the preloading timer thing and the 3 flavors. The real code ends up being shortened by a lot (staticifs) and the functions that matter have relatively short code. Anyway, imo we don't need more timer systems since the differences in speed are realistically negligible. We don't want it to be like the time when TimerUtils, HandleVars, HSAS, ABC/ABCT/TT, T2Ix, and HAIL were all viable timer systems. Instead, we should embrace the fact that people normally conform to using 1-2. =) |
| 10-30-2011, 08:07 AM | #10 | ||
Quote:
that is for crazy physics engines. And people that make those usually inline their timer stuff manually anyways, they don't need systems. THE MAIN PURPOSE OF SYSTEMS IS TO MAKE MAPPING EASIER. Speed/Optimization is something for private use, there is no such thing as general purpose optimization. Quote:
But yes Table owned HandleVars, ABC, HSAS and HAIL. But not because it is faster but because it is easier to use. The reason there was so much handle systems was not because they were really different but because they used different interfaces to do the same stuff. The differences in speed were 99% of times imaginary arguments of systems author (me included) The same reasoning is now applied to "flavors" of timerutils. Flavors exist because of imaginary arguments... IMHO, there should be one timer system fast enough for 95% of people. Those 5% freaks will make their custom systems no matter how good standard one is anyways. I mean there are people now claiming that hashtables are slow == a sure sign of optimization deranged mind. Something to think about: you don't need timer preloading if you use timer recycling. |
| 10-30-2011, 09:21 AM | #11 | |||||
Quote:
Quote:
Quote:
Quote:
Quote:
What PurgeandFire111 said is true: a minimal implementation of TimerUtils would be much shorter. You didn't respond to my previous post, would you find the overhead of an .evaluate acceptable in order to have a nicer timer callback that takes the data value as an argument instead of using an awkward getData method? |
| 10-30-2011, 12:22 PM | #12 | |
Quote:
TT uses .evaluate to make this possible: (implicit timer release) JASS://=========================================================================== // This is how you recycle timer with TT //=========================================================================== return true //=========================================================================== // This is how you recycle timer with TimerUtils //=========================================================================== call ReleaseTimer(GetExpiredTimer()) Using evaluate to remove getData function is pointless, since you have to write explicit struct cast anyways, so you get same number of code lines in the end. JASS:private function Periodic takes integer data returns boolean local Data d = (Data)data // how is this better local Data d = Timer.getData() // than this endfunction |
| 11-23-2011, 04:05 PM | #13 |
Arent there more things to do with timers than starting? Like pausing, getting the remaining time and getting the elapsed time? What about non-periodic timers with no data attached? Seems to me like call TimerStart(NewTimer(),TIMEOUT, false, function Callback) is about as hard/long to write as call TT_StartEx(function Periodic, 0, PERIOD). Yes, this is probably a minority of all use-cases of timers, but its a reasonable one. One size just doesnt fit all. |
| 11-25-2011, 10:20 AM | #14 |
I still explicitly create timers when it is logical to do so. Besides don't make this thread too serious, I was just trolling. Basically I use TT because: 1. I made it 2. It makes great sense to me (because I made it, hah) I don't really care what other people use (that was me like 3 years ago) |
