• 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] Channeled Spell & Trigger Init - starting/stopping an effect?

Status
Not open for further replies.
Level 4
Joined
Sep 25, 2005
Messages
71
Was recently a bit puzzled after coming back having not touched the w3edit in what seems like forever. The idea struck me to create a spell that was "charged" like I've seen before - spell is cast, spell begins channeled, effect begins to scale to the end of channeling, and whenever the channeling is broken, the effect occurs to scale of the duration of charging.

Here's what I have so far, a basic event registry with no actual effect taking place:

JASS:
scope chargeBall initializer init

globals
    private constant integer                    ABIL_ID                     = 'A111'
endglobals

struct chargeBall
//effects go here
endstruct

private function checkChargeBall takes nothing returns boolean
//if it's the spell, then do the things
    if GetSpellAbilityId() == ABIL_ID then
        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "effect")
    endif
    return false
endfunction

private function init takes nothing returns nothing
	local trigger localTrigVar = CreateTrigger()
	call TriggerRegisterAnyUnitEventBJ(localTrigVar, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition( localTrigVar, Condition(function checkChargeBall))
	set localTrigVar = null
endfunction

endscope

I'm just a little puzzled where I set up the trigger for stopping the cast, considering I can't compile the trigger being anywhere before the init.
 
I'm just a little puzzled where I set up the trigger for stopping the cast, considering I can't compile the trigger being anywhere before the init.
Why not in init function? :)

JASS:
private function onCast takes nothing returns nothing
endfunction

private function onCancel takes nothing returns nothing
endfunction

private function Init takes nothing returns nothing
    // Attach functions to triggers
endfunction
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
Stopping the cast in like... the unit is not allowed to cast the spell?
Or in like... the unit has stopped casting?

1) A unit is issued an order targeting a point (probably)
Issued order equal to order(spellorderstring) (If you use Channel then this is the exact same as Base-Order-Id)
Actions create a 0 seconds timer that will issue the caster to stop.
JASS:
function IssueUnitToStop_Callback takes nothing returns nothing
    local timer t = GetExpiredTimer()
    call IssueImmediateOrder(LoadUnitHandle(udg_Hashtable, GetHandleId(t), 0), "stop")
    call FlushChildHashtable(GetHandleId(t), udg_Hashtable)
    call DestroyTimer(t)
    set t = null
endfunction
function IssueUnitToStop takes unit whichUnit returns nothing
    local timer t = CreateTimer()
    call TimerStart(t, 0, false, function IssueUnitToStop_Callback)
    call SaveUnitHandle(udg_Hashtable, GetHandleId(t), 0, whichUnit)
    set t = null
endfunction

2) Use the two events "A unit has finished casting an ability" and "A unit has canceled casting an ability"
 
Level 4
Joined
Sep 25, 2005
Messages
71
Why not in init function? :)

onCast creates a struct which has the actual effects of the spell
onCancel releases the effects scaled by the struct

More or less where am I calling the event response here? You say setup the triggers on init, but I need the trigger to react specifically to that single instance, that created struct, if I'm not mistaken, in order to get it correctly instanced? It's not a unit finishes casting any spell, it's "take the effects of that individual spellcast/channel duration as parameters, and if canceled/follow-through cast time is finished, actually do a thing"

Or in like... the unit has stopped casting?

1) A unit is issued an order targeting a point (probably)
Issued order equal to order(spellorderstring) (If you use Channel then this is the exact same as Base-Order-Id)

2) Use the two events "A unit has finished casting an ability" and "A unit has canceled casting an ability"

As in this. I understand how to link the effects to this event, but how do I create another event response that is only valid once the spell has started, so to speak, and is properly instanced?

If the trigger that is referenced when the casting ends (i.e. the charging begins and the spell effect is created, but not "released,") creates a struct that is the effective spell, where and how am I putting this trigger that checks when the -channel- (charging - the unit stops casting a spell event response) that correctly checks the other effect?

If it's just in the init, how am I going to get it to reference the proper struct, more or less? One that is already created?
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
You have to make a boolean for each unit (MUI) that tells if they have started the effect of your spell.

The easiest way is make a hashtable (or use a hashtable that you use for these situations) and have a row for only this value.
Then every unit has that boolean.

I don't know much about vJASS but there was this thing called table that would replace the hashtable.
Don't know what the exact differences are so...
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
I think that the best thing is to set an integer to the time in milliseconds in the hashtable
When the spell is stopped casting or finished casting, you check the difference between the current time and the casting time.
Also set that value back to 0 after the damage is dealt.
When the value is 0, there is no channeling.
 
Level 4
Joined
Sep 25, 2005
Messages
71
It's been months since I really touched JASS and it got to the point wherein I can't seem to figure a few things that are impeding me. Trying the above using a condition to check if it's the correct unit and referencing it within a hashtable, how does one add a method in a struct as a condition for a trigger? Is this even possible?

I'm curious about your implementation of using a hash to check the boolean of the unit. I'm pretty braindead right now. Is there some example pseudo code I could look at to understand your proposal? I genuinely don't remember understanding hashes all that well.
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
The best way to create a condition for a single function/method is to make in inside it:
JASS:
function f takes boolean b returns nothing
    if b then
        //Do nothing.
        return
    endif
    
    //Do actions.
endfunction
If you want to use it for many functions... I don't know... but it is still the best way if you only care about performance.

A hashtable is a simple 2 dimensional array, or a table, that can be used to store different types of data for every cell.
Because WC3 cant do "object array array", you require hashtables to save dynamic data.
However, hashtables can simulate "object array array array array array array array array array array array array array array array array array array array array array array array array" ... until you hit the 255 hashtable limit (because for each increase, you create a new hashtable) or when you will have more keys (from one array) than the possible rows/columns in a hashtable.
But "object array array array array" will be the biggest one you will ever use anyway.

My implementation of the "Is_Casting" thing is pretty simple:
Event -> A unit starts the effect of an ability ->
Condition -> Ability being cast equal to (your ability)
Actions ->
- Save (Current Gametime) in (hashtable) with key (caster) and key (your ability / ability being cast) ////(both can be used)

Event ->
- A unit finishes casting an ability
- A unit cancels casting an ability
Condition -> Ability being cast equal to (your ability)
Actions ->
- If integer from (hashtable) with key (caster) and key (your ability) is greater than 0 Then
---- Set channeltime = Current Gametime - integer from hashtable ////(because you use it more than once, you should save it in a tempvariable)
---- Deal damage related to channeltime
---- Save 0 in (hashtable) with key (caster) and key (your ability) ////(For handles, there is a function that removes the data completely... I don't know if there is a function that can do the same for non-agents.)
 
Status
Not open for further replies.
Top