No they don't.PurplePoot said:Shouldnt you be able to detect on cast? Or do autocasts not fire A Unit xxxs an Ability?
It's not accurate I think. What if you attack a unit from 100 range. It takes the damage, has the buff, but the effect you want comes a sec later? Hmm...donut3.5 said:Couldn't you just attach a buff to the autocast effect, and do
A unit is attacked
Wait 1 seconds
If triggering unit has buff then do blah blah else do nothing?
Well, how would it do it? I'm interested in knowing that, so I'd be pleased to you if you could explain it to me and maybe some others who want to know it.paskovich said:...
As I said, JASS would do it.
//======================================================================
//This catches the turn on/off order
//======================================================================
function Trig_ArrowSpellsOrder_Conditions takes nothing returns boolean
return GetIssuedOrderId() == OrderId("flamingarrows") or GetIssuedOrderId() == OrderId("unflamingarrows")
endfunction
function Trig_ArrowSpellsOrder_Actions takes nothing returns nothing
local unit flamer = GetTriggerUnit()
if GetIssuedOrderId() == OrderId("flamingarrows") then
call SetHandleInt(flamer,"arrowon",1)
else
call SetHandleInt(flamer,"arrowon",0)
endif
set flamer = null
endfunction
//======================================================================
//This is the "projectile hit detection" trigger - this makes the effect
//======================================================================
function Trig_ArrowSpells_Hit_Conditions takes nothing returns boolean
return GetEventDamageSource() == GetHandleUnit(GetTriggeringTrigger(), "DamageSource")
endfunction
function Trig_ArrowSpells_Hit_Actions takes nothing returns nothing
local unit flamer = GetEventDamageSource()
local unit target = GetTriggerUnit()
local trigger dmgtrig = GetTriggeringTrigger()
//
//All the effects go here...
//Here, it creates a special effect on the target:
call DestroyEffect(AddSpecialEffectTarget("abilities\\weapons\\DemolisherMissile\\DemolisherMissile.mdl",target,"origin"))
//
call SetHandleHandle(flamer, "DamageTrigger", null)
call FlushHandleLocals(dmgtrig)
call DestroyTrigger(dmgtrig)
set target = null
set flamer = null
set dmgtrig = null
endfunction
//======================================================================
//This is the 'unit is attacked' trigger
//======================================================================
function Trig_ArrowSpellsAttack_Conditions takes nothing returns boolean
return GetHandleInt(GetAttacker(),"arrowon") == 1 and GetHandleTrigger(GetAttacker(), "DamageTrigger") == null
endfunction
function Trig_ArrowSpellsAttack_Actions takes nothing returns nothing
local unit flamer = GetAttacker()
local unit target = GetTriggerUnit()
local trigger dmgtrig = CreateTrigger()
call SetHandleHandle(flamer, "DamageTrigger", dmgtrig)
call SetHandleHandle(dmgtrig, "DamageSource", flamer)
call TriggerRegisterUnitEvent(dmgtrig, target, EVENT_UNIT_DAMAGED)
call TriggerAddCondition(dmgtrig, Condition(function Trig_ArrowSpells_Hit_Conditions))
call TriggerAddAction(dmgtrig, function Trig_ArrowSpells_Hit_Actions)
call TriggerSleepAction(2)
call FlushHandleLocals(dmgtrig)
call DestroyTrigger(dmgtrig)
call SetHandleHandle(flamer, "DamageTrigger", null)
set target = null
set flamer = null
set dmgtrig = null
endfunction
//======================================================================
//This is the 'spell effect' trigger
//======================================================================
function Trig_ArrowSpellsCast_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'AHfa'
endfunction
function Trig_ArrowSpellsCast_Actions takes nothing returns nothing
local unit flamer = GetTriggerUnit()
local unit target = GetSpellTargetUnit()
local trigger dmgtrig = CreateTrigger()
call SetHandleHandle(flamer, "DamageTrigger", dmgtrig)
call SetHandleHandle(dmgtrig, "DamageSource", flamer)
call TriggerRegisterUnitEvent(dmgtrig, target, EVENT_UNIT_DAMAGED)
call TriggerAddCondition(dmgtrig, Condition(function Trig_ArrowSpells_Hit_Conditions))
call TriggerAddAction(dmgtrig, function Trig_ArrowSpells_Hit_Actions)
call TriggerSleepAction(2)
call FlushHandleLocals(dmgtrig)
call DestroyTrigger(dmgtrig)
call SetHandleHandle(flamer, "DamageTrigger", null)
set target = null
set flamer = null
set dmgtrig = null
endfunction
//===========================================================================
function InitTrig_ArrowSpells takes nothing returns nothing
local trigger ArrowSpellsOrder = CreateTrigger()
local trigger ArrowSpellsAttack = CreateTrigger()
local trigger ArrowSpellsCast = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(ArrowSpellsOrder, EVENT_PLAYER_UNIT_ISSUED_ORDER )
call TriggerAddCondition(ArrowSpellsOrder, Condition( function Trig_ArrowSpellsOrder_Conditions ) )
call TriggerAddAction(ArrowSpellsOrder, function Trig_ArrowSpellsOrder_Actions )
call TriggerRegisterAnyUnitEventBJ(ArrowSpellsAttack, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddCondition(ArrowSpellsAttack, Condition( function Trig_ArrowSpellsAttack_Conditions ) )
call TriggerAddAction(ArrowSpellsAttack, function Trig_ArrowSpellsAttack_Actions )
call TriggerRegisterAnyUnitEventBJ(ArrowSpellsCast, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition(ArrowSpellsCast, Condition( function Trig_ArrowSpellsCast_Conditions ) )
call TriggerAddAction(ArrowSpellsCast, function Trig_ArrowSpellsCast_Actions )
endfunction
//======================================================================
//This is the "projectile hit detection" trigger - this makes the effect
//======================================================================
function **** takes nothing returns boolean
return GetHandleInt(GetEventDamageSource(),"arrowon") == 1
endfunction
function **** takes nothing returns nothing
//local unit flamer = GetEventDamageSource()
local unit target = GetTriggerUnit()
local trigger dmgtrig = GetTriggeringTrigger()
//All the effects go here...
//Here, it creates a special effect on the target:
call DestroyEffect(AddSpecialEffectTarget("abilities\\weapons\\DemolisherMissile\\DemolisherMissile.mdl",target,"origin"))
//call SetHandleHandle(flamer, "DamageTrigger", null)
//call FlushHandleLocals(dmgtrig)
call DestroyTrigger(dmgtrig)
set target = null
//set flamer = null
set dmgtrig = null
endfunction
...
Paskovitch's Script said:EVENT_UNIT_DAMAGED
function Trig_ArrowSpells_Conditions takes nothing returns boolean
return GetLearnedSkill() == 'A00B' and GetLearnedSkillLevel() == 1
endfunction
function ArrowSpells_Damage takes nothing returns nothing
local unit target = GetTriggerUnit()
local unit attacker = GetEventDamageSource()
if GetUnitAbilityLevel(target, 'B001')>0 and GetUnitAbilityLevel(attacker, 'A00B')>0 then
call DestroyTrigger(GetTriggeringTrigger())
//
//Effects come here:
//
endif
set target = null
set attacker = null
endfunction
function ArrowSpells_Condition takes nothing returns boolean
if GetTriggerEventId() == EVENT_PLAYER_UNIT_ATTACKED then
return GetUnitAbilityLevel(GetAttacker(), 'A00B')>0 and GetHandleInt(GetAttacker(),"arrowon")==1 and not IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE)
elseif GetTriggerEventId() == EVENT_UNIT_ISSUED_ORDER then
if GetIssuedOrderId() == OrderId("poisonarrows") then
call SetHandleInt(GetTriggerUnit(), "arrowon", 1)
elseif GetIssuedOrderId() == OrderId("unpoisonarrows") then
call SetHandleInt(GetTriggerUnit(), "arrowon", 0)
endif
elseif GetTriggerEventId() == EVENT_UNIT_SPELL_EFFECT then
return GetSpellAbilityId()== 'A00B'
endif
return false
endfunction
function ArrowSpells_Actions takes nothing returns nothing
local unit target = null
local trigger dmgtrig = CreateTrigger()
if GetTriggerEventId() == EVENT_UNIT_SPELL_EFFECT then
set target = GetSpellTargetUnit()
else
set target = GetTriggerUnit()
endif
call TriggerRegisterUnitEvent(dmgtrig, target, EVENT_UNIT_DAMAGED)
call TriggerAddAction(dmgtrig, function ArrowSpells_Damage)
call TriggerSleepAction(2)
call DestroyTrigger(dmgtrig)
set dmgtrig = null
set target = null
endfunction
function Trig_ArrowSpells_Actions takes nothing returns nothing
local trigger t = CreateTrigger()
local unit attacker = GetTriggerUnit()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED)
call TriggerRegisterUnitEvent(t, attacker, EVENT_UNIT_SPELL_EFFECT)
call TriggerRegisterUnitEvent(t, attacker, EVENT_UNIT_ISSUED_ORDER)
call TriggerAddCondition(t, Condition(function ArrowSpells_Condition))
call TriggerAddAction(t, function ArrowSpells_Actions)
set t = null
set attacker = null
endfunction
//===========================================================================
function InitTrig_ArrowSpells takes nothing returns nothing
set gg_trg_ArrowSpells = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(gg_trg_ArrowSpells, EVENT_PLAYER_HERO_SKILL)
call TriggerAddCondition(gg_trg_ArrowSpells, Condition(function Trig_ArrowSpells_Conditions))
call TriggerAddAction(gg_trg_ArrowSpells, function Trig_ArrowSpells_Actions)
endfunction
I still don't understand why you should store DamageSource and DamageTrigger in GameCache. If you want to use the attacker, you can just use the function GetDamageSource() (like I did in my version of the condition). And what should you need the dmgtrig for? Blocking it? You could also do that using an extended condition (e.g. checking the target's custom value). GameCache is not that fast, as far as I know. Well, in this case this won't play an important role since the spell won't be casted that often.paskovich said:You're right with removing the 'flamer' in the damagetrig IN THIS CASE. But if you want sthg complex effect (or maybe more damage), you need the attacker.
Storing "DamageSource" and "DamageTrigger" is the key moment of the whole thing! This makes it 99% (i haven't found any) bugless.
I'm not completely sure since I'm not a leak-specialist, but what's with this:paskovich said:In which condition does the unit leak?
function Trig_ArrowSpells_Hit_Conditions takes nothing returns boolean
return GetEventDamageSource() == GetHandleUnit(GetTriggeringTrigger(), "DamageSource")
endfunction
The trigger does not fire everytime actually, at least not its actions, because there is the condition, that the attacker has the arrow ability turned on. To check this, you don't need to store the attacker itself if you do the check like I did in my version of the condition. This way you will also only fire once for each missile, because there can always impact only one missile from one attacker at the same time.paskovich said:Ok first of all, "Why storing DamageSource?":
Let's think it over. We have a trigger with EVENT_UNIT_ATTACKED. This fires every time, the unit is attacked by an other one. The trigger creates an other one, that detects the damage caused by any unit. What if the unit is attacked, and while the projectile is still "flying", the unit is damaged by an other (probably melee) unit. Storing the attacker, and checking it in the condition precludes these (exrteme) situations to happen.
You already kill old created triggers after a short wait in your script, don't you? The only possibility that this does not work is that the caster fires again before the first missile impacts, am I right?"Why storing the DmgTrigger?":
What if the unit misses? The damage trigger is created, and still waiting for the event. The unit attacks again, but this time it does not miss, an other damage trigger is created. Now there are 2 active damage triggers. (Repeat: Storing the trigger, and checking it in the condition precludes these (exrteme) situations to happen.)
Hm, you're again right. Not that easy if you still want to take care of the possibility of more than one missile of the same unit in the air. If you exclude this possibility, it should be enough to check the cooldown in the "unit is attacked" trigger, I think.And also an other thing about my script: It does not work if the ability has a cooldown... It is a bigger problem than mana.
In some extreme situations (and of course when there are more units with the ability) this CAN happen! Each attacker has the ability, each of them "arrowon" set to 1, now what if they attack the same unit in the same second? This "storing-the-attacker" thing is only a safety action that is useful in maps more simple units have the ability (for exaple in a melee map), and the player controls and orders them in a group. But if you have only one unit with the ability (like in hero arena maps), it's not neccessary of course....there can always impact only one missile from one attacker at the same time