• 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.
  • It's time for the first HD Modeling Contest of 2025. Join the theme discussion for Hive's HD Modeling Contest #7! Click here to post your idea!

[Spell] Simplest spell that uses vjass?

Status
Not open for further replies.
Level 26
Joined
Aug 18, 2009
Messages
4,097
Well for example make a spammable "Spawn Bomb" ability, which creates an explosive at the target location that goes off after a few seconds. Save the ability level and the original caster, so you can associate the to be dealt damage to the caster and you can vary the strength. Also show the remaining ticks periodically as floating text above the bomb. Make another ability "Defuse Bomb", which gets rid of the bomb and what belongs to it.
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
Yes. The variables are the attributes of the struct instance, in this case abilityLevel, caster, remaining ticks or what else you need to store. Static variables are not assigned to the struct instance but count for all, so that's just a scoped global variable. This can be for example the level->damage mapping since that rule is the same for every bomb.

Methods are functions you apply to struct instances. Maybe "destroy", so the "this" keyword represents the instance you enter the function with. Static methods on the other hand are again general, just scoped functions for your convenience and therefore they have no implicit "this". When you start a timer to run a function handler, this can only be done on functions which take no parameters, so no non-static-methods. Then you have to write a static method and retrieve the struct instance(s) by some mapping you did beforehand and either put the actions therein directly or call other methods with the instances you gained.
 
Level 3
Joined
Sep 9, 2009
Messages
658
Okay...now I'm confused. How do I incorporate the timer? And can anyone comment on this so far? But please ignore the fact that the spell isn't inside the conditions block or that I'm using TriggerRegisterAnyUnitEventBJ.

JASS:
scope TBomb initializer Init
    globals
        private constant integer AID = 'A000'
        private constant integer BOMB = 'e001'
    endglobals
    
    struct Bomb
        unit u = GetTriggerUnit()
        unit dummy
        player p = GetOwningPlayer(u)
        real x = GetSpellTargetX()
        real y = GetSpellTargetY()
        static real BaseDamage = 300
        real Damage = GetUnitAbilityLevel(u, AID) * BaseDamage
        
        public method MakeBomb takes nothing returns nothing
            set dummy = CreateUnit(p, BOMB, x, y, 270)
        endmethod
    endstruct
    
    private function Actions takes nothing returns nothing
        local Bomb b = Bomb.create()
        
        call b.destroy()
    endfunction
    
    private function Conditions takes nothing returns boolean
        if GetSpellAbilityId() == AID then
            call Actions()
        endif
        return false
    endfunction

//===========================================================================
    private function Init takes nothing returns nothing
        local trigger t= CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( t, Condition( function Conditions ) )
        set t = null
    endfunction
endscope
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
The variable assignments you have done should rather be in the constructor method of the struct and I would suggest to keep the event responses out because you may want to create the bomb in another context and from the struct's point of view, you do not really see the relation as you have not even put the event creation inside the struct.

Methods are public by default. Unless the syntax checker strikes, you do not have to return a boolean from a condition function. The timer can be integrated as shown.

JASS:
scope TBomb initializer Init
    globals
        private constant integer AID = 'A000'
        private constant integer BOMB = 'e001'
        private hashtable ht = InitHashtable()
    endglobals
   
    struct Bomb
        static real baseDamage = 300
        static real tickInterval = 1.

        unit u
        unit dummy
        integer level
        player p
        real x
        real y
        real damage
        timer tickTimer

        static method onTickTimer takes nothing returns nothing
            local thistype this = LoadInteger(ht, GetHandleId(GetExpiredTimer()), 0)

            //...
        endmethod

        static method create takes integer level, unit caster, real targetX, real targetY returns thistype
            local thistype this = allocate()

            set .damage = level * baseDamage
            set .level = level
            set .u = caster
            set .p = GetOwningPlayer(caster)
            set .tickTimer = CreateTimer()
            call SaveInteger(ht, GetHandleId(.tickTimer), 0, this)

            set .dummy = CreateUnit(.p, BOMB, targetX, targetY, 270)

            call TimerStart(.tickTimer, .tickInterval, true, function thistype.onTickTimer)

            return this
        endmethod
    endstruct
   
    private function Conditions takes nothing returns nothing
        if GetSpellAbilityId() == AID then
            return
        endif

        call Bomb.create(GetUnitAbilityLevel(GetTriggerUnit(), AID), GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY())
    endfunction

//===========================================================================
    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger(  )

        call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( t, Condition( function Conditions ) )

        set t = null
    endfunction
endscope
 
Status
Not open for further replies.
Top