• 🏆 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!

Order dummy to cast spell problem...

Status
Not open for further replies.
Level 14
Joined
Aug 8, 2010
Messages
1,022
Hello! I want to ask if there is a way to order a dummy not to cast 'Human Priest - Inner Fire' or 'Mountain King - Storm Bolt', but order it to cast a custom spell. In my case, i have the 'Speed Bonus' item ability. I am talking about the action 'Unit - Issue order targeting a unit'. I know you will say to just recreate the spell with triggers, but i can solve many problems with the max speed of a unit by just ordering a dummy to cast that Speed Bonus ability.

+rep will be given! Thanks in advance!
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
Can't you do?:

JASS:
call IssueTargetOrderById(udg_yourCastingUnit, 'Alsp', udg_targetedUnit)

Here you order yourCastingUnit to ('Alsp' = Item Temporary Speed Bonus) targetedUnit

EDIT: not sure if this will work, haven't tested it yet...
You might need to do this:

JASS:
call UnitAddAbility(udg_yourCastingUnit, 'Alsp')
call SetUnitAbilityLevel(udg_yourCastingUnit, 'Alsp', 1)
call IssueTargetOrderById(udg_yourCastingUnit, 'Alsp', udg_targetedUnit)
call UnitRemoveAbility(udg_yourCastingUnit, 'Alsp')
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
I don't understand - 'Alsp' is the custom ability name or something else? Btw - do i have to write it with the quotes?

Yes you have to write it with quotes. (It's actually an integer ^,^ but I won't bother you with that...)

EDIT: I'm not sure if this will work because you are adding a item ability to a unit and then you are casting that item ability...
Haven't tested it yet, but in theory it should work right ^.^? Since the item ability is an ability.

Here is where the magic happens: go into your object editor and press control + D

Voila you can see the raw codes of any objects and use it in Jass script or in GUI custom script (which is basically Jass script)...

Another usefull tip: if you have JNGP installed, go into your trigger editor, click on the header of your map and there should be a button called function list.
From there you can search for a Jass native function with the search box to see how it should be used.
(The header is the icon of your map with the name of your map next to it. Which is located on top of all the trigger category's)
 
Level 14
Joined
Aug 8, 2010
Messages
1,022
Ah...i didn't explained carefully. The speed bonus WAS a item ability, then i set 'Stats - Item Ability' equal to 'False'. I i wanted to say is that the spell WAS for an item, but now, it's for a unit. :) Btw - i tried the 'control + D' thingy and then - a sorcery happen! :O I saw the codes of the spells. :)))

And... i don't have JNGP. Can you give me a link to download it? :)
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
Ah...i didn't explained carefully. The speed bonus WAS a item ability, then i set 'Stats - Item Ability' equal to 'False'. I i wanted to say is that the spell WAS for an item, but now, it's for a unit. :) Btw - i tried the 'control + D' thingy and then - a sorcery happen! :O I saw the codes of the spells. :)))

And... i don't have JNGP. Can you give me a link to download it? :)

JNGP stands for JassNewgenPackage. Here's a complete guide on how to install and set it up:

http://www.hiveworkshop.com/forums/...456/how-download-install-confige-jngp-160547/

It also adds a lot of usefull extra functionality to the standard world editor.
Once you've installed it, it is a lot easyer to learn how Jass works with the function list...
Also, if you want to learn how to execute a specific function in Jass simply create it in GUI, then convert that GUI to custom text and you can see which function is being used.
Be aware that a lot of functions that are being called through GUI are so called BJ natives. Here is an example:

Lets say I want to add an ability to a unit whenever it enters playable map area. In GUI it will look something like this:

  • add ability
    • Events
      • Unit - A unit enters (Playable map area)
    • Conditions
    • Actions
      • Unit - Add Acid Bomb to (Triggering unit)
If I convert this to custom text with Edit -> Convert to Custom Text (You can reverse this by selecting the trigger and pressing Control + Z)
It will look something like this:
JASS:
function Trig_add_ability_Actions takes nothing returns nothing
    call UnitAddAbilityBJ( 'ANab', GetTriggerUnit() )
endfunction

//===========================================================================
function InitTrig_add_ability takes nothing returns nothing
    set gg_trg_add_ability = CreateTrigger(  )
    call TriggerRegisterEnterRectSimple( gg_trg_add_ability, GetPlayableMapRect() )
    call TriggerAddAction( gg_trg_add_ability, function Trig_add_ability_Actions )
endfunction

If you search for UnitAddAbilityBJ in the function list it'll show this:
JASS:
function UnitAddAbilityBJ takes integer abilityId, unit whichUnit returns boolean
    return UnitAddAbility(whichUnit, abilityId)
endfunction

So as you can see, the BJ simply calls UnitAddAbility. This is pretty useless and takes up time. In order to optimize it we simply call UnitAddAbility ourselves...
So now the script looks something like this:

JASS:
function Trig_add_ability_Actions takes nothing returns nothing
    call UnitAddAbility( GetTriggerUnit(), 'ANab' )
endfunction

//===========================================================================
function InitTrig_add_ability takes nothing returns nothing
    set gg_trg_add_ability = CreateTrigger(  )
    call TriggerRegisterEnterRectSimple( gg_trg_add_ability, GetPlayableMapRect() )
    call TriggerAddAction( gg_trg_add_ability, function Trig_add_ability_Actions )
endfunction

Now I'll explain how the event and actions work:

This part basically is what creates, initializes and puts together the GUI trigger:

JASS:
function InitTrig_add_ability takes nothing returns nothing
    set gg_trg_add_ability = CreateTrigger(  )
    call TriggerRegisterEnterRectSimple( gg_trg_add_ability, GetPlayableMapRect() )
    call TriggerAddAction( gg_trg_add_ability, function Trig_add_ability_Actions )
endfunction

function InitTrig basically means that whenever add_ability exists it will execute that function. So function InitTrig_add_ability will be executed if add_ability exists.

Now what it does is set a variable called gg_trg_add_ability to be a trigger.
gg_trg_add_ability now is the actual trigger. And you can use this to add events and actions to that trigger.

TriggerRegisterEnterRectSimple adds the event a unit enters a region. As you can see this function is also in red because it also calls other functions. In the function list it shows this:

JASS:
function TriggerRegisterEnterRectSimple takes trigger trig, rect r returns event
    local region rectRegion = CreateRegion()
    call RegionAddRect(rectRegion, r)
    return TriggerRegisterEnterRegion(trig, rectRegion, null)
endfunction

as you can see a local region is created and then used inside the function TriggerRegisterEnterRegion. We're just going to use that function instead to optimize it. So to optimize it we'll use:
JASS:
TriggerRegisterEnterRegion(gg_trg_add_ability, GetPlayableMapRect, null)

As you might have noticed GetPlayableMapRect is also unnessecary. Check the function list and it shows:
JASS:
function GetPlayableMapRect takes nothing returns rect
    return bj_mapInitialPlayableArea
endfunction

Now let's use that instead:
JASS:
TriggerRegisterEnterRegion(gg_trg_add_ability, bj_mapInitialPlayableArea, null)

Now the entire function should look something like this:

JASS:
function Trig_add_ability_Actions takes nothing returns nothing
    call UnitAddAbility( GetTriggerUnit(), 'ANab' )
endfunction

//===========================================================================
function InitTrig_add_ability takes nothing returns nothing
    set gg_trg_add_ability = CreateTrigger(  )
    call TriggerRegisterEnterRegion(gg_trg_add_ability, bj_mapInitialPlayableArea, null)
    call TriggerAddAction( gg_trg_add_ability, function Trig_add_ability_Actions )
endfunction

call TriggerAddAction simply adds the actions to the trigger that need to be executed when the event starts. So function Trig_add_ability_Actions will be added to gg_trg_add_ability and will be called when the event is started.

As you can see Jass is actually quite simple. And it allows you to create triggers which can be way faster then GUI since GUI uses a lot of function calls which are unnessecary.
(This was just a simple explenation how triggers work in Jass and how to optimize them)

I hope you start learning Jass, it's way more efficient and gives you more power then GUI ^.^
 
Last edited:
Level 14
Joined
Aug 8, 2010
Messages
1,022
@Hashjie - hm... i think i understand what you say at 95%. From now on, Jass is not a magical thing, created by letters and numbers that i don't understand. But still - i think it is way too early for me to begin learning jass... i can't yet create MUI spells with GUI. Actually, i know HOW it must be done, but i need to practice because i still make mistakes. To be honest - i have 4 MUI triggers at all. (you can check my 2 spells in my signature :p). I have a map (using a lot of custom MUI and GUI abilities) and after i finish it, i think ill be ready for Jass! I will bookmark your post. It will definitely help me one day! Thank you very much for the time spend! :)

@-Kobas- - i want to use ability because if i add movement speed with triggers and then remove it with triggers, terrible things can happen. For example - i have a unit with 450 MS (Movement Speed). I have a spell that gives 100 MS. Max MS is 522. Look what happens when i cast the spell : 450MS -> spell is casted -> adds 100 ms -> MS can't be 550, so it's reduced to 522 -> effect disappears -> MS is 522-100=422 instead of 450.

Thats why. :)
 
Level 14
Joined
Aug 8, 2010
Messages
1,022
Dude... i can't do sorceries with jass. :D But what if the normal speed of unit is 200, it has a buff that makes it 250 and the ability which makes it 350 for example. When the effect ends, the MS of the caster will be 200 (the normal speed of the caster WITH the buff that gives 50 MS) or 250 (the normal speed of the caster WITH the 50 MS adding buff)

With one word - will that ability neglect the MS of the buff?
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
  • T
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
    • Actions
      • Custom script: local real ms = GetUnitMoveSpeed(GetTriggerUnit())
      • Custom script: call SetUnitMoveSpeed( GetTriggerUnit(), ms + 100.00 )
      • Wait 5.00 seconds
      • Custom script: call SetUnitMoveSpeed( GetTriggerUnit(), ms )
o_O?

@CoLd Bon3:

This script simply creates a local real variable and sets it to the movement speed of the triggering unit.

Then it sets the movement speed of the unit to the movement speed of the unit + 100.

Then wait 5 seconds.

Then set the movement speed of the unit to the movement speed of the unit back again.
It's so simple ^.^ GetUnitMoveSpeed(GetTriggerUnit()) = get the movement speed for triggering unit (duh)

SetUnitMoveSpeed( GetTriggerUnit(), ms + 100.00) = set the movement speed for the unit for triggering unit to ms (the variable that contains the movement speed in the previous line) + 100
Here are the functions from the function list:

JASS:
native SetUnitMoveSpeed takes unit whichUnit, real newSpeed returns nothing
constant native GetUnitMoveSpeed takes unit whichUnit returns real

With this you won't even need the buff since you can set and get the movement speed yourself...

For example:
local real variable ms = 200 (movement speed of the unit when the effect of the ability started)
set the movement speed to ms + 100 = 300
wait 5 seconds
set the movement speed back to ms = 200

With Jass you can also create a loop that within those 5 seconds, if the movement speed of the unit alters, calculate the difference and make sure it's set accurate again.
So if for example within the 5 seconds the unit's movement speed is higher, do something like: set some variable = GetUnitMoveSpeed(GetTriggerUnit()) - ms.
This would be the difference that's added within these 5 seconds. then you simply do: when the 5 seconds finish set it to ms + variable. Just an example...
It's better to make everything trigger based though ;) More customization...

EDIT:
JASS:
GetUnitMoveSpeed(GetTriggerUnit())
-> Gets the movement speed + all buffs applied

JASS:
GetUnitDefaultMoveSpeed(GetTriggerUnit())
-> Gets the default movement speed

Now you can simply do something like:
JASS:
local real ms = GetUnitMoveSpeed(GetTriggerUnit())
call SetUnitMoveSpeed(GetTriggerUnit(), ms + 100)
wait 5 sec
if your unit still has buff
then
call SetUnitMoveSpeed(GetTriggerUnit(), ms)
else
call SetUnitMoveSpeed(GetTriggerUnit(), GetUnitDefaultMoveSpeed)

Shouldn't be that hard to figure out :)
 
Last edited:
Level 14
Joined
Aug 8, 2010
Messages
1,022
I think i get it. Now i will go to sleep. Tomorrow i will test it and i will tell you if it works. :)

------- EDIT -------
I tried that, but i have failed to achieve something. Maybe if you explain me what you exactly do, i can make that in GUI. I still don't understand jass very well.
 
Last edited:
Level 14
Joined
Apr 20, 2009
Messages
1,543
I think i get it. Now i will go to sleep. Tomorrow i will test it and i will tell you if it works. :)

------- EDIT -------
I tried that, but i have failed to achieve something. Maybe if you explain me what you exactly do, i can make that in GUI. I still don't understand jass very well.

  • Start triggered buff
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to (==) Your Ability
    • Actions
      • Set TriggeringUnit = (Triggering unit)
      • Set ms = (Current movement speed of TriggeringUnit)
      • Unit - Set TriggeringUnit movement speed to ((Current movement speed of TriggeringUnit) + 100.00)
      • Countdown Timer - Start Timer as a One-shot timer that will expire in 5.00 seconds
  • Stop triggered buff
    • Events
      • Time - Timer expires
    • Conditions
    • Actions
      • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (TriggeringUnit has buff Speed Bonus) Equal to (==) True
        • Then - Actions
          • Unit - Set TriggeringUnit movement speed to ms
        • Else - Actions
          • Unit - Set TriggeringUnit movement speed to (Default movement speed of TriggeringUnit)
At this moment it's not MUI, but you told me that you know how to make GUI triggers MUI... ^.^ I'm lazy :p
Either ways this is basically the same as the Jass script above.
All you have to do is make sure it's MUI, right now if 2 units cast that ability within 5 seconds from each other, shit is starting to get ugly.

Tip: local variables or hashtables ftw :)

EDIT: You might also want to check if the unit has a speedbuff before setting ms... Just a subtle hint ;)
 
Last edited:
Level 14
Joined
Aug 8, 2010
Messages
1,022
Am i getting in right? In the 'Stop triggered buff' in the If/Then/Else in the conditions i should add all the buffs (under 'Or - Any conditions are true') in the map that add movement speed. Am i right? :? So that if the unit has any of them, the trigger won't set the unit's speed to default?
 
OMG just use:
  • Shit
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • Custom script: local real ms = GetUnitDefaultMoveSpeed(GetTriggerUnit())
      • Custom script: call SetUnitMoveSpeed( GetTriggerUnit(), ms + 100.00 )
      • Wait 2.00 seconds
      • Custom script: call SetUnitMoveSpeed( GetTriggerUnit(), ms )
This time you will increase default unit ms by some value (if possible) and after some time reduce it to old value.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
OMG just use:
  • Shit
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • Custom script: local real ms = GetUnitDefaultMoveSpeed(GetTriggerUnit())
      • Custom script: call SetUnitMoveSpeed( GetTriggerUnit(), ms + 100.00 )
      • Wait 2.00 seconds
      • Custom script: call SetUnitMoveSpeed( GetTriggerUnit(), ms )
This time you will increase default unit ms by some value (if possible) and after some time reduce it to old value.

Let's say the triggering unit has a buff which already increases movespeed.
Wouldn't this override the buff with the default move speed of the unit?
Let's say for example:

The unit has 200 default move speed. A buff adds 30 move speed. The unit now has a total of 230 move speed.
When this trigger get's executed it will get the default move speed which is 200.
Then it sets the move speed of the unit to the default + 100 move speed, which is then 300.
Then it waits 2 seconds and the move speed is being set back to 200. Now where is that 230 move speed of the buff?
The buff still exists on the unit but the move speed enhancement is gone...

Correct me if I'm mistaken.

EDIT:
Am i getting in right? In the 'Stop triggered buff' in the If/Then/Else in the conditions i should add all the buffs (under 'Or - Any conditions are true') in the map that add movement speed. Am i right? :? So that if the unit has any of them, the trigger won't set the unit's speed to default?
If my theory above is correct then yes, however there still is one problem.
What if the buff is added to the unit after the trigger gets the movement speed of the unit + buffs and before the timer is expired?
Exactly, the speed of the buff will still not be added to the movement speed.
So in order to do this correctly you'd probably have to use a loop that checks after that the movement speed of the unit + the buff is retrieved and between those 5 seconds, if the buff is added to the unit.
If it is, then the movement speed + buffs should be retrieved before the unit movement speed is set.
So that ms can be re-defined before the movement speed bonus is removed thus keeping the movement speed bonus of the unit.

This can probably be done with a continueus timer that checks for buffs every ... seconds which get stopped after 5 seconds and then sets the movement speed.
(Just an example of how this can be done for GUI users)

Yet again, please correct me if I'm mistaken. It seems so logical to me...
 
Last edited:
Level 14
Joined
Apr 20, 2009
Messages
1,543
Buff will still edit default ms, so there is nothing wrong with code.
It's 100% safe and true.

I just tested that.

My apoligies then. I thought that when setting the movement speed of the unit the buff will not be applied. I guess I was wrong.

Thank you, I learned a valuable lesson here.
 
Level 14
Joined
Aug 8, 2010
Messages
1,022
Sooo... i can use -Kobas-'s script and it will be 100% safe? :?
  • Shit
  • Events
  • Unit - A unit Dies
  • Conditions
  • Actions
  • Custom script: local real ms = GetUnitDefaultMoveSpeed(GetTriggerUnit())
  • Custom script: call SetUnitMoveSpeed( GetTriggerUnit(), ms + 100.00 )
  • Wait 2.00 seconds
  • Custom script: call SetUnitMoveSpeed( GetTriggerUnit(), ms )
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
Sooo... i can use -Kobas-'s script and it will be 100% safe? :?

Yes, because apparantly if you set the movement speed of the unit to the default speed.
The buff will still affect it, only the default speed of the unit will be changed.
Any movement speed buff will still affect the default movement speed of the unit.

-Kobas- said:
I just tested that.
 
Status
Not open for further replies.
Top