• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[vJASS] Need help with a spell....again

Status
Not open for further replies.
Level 4
Joined
Apr 7, 2012
Messages
63
Ok,as you some of you know I am still new to Jass and stuff so I'm trying to make a spell that if you are attacked theres a chance that the enemy who is attacking you will be stunned,almost like Tiny's passive.

So far I've got this.
JASS:
 private function Actions takes nothing returns nothing
        local location SpellLoc = GetSpellTargetLoc()
        local real spellX = GetLocationX(SpellLoc)
        local real spellY = GetLocationY(SpellLoc)
        local unit caster = GetTriggerUnit()
        local integer level = GetUnitAbilityLevel(caster, SPELL_ID)
        local unit f
        local integer creeps = 0
        

        call GroupEnumUnitsInRange(all,spellX,spellY,Range(level),b)
        set SPassive = StunPassive(all)
        loop
            set f = FirstOfGroup(copy)
            exitwhen(f == null)
            call GroupRemoveUnit(copy,f)
            if IsUnitAlly(f,GetOwningPlayer(caster)) then
               set creeps = creeps+1
            else
               call DoNothing
            endif
        endloop
I already have filters and that stuff all I need is the action and how to preload the ability.Also I'm not sure if this is totally correct.
JASS:
call DoNothing
Just want to be sure.
Ok so I have the group sort of if it was an active spell so I also need help there and then I have this.
JASS:
loop  
                set f = FirstOfGroup(all)
                exitwhen (f == null)
                call GroupRemoveUnit(all, f)
                if IsUnitEnemy(f, GetOwningPlayer(caster)) then
                    call UnitDamageTarget(caster, f, Damage(level), true, false, A_TYPE, D_TYPE, null)
                endif
            endloop
Ok so this damages the unit as you've realized,but I only want it to be stunned for like 0.5 or 1 second.

Please don't rate my skill in vJass I know I still suck:/

Was I supposed to post this in the World Editor Help Zone?

Credits---
The Hiveworkshop for all their helpful tutorials on vJass and Jass.
 
Last edited:
Level 20
Joined
Jul 14, 2011
Messages
3,213
Why do you need a group and a spell and stuff?

Event : A unit is attacked
Condition: Level of Ability for Triggering Unit > 0
Condition: Attacking Unit is an Ally of Triggering Unit == false
Action: If Random Integer is less than or equal to *YourTriggerChance* then create a dummy to cast hurl boulder, or storm bolt at the target with a 0.5 duration.

Mess with the duration and ability level however you want. After that, just improve the code.

There's no need to use the "Do Nothing" leave the blank space.

JASS:
function TinyStun takes nothing returns nothing
       local unit Enemy = GetAttackerUnit() // I'm not sure if it's "AttackerUnit", but you know.
       local unit Attacked = GetTriggerUnit()
       local real EnemyX
       local real EnemyY
       local unit dummy
       
If GetRandomReal(0,1) <= 25 then
       set EnemyX = GetUnitX(Enemy)
       set EnemyY = GetUnitY(Enemy)
       set dummy = CreateUnit(...)
       // do your stuff
 
GetAttackerUnit()
If GetRandomReal(0,1) <= 25

--->
GetAttacker()
If GetRandomInt(0,100) <= 25

using a timer system like TimerUtils can do this by pausing the attacker and
giving him a stun sfx, if timer expires, unpause the unit and destroy the sfx...
if you want it very simple but has a little inaccuracy, use locals and TriggerSleepAction...
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
It would be DoNothing() rather than DoNothing, but you don't need to call it at all. The reason it exists in GUI is for the single-line ifs which require you to enter both a Then and an Else. In JASS you can even leave out the else entirely if you so desire.

JASS:
if foo then
    bar
endif

In addition, rather than

JASS:
       local location SpellLoc = GetSpellTargetLoc()
       local real spellX = GetLocationX(SpellLoc)
       local real spellY = GetLocationY(SpellLoc)

you can have

JASS:
local real spellX = GetSpellTargetX()
local real spellY = GetSpellTargetY()

--

You should really use a damage detection system for this. When the unit is damaged, if the damage was from an attack, if the random chance says it should fire,

  • Create a dummy. local unit d = CreateUnit(...)
  • Add a storm bolt ability to the dummy. call UnitAddAbility(d,...)
  • Tell the dummy to cast storm bolt on the unit which should be stunned. call IssueTargetOrder(d,...)
  • Add a life timer to the dummy. call UnitApplyTimedLife(d,'BTLF',2)
 
Level 4
Joined
Apr 7, 2012
Messages
63
Ok so theres one more thing I don't understand.
JASS:
call IssueTargetOrder(unit WhichUnit,string order,widget targetWidget) returns boolean.
Then then you need to fill the brackets.
I'm stuck at the second one "string order," I don't know what the hell I'm supposed to put in there.
Like how do I tell the dummy to cast the spell.
 
Last edited:
Level 19
Joined
Apr 10, 2010
Messages
2,789
Thats the order string of the order you would want them to do. Examples are thunderbolt, charm, stop, etc.
So, if you do call IssueTargetOrder( dummy, "thunderbolt", targ), then it would mean that the dummy unit would cast Storm Bolt to the target unit.

Btw, dont double post. Use the edit button.
 
Level 4
Joined
Apr 7, 2012
Messages
63
Thanks guys
Btw, dont double post. Use the edit button
Okey,will remember next time:)
Ok I understand the order thing,can somebody please give me an example of what Spartipilo mentioned when he said
Condition: Level of Ability for Triggering Unit > 0
I couldn't find anything alike in GUI and I don't know the jass version of it either.
Thanks again for all the help.
This is what I have so far,there's no syntax errors but it still doesn't work,can somebody explain to me why?
JASS:
scope MiniStun initializer Init
function MiniStun_Conditions takes nothing returns boolean
    if ( not ( GetUnitTypeId(GetTriggerUnit()) == 'H003' ) ) then
        return false
    endif
    return true
endfunction

globals
      private constant integer MiniStunId = 'A005'
      private constant integer DummyId = 'o000'
endglobals


private function Actions takes nothing returns nothing
     local unit Enemy = GetAttacker()
     local unit AttackedUnit = GetTriggerUnit()
     local real EnemyX
     local real EnemyY
     local unit dummy
     
     
     if GetRandomInt(0,100) <= 100 then
         set EnemyX = GetUnitX(Enemy)
         set EnemyY = GetUnitY(Enemy)
         call CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DummyId, 0, 0, 0)
         set dummy = bj_lastCreatedUnit
         call UnitAddAbility(dummy,'A005') 
         call IssueTargetOrder(dummy,"thunderbolt",Enemy)
         call UnitApplyTimedLife(dummy,'BTLF',2) 
       endif 
 endfunction      
      

//===========================================================================
function Init takes nothing returns nothing
    local trigger MiniStunTrg = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( gg_trg_MiniStun, EVENT_PLAYER_UNIT_ATTACKED )
    call TriggerAddCondition( gg_trg_MiniStun, Condition( function MiniStun_Conditions ) )
    call TriggerAddAction( gg_trg_MiniStun, function Actions )
endfunction
endscope
 
Last edited:
Level 40
Joined
Dec 14, 2005
Messages
10,532
bj_lastCreatedUnit doesn't work for natives, nor does it need to. There's also little point in having a constant if you don't use it. You should also create the dummy at the position of the attacker.

JASS:
         set EnemyX = GetUnitX(Enemy)
         set EnemyY = GetUnitY(Enemy)
         call CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DummyId, 0, 0, 0)
         set dummy = bj_lastCreatedUnit
         call UnitAddAbility(dummy,'A005')

becomes

JASS:
         set dummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DummyId, GetUnitX(Enemy), GetUnitY(Enemy), 0)
         call UnitAddAbility(dummy,MiniStunId)

You should also make the remaining functions in your scope private, and fix the chance (currently it's ~99%).
 
Level 4
Joined
Apr 7, 2012
Messages
63
I think the event is "A unit is attacked" because Tiny stun's units before being damaged.
I meant the condition,thats the thing I don't understand.
This is what I have so far,can you guys help me improve it if needed please?

JASS:
scope MiniStun initializer Init
private function MiniStun_Conditions takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit()) == 'H003' 
endfunction

globals
      private constant integer MiniStunIdLvl1 = 'A005'
      private constant integer MiniStunIdLvl2 = 'A006'
      private constant integer MiniStunIdLvl3 = 'A007'
      private constant integer DummyId = 'o000'
      private constant integer EarthSkinId = 'A004'
      private constant string MiniStunEffect = "Objects\\Spawnmodels\\Demon\\DemonLargeDeathExplode\\DemonLargeDeathExplode.mdl"
endglobals

private function Chance takes integer level returns integer
    //returns the chance that the unit will be stunned
          return 15+level*2
    endfunction

private function Duration takes integer level returns integer
    //returns the duration that the unit will be stunned
          return level*1
    endfunction

    private function Targets takes unit Enemy returns boolean
    //the units the spell will effect
         return (GetWidgetLife(Enemy) > 0.405) and(IsUnitType(Enemy, UNIT_TYPE_STRUCTURE) == false) and(IsUnitType(Enemy, UNIT_TYPE_MAGIC_IMMUNE) == false) and(IsUnitType(Enemy, UNIT_TYPE_MECHANICAL) == false)  
    endfunction        
    
private function Actions takes nothing returns nothing
     local unit Enemy = GetAttacker()
     local unit AttackedUnit = GetTriggerUnit()
     local real EnemyX
     local real EnemyY
     local unit dummy
     local integer level = GetUnitAbilityLevel(AttackedUnit,EarthSkinId)
     
     if GetRandomInt(0,100) <= Chance then 
          set dummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DummyId, GetUnitX(Enemy), GetUnitY(Enemy), 0)
     endif
     if Duration == 1 then  
         call UnitAddAbility(dummy,MiniStunIdLvl1)
     
     elseif Duration == 2 then
         call UnitAddAbility(dummy,MiniStunIdLvl2)
     
     elseif Duration == 3 then
        call UnitAddAbility(dummy,MiniStunIdLvl3)
     endif                   
         call IssueTargetOrder(dummy,"thunderbolt",Enemy)
         call DestroyEffect(AddSpecialEffectTarget(MiniStunEffect, Enemy, "origin")) 
         call UnitApplyTimedLife(dummy,'BTLF',2) 
 endfunction      
      

//===========================================================================
private function Init takes nothing returns nothing
    local trigger MiniStunTrg = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( MiniStunTrg, EVENT_PLAYER_UNIT_ATTACKED )
    call TriggerAddCondition( MiniStunTrg, Condition( function MiniStun_Conditions ) )
    call TriggerAddAction( MiniStunTrg, function Actions )
endfunction
endscope
 
Last edited:
Level 40
Joined
Dec 14, 2005
Messages
10,532
It would be easier and more easily modified (changing the number of spell levels etc) to store the various spell IDs in an array, or, assuming that you only intend to use one ability base (Storm Bolt, for example) to just have multiple levels on the dummy ability and use SetUnitAbilityLevel.

I'm still not a fan of using EVENT_PLAYER_UNIT_ATTACKED for basically anything other than an anti-teamkilling trigger, but that's your call.
 
Level 4
Joined
Apr 7, 2012
Messages
63
I'm still not a fan of using EVENT_PLAYER_UNIT_ATTACKED for basically anything other than an anti-teamkilling trigger, but that's your call.
Would you reccommend something better?
 
A damage detection system. The reason why is because EVENT_PLAYER_UNIT_ATTACKED can be spammed if a player is in acquisition range and repeatedly spams "stop" with the s hotkey.

EVENT_PLAYER_UNIT_ATTACKED registers when a unit has the "attack" order, rather than when a unit is hit by an attack. I hope that makes sense.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Probably in most cases it would be abuseable or something... But we're talking about a near distance (300) attack which has a chance to result in being stunned, so, it would be hard to spam.
 
Level 4
Joined
Apr 7, 2012
Messages
63
OK,I'll see if it's gonna be a problem.If not I guess I'll keep it that way for now.Thanks
 
Status
Not open for further replies.
Top