• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[General] How to get Spell Ability ID with custom script

Status
Not open for further replies.
Level 12
Joined
Feb 5, 2018
Messages
521
  • Custom script: local boolean id = GetSpellAbilityId(GetAbilityBeingCast())
It says too many given arguments.
 
Level 12
Joined
Feb 5, 2018
Messages
521
I made it like this:

  • Custom script: local ability a = BlzGetUnitAbility(GetTriggerUnit(), GetSpellAbilityId())
I am trying to make a spell mirror, which reflects any spell back to the caster.
So it is important to have everything stored.
 
Level 12
Joined
Jan 30, 2020
Messages
875
Hello there !

I don't understand why you complicate things.
As JAKEZINC just pointed out, you can easily get the ability id with the provided native. This ability id will be easier for you to use than the ability itself.

  • Custom script: local integer AbilityID = GetSpellAbilityId()
Note this native will give you the ability that fired the trigger that uses these events :

JASS:
// EVENT_UNIT_SPELL_CHANNEL
// EVENT_UNIT_SPELL_CAST
// EVENT_UNIT_SPELL_EFFECT
// EVENT_UNIT_SPELL_FINISH
// EVENT_UNIT_SPELL_ENDCAST
// EVENT_PLAYER_UNIT_SPELL_CHANNEL
// EVENT_PLAYER_UNIT_SPELL_CAST
// EVENT_PLAYER_UNIT_SPELL_EFFECT
// EVENT_PLAYER_UNIT_SPELL_FINISH
// EVENT_PLAYER_UNIT_SPELL_ENDCAST

Note that if you can get the name of the ability with this native: constant native GetObjectName takes integer objectId returns string

Hope this helps.

EDIT : As a side note, GetSpellAbilityId() does not return a boolean like you thought in your custom script, but an integer.
 
Level 12
Joined
Feb 5, 2018
Messages
521
Thank you both for your help. I am pretty close to making it work now. There a few issues remaining at hand.
  • SpellMirror
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Unit-type of (Target unit of ability being cast)) Equal to Footman
    • Actions
      • Custom script: local integer AbilityID = GetSpellAbilityId()
      • Custom script: local unit u = GetSpellTargetUnit()
      • Custom script: local unit uu = GetTriggerUnit()
      • Custom script: local unit uuu = null
      • Custom script: local location l = GetUnitLoc(GetSpellTargetUnit())
      • Custom script: local location ll = GetUnitLoc(GetTriggerUnit())
      • Custom script: local player p = GetOwningPlayer(u)
      • Custom script: local player pp = GetOwningPlayer(uu)
      • -------- Too many arguments for location --------
      • Custom script: call CreateNUnitsAtLoc( 1, GetUnitTypeId(uu), GetPlayerId(p), GetLocationX(l), GetLocationY(l), bj_UNIT_FACING )
      • -------- ------ --------
      • Custom script: set uuu = GetLastCreatedUnit()
      • Custom script: call UnitAddAbilityBJ( AbilityID, uuu )
      • -------- Unexpected "," --------
      • Custom script: call UnitApplyTimedLifeBJ( 2.00, 'BTLF', (uuu) )
      • -------- -------- --------
      • Custom script: call IssueTargetOrderBJ( uuu), "AbilityID", (uu)
      • Custom script: call RemoveLocation (l)
      • Custom script: call RemoveLocation (ll)
Problem 1) Too many given arguments for location. I tried GetLocation(l) and it didn't work either.
Problem 2) On the row call IssueTargetOrderBJ( uuu), "AbilityID", (uu) It says unexpected "," meaning there is something off with the code line.

I honestly can't even tell if you can order the unit to cast the spell based on the AbilityID, but I hope this is the right way of doing it.

Just noticed it is still also missing the integer to get the ability level, but that shouldn't be too hard to add.
And yes, this could be probably done without locals and with some combination of GUI and few lines of custom scripts, but I am trying to push my limits here and learning something.
 
Level 12
Joined
Jan 30, 2020
Messages
875
Hello again.

First of all, as all your actions are custom script lines, maybe it would be easier for you to convert this specific trigger to custom text (from the Edit Menu of the Trigger Editor), to make it easier to work with.

Next for your errors, you need to look inside blizzard.j to see how BJ functions work, and what variables they take as arguments.

Here is the CreateUnitsAtLoc function (it is a BJ function even if it has no suffix, because it is not a native) :
JASS:
function CreateNUnitsAtLoc takes integer count, integer unitId, player whichPlayer, location loc, real face returns group
    call GroupClear(bj_lastCreatedGroup)
    loop
        set count = count - 1
        exitwhen count < 0
        call CreateUnitAtLocSaveLast(whichPlayer, unitId, loc, face)
        call GroupAddUnit(bj_lastCreatedGroup, bj_lastCreatedUnit)
    endloop
    return bj_lastCreatedGroup
endfunction

Looking at the variables it takes, you can see that you are using the wrong ones : you pass it a playerid rather than a player, and the location coordinates (reals) instead of the location itself.
Your line should look like call CreateNUnitsAtLoc( 1, GetUnitTypeId(uu), p, l, bj_UNIT_FACING )

Now let's look at UnitApplyTimedLifeBJ :
JASS:
function UnitApplyTimedLifeBJ takes real duration, integer buffId, unit whichUnit returns nothing
    call UnitApplyTimedLife(whichUnit, buffId, duration)
endfunction

This one seems alright, but for some reason you put the unit variable between brackets, so this might be the cause.

But I can see another line that is just completely wrong :
  • Custom script: call IssueTargetOrderBJ( uuu), "AbilityID", (uu)
For some strange reason, you added brackets to the two unit variables, but removed the brackets for the function call !!!!
Also the function does not use the ability id but the order string of the ability (you can find it in the object editor, in your ability field called "Text - Order string - Use / Turn On".

It should be all IssueTargetOrderBJ( uuu, "*put your ability order string here*", uu)

Hope this will help.
 
Level 12
Joined
Feb 5, 2018
Messages
521
Also the function does not use the ability id but the order string of the ability (you can find it in the object editor, in your ability field called "Text - Order string - Use / Turn On".

Yea, but I want the unit to reflect any spell back, so now that it is stored with the abilityID, it can be used as an order, no?

If I need to store all the spells invidually it will be too time consuming.

Could I instead then store the orderID too and issue the order to the dummy unit that reflects the spell?
 
Level 12
Joined
Jan 30, 2020
Messages
875
No.

Abilities ids are used to test what ability was used by a unit / hero, or to check if a unit has an ability, or what is the level of their ability, etc...

If you want to reflect the ability, send it back to the caster, you need to give the "mirroring unit" the ability using this ability id.
Then you need to give the mirror unit the target (initial caster) order.
But that order has nothing to do with the ability id.

So you have two options, or you store all the orders of the abilities you want to be "mirrorable" in an array, and then use a set of tests with if then else like "if abilityid='A000') then set order="ensnare" but you will need one line for each ability.

The other thing you could do is use a different event like A unit is issued a target order and get the order with GetIssuedOrder, but then you won't have the ability id to add the ability to your mirroring unit. And this one is worse as each ability has a single order string when it can be ordered, but an order can cast different abilities.

then I would advise you the first solution.

Maybe you could also remove the buff recieved by the mirroring unit so that even if not spell immune, it does not suffer from the negative effects of the ability it was the target of.

This is important, because if the ability is something like stormbolt, your mirroring unit will be stun and won't be able to send the stormbolt back.

I understand there is a lot to assimilate when starting to use Jass, but don't give up, once you understand its principles, everything becomes less confusing, and possibilities become really unlimited.
 
Status
Not open for further replies.
Top