• 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] Charging Spell Similar to Charge of Darkness

Status
Not open for further replies.
Level 17
Joined
Feb 11, 2011
Messages
1,860
Hi guys,

I am trying to make a spell like Barathrum's Charge of Darkness, but I am unable to get it completely correct. It works fine, the problem comes when I want the unit to cancel the charge. Here is the code:

JASS:
scope Charge initializer RegisterOrder

    globals
        private constant integer SPELL_ID = 'A000'
        
        private boolean enabled = true
        private group chargingUnits = CreateGroup()
    endglobals

    private struct Charge_Data
        unit caster
        real x
        real y
        real angle
    
        private method destroy takes nothing returns nothing
            call SetUnitAnimation(.caster, "stand")
            set .caster = null
            call .deallocate()
        endmethod
    
        private static method move takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local thistype this = GetTimerData(t)
            local real x = GetUnitX(.caster) + 10 * Cos(.angle)
            local real y = GetUnitY(.caster) + 10 * Sin(.angle)
            
            if IsUnitPaused(.caster) then
                call PauseUnit(.caster, false)
            endif
            
            call SetUnitX(.caster, x)
            call SetUnitY(.caster, y)
            set enabled = false
            call IssueImmediateOrder(.caster, "holdposition")
            set enabled = true
            set x = .x - x
            set y = .y - y
            
            if not (IsUnitInGroup(.caster, chargingUnits)) or (SquareRoot((x*x) + (y*y)) <= 25) then
                call ReleaseTimer(t)
                call .destroy()
            endif
            
            set t = null
        endmethod
    
        private static method create takes nothing returns thistype
            local thistype this = thistype.allocate()
            local timer t = NewTimerEx(this)
            
            set .caster = GetTriggerUnit()
            set .x = GetSpellTargetX()
            set .y = GetSpellTargetY()
            set .angle = Atan2(.y - GetUnitY(.caster), .x - GetUnitX(.caster))
            call GroupAddUnit(chargingUnits, .caster)
            call PauseUnit(.caster, true)
            call SetUnitAnimationByIndex(.caster, 2)
            call TimerStart(t, 0.03, true, function thistype.move)
            
            set t = null
            return this
        endmethod
    
        private static method onInit takes nothing returns nothing
            call RegisterSpellEffectEvent(SPELL_ID, function thistype.create)
        endmethod
    
    endstruct

    private function CheckOrder takes nothing returns boolean
        if enabled and IsUnitInGroup(GetTriggerUnit(), chargingUnits) then
            call GroupRemoveUnit(chargingUnits, GetTriggerUnit())
        endif
        return false
    endfunction
    
    private function RegisterOrder takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_ORDER)
        call TriggerAddCondition(t, Condition(function CheckOrder))
        set t = null
    endfunction
    
endscope
Explanation:
When the unit casts the spell, he is added to a unit group. Each 0.03 seconds, it checks whether the unit is in the group. If it is not, it stops the spell. The unit is removed from the group when he casts another order. Every 0.03 seconds, the hero is issued the "holdposition" order, to stop him from running off and attacking. When this order is issued, I set enabled = false, so the system does not register it as a manual order.

The Problem:
As soon as the spell is cast, it stops. I think it is still somehow registering the "holdposition" order, even though enabled = false.

If I need to explain more, please say so.

Thanks for any help,

Mr_Bean
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
Every 0.03 seconds, the hero is issued the "holdposition" order, to stop him from running off and attacking.
To counter this issue, try order the unit to attack the targeted unit when initially cast the spell:
  • Charge of Darkness
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Charge of Darkness
    • Actions
      • Unit - Order (Triggering unit) to Attack (Target unit of ability being cast)
Since you are using SetUnitX/Y, you don't have to worry about the order cancellation, technically, SetUnitX/Y does not interrupt unit's current order, just do this and the unit will only focus to attack to the targeted unit.

Remember to only initiate this command single-time only (right after it casts the trigger, before this unit is in the Loop), not, once every 0.03 second.
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
Well, order it to move then ?
If you order a unit to move (default order, via Mouse Click), the unit won't go stray away from your order, right ?

Just change the action to this:
  • Charge of Darkness
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Charge of Darkness
    • Actions
      • Set TargetLoc = (Target point of ability being cast)
      • Unit - Order (Triggering unit) to Move To TargetLoc
      • Custom script: call RemoveLocation(udg_TargetLoc)
 
You can't do this:

JASS:
set enabled = false
call IssueImmediateOrder(.caster, "holdposition")
set enabled = true

Because ordering a unit to hold position isn't happening instantaneously.

You can try removing the hold position order and instead giving the unit 0 movement speed while charging, or you can try using a dummy unit.
 
Status
Not open for further replies.
Top