Warcraft III resources & community, 2003–2006 · archived

Arrow Spells

25 posts
#1

Arrow Spells

Is there a way to make arrow spells (autocast spells who can used instead o attack (flaming arrows and such)) in GUI?
if so please say it :)
#2

seen it

iv seen this before...
unit has no attack but an ability called shoot arrow
when auto cast is on she attacks normaly but uses a custom arrow that flies forwards...

its in a spell map on this site...
search arrow in the system section and i think you'll find it...

should help you... if not i'll look it up for you...
#3
sorry for bump this tread up but i mean like silencer (from dota) or something an effect on your normall attack :)
#4
Well, it's very complex, needs many triggers, and if you want it in GUI, it is very buggy.
To start with, every autocast-ability has different order strings like "flamingarrowson", "flamingarrowsoff", these are used when you right click on the ability button, you know... This way, you can detect, and catch the unit's order in the trigger:

Event
Unit is issued an order
Cond
(Level of Flaming Arrows for Triggering Unit) > 0
Actions
Set UnitVar = Triggering Unit
If Issued order == "flamingarrowson"
Set Ordered = "on"
If Issued order == "flamingarrowsoff"
Set Ordered = ""

(Ordered is a string variable, but you can also use an integer var, and set the values to 0 and 1, or whatever. UnitVar is a unit variable, just to store that unit.)
Now, in an other trigger, you detect if the unit attacks an other unit:

Event
A unit is attacked
Cond
Attacking Unit == UnitVar
Ordered is not equal to "" (empty string)
Actions
Here goes the effect you want...

Now we detected if a unit is autocasting, but the effect still doesn't occur when you CAST the ability. So you need an other trigger for casting:

Event
A unit starts the effect of an ability
Cond
Ability being cast == Flaming Arrows
Actions
Here goes the effect you want...


Well that's it. But as i said, its buggy. JASS would solve all the problems.
#5
Shouldnt you be able to detect on cast? Or do autocasts not fire A Unit xxxs an Ability?
#6
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?
--donut3.5--
#7
PurplePootShouldnt you be able to detect on cast? Or do autocasts not fire A Unit xxxs an Ability?

No they don't.
donut3.5Couldn'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?

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...

As I said, JASS would do it.
#8
woha that is complex :shock:
I dont understand JASS at all, i already read the jass tutorial but still dont get it, thanks for your help :)
Maybe i need to reread the tutorial?
#9
Even if you detect for the buff as the unit takes damage, you can't store damage with that method, as it returns 0.
#10
paskovich...
As I said, JASS would do it.

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. :)
Even if hugotje does not know JASS YET (probably it will change if he gets deeper into spellmaking :wink: ).
#11
Here:
//======================================================================
//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

As you see, there are three triggers in one. Sry i won't explain it. Analize the code and you will understand everything...
But there are a few things to be done:
1. Be sure, the ability does some damage, no matter if it deals 0.5, but make sure it does.
2. Do not flush the handles from units in other triggers, as it will interfere with this one.
#12
Ah, yes, I think I understand it, thanks! :)
Not that easy... well, but you should be able to do the projectil damage effects like this:
//====================================================================== 
//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
...

I made comments out of lines that should not be necessary if the condition works as I want it to work. Of course you can also delete the corresponding lines in the "gets attacked" trigger, which save the handles "DamageTrigger" and "DamageSource" as well then. Oh and the unit in the condition leaks, doesn't it? What do you think, does it work (did not try it out myself until now)?
#13
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! :D This makes it 99% (i haven't found any) bugless.

In which condition does the unit leak?

And, it works properly! I wouldn't release such a complex code without testing it... :P

Oh, and i just realized that the DamageTrigger's function name is ****. ??? Somehow it changed. Ok i'll edit the code.

LOOOOOL!!! :D:D It recognized the Spells(_)Hit as a vulgar word :D and changed it to ****. :D:D
#14
Hey paso, someone who listens to TFK wooooh, i dont listen to them anymore, but they still rock.

As for the spell, use the Event: Unit takes damage, and then check if they have the buff after taking the damage, it will work, but could be buggy if the unit is attacked by a large amount of units, then it will proc multiple times
#15
Paskovitch's ScriptEVENT_UNIT_DAMAGED


he uses it with some JASS, more *ahem* specific methods of checking that the attacker is the correct unit.