Bribe
vJass errors are legion
- Reaction score
- 67
This isn't about speed and TriggerSleepAction, it's about thread integrity. I've read a post from Cohadar on wc3c.net (from 2008, mind you), and this is what he says:
This challenges many common practices. Should I change my approach, use short-and-wasteful conditions and start using actions again?
cohadar said:Both Conditions and Actions should be used in a way Blizzard intended them to be used.
Doing stuff like this is bad:
JASS:function Condition takes nothing returns boolean if (GetSpellAbilityId() == 039;A000039;) then //do stuff endif return false endfunction
It clogs out the main game thread which can lead to considerable event response lag (time between you click on an ability and time it executes)
Also you cannot use TriggerSleepAction(seconds) inside a Condition and TriggerSleedCondition() function does not exist
That said it is OK to optimize some simple triggers by moving stuff from action to a condition but nothing too heavy.
For example this is OK:
JASS:library Example globals private group G = CreateGroup() endglobals // here some periodic function does something to units in a group function Condition takes nothing returns boolean if (GetSpellAbilityId() == 039;A000039;) then call GroupAddUnit(G, GetSpellTargetUnit()) set TimeLeft[GetSpellTargetUnit()] = GetUnitAbilityLevel(GetTriggerUnit(), 039;A000039;)*10. endif return false endfunction endlibrary
This is not ok:
JASS:function Condition takes nothing returns boolean if (GetSpellAbilityId() == 039;A000039;) then call Dummy_create(GetTriggerUnit(), AID_DUMMY, GetUnitAbilityLevel(hero, AID_SPELL), 5.) call IssueTargetOrderById(bj_lastCreatedUnit, OID_DUMMY, GetSpellTargetUnit()) return false endfunction
Spells with heavy stuff like creating dummy casters or sliding units or spells with custom effects should never be done in conditions.
In fact in 99% of cases you should use Conditions and Actions the way they are intended to be used.
That 1% that differs are stuff like DamageDetection systems where you register OnDamage trigger with default Condition and the call TriggerExecute from it for a specific stuff.
Here is such a condition from ORBEngine:
JASS://========================================================================= // MAIN ENGINE //========================================================================= // Units that use OrbAttacks need to have AID_ORB_ATTACK // Units that use OrbShields need to have AID_ORB_SHIELD //========================================================================= private function UnitDamaged takes nothing returns boolean local integer i local unit attacker local unit victim if GetEventDamage()<=0.0 then return false endif // recursion prevention if SEM > 1 then call BJDebugMsg(SCOPE_PREFIX+"UnitDamaged - SEM>1") return false endif set attacker = GetEventDamageSource() set victim = GetTriggerUnit() // Orb Spells on SEM==0 must deal minimum damage (0..1) because they don't triger Orb Shields if (GetUnitAbilityLevel(attacker, ORBConfig_SPELL) > 0) and (SEM==0) then set SEM = SEM + 1 //----------------// set i = 0 loop exitwhen i >= SpellCounter if GetUnitAbilityLevel(attacker, SpellId<i>) > 0 then //call TextTag_Unit(victim, SpellDescription<i>, "|c0000FF00") if TriggerEvaluate(SpellTrigger<i>) then call TriggerExecute(SpellTrigger<i>) endif exitwhen true // no dummy casts 2 different orb spells endif set i = i + 1 endloop set SEM = SEM - 1 //----------------// // if unit has custom shield ability elseif (GetUnitAbilityLevel(victim, ORBConfig_SHIELD) > 0) then set i = 0 loop exitwhen i >= ShieldCounter if GetUnitAbilityLevel(victim, ShieldId<i>) > 0 then //call TextTag_Unit(victim, ShieldDescription<i>, "|c000000FF") if TriggerEvaluate(ShieldTrigger<i>) then call TriggerExecute(ShieldTrigger<i>) endif endif set i = i + 1 endloop endif // unit special attack if (GetUnitAbilityLevel(attacker, ORBConfig_ATTACK) > 0) and (SEM==0) and (attacker!=victim) then set SEM = SEM + 1 //----------------// set i = 0 loop exitwhen i >= AttackCounter if GetUnitAbilityLevel(attacker, AttackId<i>) > 0 then //call TextTag_Unit(attacker, AttackDescription<i>, "|c00FF0000") if TriggerEvaluate(AttackTrigger<i>) then call TriggerExecute(AttackTrigger<i>) endif exitwhen true // prevent using 2 orb attacks at same time endif set i = i + 1 endloop set SEM = SEM - 1 //----------------// endif // debugging // 0 - standard damage // 1 - custom damage //if SEM == 1 then // call TextTag_Unit(GetTriggerUnit(), I2S(R2I(GetEventDamage())), "|c00FFFFFF") //endif set attacker = null set victim = null return false endfunction </i></i></i></i></i></i></i></i></i></i></i></i>
========================================================
But I doubt you will be making this kind of triggers any time soon,
so the answer to your question is:
Use Conditions and Actions like Blizzard does.
This challenges many common practices. Should I change my approach, use short-and-wasteful conditions and start using actions again?