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

[Solved] Spell Trigger Help

Status
Not open for further replies.
Level 4
Joined
Feb 24, 2018
Messages
71
Hello there ! I would like to add [code=jass] Freezing Field v1.1d to my map but I would like to modify it so the damage is based on the caster's intelligence. The author has been offline so I'm asking here for some assistance. I've just started using JASS so I can import some spells but I don't know how coding works. Thanks !
JASS:
// CONFIGURATION

// Constants

// Main spell raw code
constant function FF_GetSpellID takes nothing returns integer
    return 'A004'
endfunction

// Field Effect
constant function FF_FieldFx takes nothing returns string
    return "war3mapimported\\FreezingField.mdx" 
endfunction

// Explosion Effect
constant function FF_ExpFx takes nothing returns string
    return "war3mapimported\\SnowyBlizzardTarget.mdx"
endfunction

// Explosion Effect delay
constant function FF_ExpDelay takes nothing returns real
    return 0.8
endfunction

// Explosion Interval
constant function FF_Interval takes nothing returns real
    return 0.05
endfunction

// Booleans

function FF_FilterUnit takes player casterowner, unit u returns boolean
    return IsUnitEnemy(u, casterowner) and not IsUnitType (u, UNIT_TYPE_DEAD) and GetUnitAbilityLevel(u, 'Avul') == 0 and not IsUnitType (u, UNIT_TYPE_MAGIC_IMMUNE)
endfunction

// Get spell level

function FF_SpellLvl takes unit caster returns integer
    return GetUnitAbilityLevel (caster, FF_GetSpellID()) // Get the spell level of the caster
endfunction

// Level dependable values

function FF_Duration takes integer level returns real
    return 5.
endfunction

function FF_ExpDmg takes integer level returns real
    return 100. + level*20.
endfunction

function FF_ExpAoE takes integer level returns real
    return 100. + level*20.
endfunction

function FF_FieldAoe takes integer level returns real
    return 400. + level*50.
endfunction

// Attack - Damage - Weapon type

function FF_AttackType takes nothing returns attacktype
    return ATTACK_TYPE_NORMAL
endfunction

function FF_DamageType takes nothing returns damagetype
    return DAMAGE_TYPE_MAGIC
endfunction

function FF_WeaponType takes nothing returns weapontype
    return WEAPON_TYPE_WHOKNOWS
endfunction

// END CONFIGURATION

// SPELL FUNCTIONS

// This is the main function of the spell

function FF_TimerLoop takes nothing returns nothing
    local integer ID
    local integer ID2
    local integer listmax = LoadInteger(udg_FF_Hashtable, -1, 0 )
    local unit caster
    local integer i = 0
    local unit u
    local real x
    local real y
    local real x1
    local real y1
    local integer level
    local real t
    local integer j
    local integer modifier
    local real r

    // Now we start looping through all the spell instances
    loop
        exitwhen i >= listmax

        // First we load the saved values of a spell instance
        set i = i + 1
        set ID = LoadInteger(udg_FF_Hashtable, -1, i)
        set caster = LoadUnitHandle(udg_FF_Hashtable, ID, 1)
        set x = LoadReal(udg_FF_Hashtable, ID, 2)
        set y = LoadReal(udg_FF_Hashtable, ID, 3)
        set level = FF_SpellLvl(caster)
        set t = LoadReal(udg_FF_Hashtable, ID, 5)
        set j = LoadInteger(udg_FF_Hashtable, ID, 6)

        if t >= FF_Duration(level) then
            call DestroyEffect(LoadEffectHandle(udg_FF_Hashtable, ID, 4))

            if listmax != i then
                call SaveInteger(udg_FF_Hashtable, LoadInteger(udg_FF_Hashtable, -1, listmax), 0, i)
                call SaveInteger(udg_FF_Hashtable, -1, i, LoadInteger(udg_FF_Hashtable, -1, listmax))
                call RemoveSavedInteger(udg_FF_Hashtable, -1, listmax)
                set i = i - 1
            endif

            set listmax = listmax - 1
            call SaveInteger(udg_FF_Hashtable, -1, 0, listmax)

            if LoadInteger(udg_FF_Hashtable, 0, 0) + 1 == LoadInteger(udg_FF_Hashtable, 0, -1) then
                call FlushChildHashtable(udg_FF_Hashtable, 0)
                call PauseTimer(LoadTimerHandle(udg_FF_Hashtable, -2, 0))
            else
                call SaveInteger (udg_FF_Hashtable, 0, 0, LoadInteger(udg_FF_Hashtable, 0, 0) + 1)
                call SaveInteger(udg_FF_Hashtable, 0, LoadInteger(udg_FF_Hashtable, 0, 0), ID)
            endif

            call FlushChildHashtable(udg_FF_Hashtable, ID)

        else
 
            if LoadBoolean(udg_FF_Hashtable, ID, 7) then
                set r = LoadReal(udg_FF_Hashtable, ID, 10)

                if r >= FF_ExpDelay() then
                    call GroupEnumUnitsInRange(udg_FF_Group, LoadReal(udg_FF_Hashtable, ID, 8), LoadReal(udg_FF_Hashtable, ID, 9), FF_ExpAoE(level), null)

                    loop
                        set u = FirstOfGroup(udg_FF_Group)
                        exitwhen u == null

                        if FF_FilterUnit (GetOwningPlayer(caster), u) and IsUnitVisible(u, GetOwningPlayer(caster)) then
                            call UnitDamageTarget(caster, u, FF_ExpDmg(level), false, false, FF_AttackType(), FF_DamageType(), FF_WeaponType())
                        endif

                        call GroupRemoveUnit(udg_FF_Group, u)
                    endloop

                    if listmax != i then
                        call SaveInteger (udg_FF_Hashtable, LoadInteger (udg_FF_Hashtable, -1, listmax), 0, i)
                        call SaveInteger (udg_FF_Hashtable, -1, i, LoadInteger (udg_FF_Hashtable,-1, listmax))
                        call RemoveSavedInteger (udg_FF_Hashtable, -1, listmax)
                        set i = i - 1
                    endif

                    set listmax = listmax - 1
                    call SaveInteger (udg_FF_Hashtable, -1, 0, listmax )

                    if LoadInteger (udg_FF_Hashtable, 0, 0) + 1 == LoadInteger (udg_FF_Hashtable, 0, -1) then
                        call FlushChildHashtable (udg_FF_Hashtable, 0) 
                        call PauseTimer (LoadTimerHandle (udg_FF_Hashtable, -2, 0))
                    else
                        call SaveInteger (udg_FF_Hashtable, 0, 0, LoadInteger(udg_FF_Hashtable, 0, 0) + 1)
                        call SaveInteger (udg_FF_Hashtable, 0, LoadInteger(udg_FF_Hashtable, 0, 0), ID)
                    endif

                    call FlushChildHashtable (udg_FF_Hashtable, ID)
                else
                    call SaveReal(udg_FF_Hashtable, ID, 10, r + FF_Interval())
                endif

            else

                set modifier = j - (j/4)*4
                set x1 = x + GetRandomReal (135, FF_FieldAoe(FF_SpellLvl(caster)))*Cos(GetRandomReal(-90, 0) + modifier*90.)
                set y1 = y + GetRandomReal (135, FF_FieldAoe(FF_SpellLvl(caster)))*Sin(GetRandomReal(-90, 0) + modifier*90.)
                call DestroyEffect(AddSpecialEffect (FF_ExpFx(), x1, y1))
                set ID2 = LoadInteger (udg_FF_Hashtable, 0, 0)

                if ID2 > 0 then
                    call SaveInteger (udg_FF_Hashtable, 0, 0, ID2 - 1)
                    set ID2 = LoadInteger (udg_FF_Hashtable, 0, ID2)
                else
                    set ID2 = LoadInteger (udg_FF_Hashtable, 0, -1) + 1
                    call SaveInteger (udg_FF_Hashtable, 0,-1, ID2)
                endif

                call SaveUnitHandle (udg_FF_Hashtable, ID2, 1, caster)
                call SaveReal (udg_FF_Hashtable, ID2, 8, x1)
                call SaveReal (udg_FF_Hashtable, ID2, 9, y1)
                call SaveReal(udg_FF_Hashtable, ID2, 10, 0)
                call SaveBoolean (udg_FF_Hashtable, ID2, 7, true)
                set listmax = listmax + 1
                call SaveInteger (udg_FF_Hashtable, -1, 0, listmax )
                call SaveInteger (udg_FF_Hashtable, -1, listmax, ID2)
                call SaveInteger (udg_FF_Hashtable, ID2, 0, listmax)

                call SaveReal(udg_FF_Hashtable, ID, 5, t + FF_Interval())
                call SaveInteger(udg_FF_Hashtable, ID, 6, j + 1)
            endif
        endif

        set caster = null
    endloop
endfunction

function Trig_FF_Conditions takes nothing returns boolean
    local unit caster
    local integer ID
    local integer listmax
    local real x
    local real y

    if GetSpellAbilityId() == FF_GetSpellID() then
        set caster = GetTriggerUnit()
        set x = GetSpellTargetX()
        set y = GetSpellTargetY()
        set ID = LoadInteger(udg_FF_Hashtable, 0, 0)

        // Now we start indexing the spell
        if ID>0 then
            call SaveInteger(udg_FF_Hashtable, 0, 0, ID - 1)
            set ID = LoadInteger (udg_FF_Hashtable, 0, ID)
        else
            set ID = LoadInteger(udg_FF_Hashtable, 0, -1) + 1
            call SaveInteger(udg_FF_Hashtable,0 ,-1, ID)
            if ID == 1 then
                call TimerStart (LoadTimerHandle(udg_FF_Hashtable, -2, 0), FF_Interval(), true, function FF_TimerLoop)
            endif
        endif

        // Save the values related to this spell instance
        call SaveUnitHandle(udg_FF_Hashtable, ID, 1, caster)
        call SaveReal(udg_FF_Hashtable, ID, 2, x)
        call SaveReal(udg_FF_Hashtable, ID, 3, y)
        call SaveEffectHandle(udg_FF_Hashtable, ID, 4, AddSpecialEffect (FF_FieldFx(), x, y))
        call SaveReal(udg_FF_Hashtable, ID, 5, 0)
        call SaveInteger(udg_FF_Hashtable, ID, 6, 0)

        set listmax = LoadInteger (udg_FF_Hashtable, -1, 0) + 1
        call SaveInteger (udg_FF_Hashtable, -1, 0, listmax )
        call SaveInteger (udg_FF_Hashtable, -1, listmax, ID)
        call SaveInteger (udg_FF_Hashtable, ID, 0, listmax)

        set caster = null
    endif
    return false
endfunction

//===========================================================================
function InitTrig_Freezing_Field takes nothing returns nothing
    local trigger FF = CreateTrigger()
    set udg_FF_Hashtable = InitHashtable ()
    call SaveTimerHandle (udg_FF_Hashtable, -2, 0, CreateTimer())
    call TriggerRegisterAnyUnitEventBJ(FF, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(FF, Condition( function Trig_FF_Conditions))
    set FF = null
endfunction
 
Level 13
Joined
May 10, 2009
Messages
868
JASS:
function FF_ExpDmg takes integer level returns real
    return 100. + level*20.
endfunction
That's the function you are looking for.

The following function retrieves the amount of intelligence a hero has GetHeroInt(whichHero, includeBonuses)

You probably need to calculate the damage based on intelligence whenever a hero casts that spell. This way would be better because you'll do it once per cast, instead of recalculating the same values upon each shard impact.
 
Last edited:
Level 4
Joined
Feb 24, 2018
Messages
71
Ok, so how do I add
JASS:
GetHeroInt(whichHero, includeBonuses)
in function FF_ExpDmg ? The damage should be like 1000 x Level of spell + 6 x Intelligence x Level of Spell
JASS:
function FF_ExpDmg takes integer level returns real
    local real damage = GetHeroInt( caster, true ) 
    return 1000*level + 6*level*damage.
endfunction
 
Level 13
Joined
May 10, 2009
Messages
868
The "caster" variable is declared in another function (Loop func).
JASS:
function FF_TimerLoop takes nothing returns nothing
    local integer ID
    local integer ID2
    local integer listmax = LoadInteger(udg_FF_Hashtable, -1, 0 )
    local unit caster // <--
As you can see, it's a local variable. Locals can't be used within other functions, you'll have to either "transfer" caster to that function by adding a new parameter to it, or use a global variable (like GUI ones).
Ex:
JASS:
// Add a new parameter to ExpDmg func
function FF_ExpDmg takes integer level, unit whichUnit returns real
    return 1000*level + 6*level*GetHeroInt(whichUnit, true)
endfunction

// Since the above function has changed, we must also adapt other parts of the code which call it. Like this one: call UnitDamageTarget(caster, u, FF_ExpDmg(level)...
// It becomes this: call UnitDamageTarget(caster, u, FF_ExpDmg(level, caster)...

// [...]

    call GroupEnumUnitsInRange(udg_FF_Group, LoadReal(udg_FF_Hashtable, ID, 8), LoadReal(udg_FF_Hashtable, ID, 9), FF_ExpAoE(level), null)

        loop
            set u = FirstOfGroup(udg_FF_Group)
            exitwhen u == null

            if FF_FilterUnit (GetOwningPlayer(caster), u) and IsUnitVisible(u, GetOwningPlayer(caster)) then
                call UnitDamageTarget(caster, u, FF_ExpDmg(level, caster), false, false, FF_AttackType(), FF_DamageType(), FF_WeaponType()) // <- You need to add the caster to the "FF_ExpDmg" function
            endif

            call GroupRemoveUnit(udg_FF_Group, u)
        endloop

// [...]
 
Level 4
Joined
Feb 24, 2018
Messages
71
Ok , I understand. But I'm getting Cannot convert returned value from integer to real here
JASS:
function FF_ExpDmg takes integer level,unit whichUnit returns real
    return 1000 * level + 6 * level * GetHeroInt(whichUnit, true)
endfunction
 
Status
Not open for further replies.
Top