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

Spell Not Going Past Loop?

Status
Not open for further replies.
Level 6
Joined
Aug 20, 2009
Messages
95
Okay, I made this spell, and it does not work. It doesn't go into my group trigger, heres the trigger.
JASS:
scope VampiricStrike initializer init
//==========================SETUP=============================================
    globals
    //The Special Effect of the Blink
        private constant string BLINK_SFX = "Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl"
    //The Special Effect of each Attack
        private constant string ATTACK_SFX = "Abilities\\Spells\\Undead\\CarrionSwarm\\CarrionSwarmDamage.mdl"
    //The Special Effect of the Final Attack
        private constant string FINAL_ATTACK_SFX = "Abilities\\Spells\\Undead\\DeathandDecay\\DeathandDecayTarget.mdl"
    //If true, then the target that you first targeted will be targeted last for the blink attacks.
        private constant boolean ALWAYS_ATTACK_FIRST = true
    //Ability ID of the Vampiric Strike ability
        private constant integer ABILITY_CODE = 'A000'
    //This is the animation string (Name) of the animation you want to play when the unit is attacked.
        private constant string ATTACK_ANIMATION = "attack"
    //If this boolean is set to true, instead of always finding units in BACK of the attacked, it will find them depending on the units
    //facing. EX. If a unit is attacking you and this triggers, it will be behind, (If you're attacking it) however, if you're attacking a unit
    //from behind, then it blinks you behind you, it won't be of much use, however, if its true it will do that.
        private constant boolean ALWAYS_BACK = false
    //This one is the rate at which you teleport to targets, attack, then find a new target. Higher values can be set for longer visual.
        private constant real KEY_TIMERS_RATE = .25
    //This is the attack type for the damage
        private constant attacktype ATTACK_TYPE = ATTACK_TYPE_NORMAL
    //This is the damage type for the damage
        private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
    //This is the weapon type for the damage
        private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS
    endglobals 
    
    private function DAMAGE takes integer lvl returns real
        return 25 + (lvl * 25.)
    endfunction
    
    private function RANGE_PER_LEVEL takes integer lvl returns real
        return 400 + (lvl * 100.)
    endfunction
    
    private function CHANCE_PER_ATTACK takes integer lvl returns real
        return 5 + (lvl * 5.)
    endfunction
    
    private function Boolexpr takes nothing returns boolean
        return IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) != true and IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING) != true and IsUnitInGroup(GetFilterUnit(), GetLastCreatedGroup())
    endfunction
//=======================ENDSETUP=============================================
    struct Vampiric
        unit Caster
        unit Targeted
        group Targets
        real Cfacing
        real Tfacing
        real Maxangle
        real Leastangle
        real Castertoattacked
        real AngleDif
        static integer Structtype
    endstruct
    
    private function Move takes nothing returns nothing
    local Vampiric V = Vampiric.Structtype
    local real damage = DAMAGE(GetUnitAbilityLevel(V.Caster, ABILITY_CODE))
    local real casterx = GetUnitX(V.Caster)
    local real castery = GetUnitY(V.Caster)
    local real targetx = GetUnitX(GetEnumUnit())
    local real targety = GetUnitY(GetEnumUnit())
    local real angle = GetUnitFacing(GetEnumUnit())
    local real offsetx = targetx + 20 * Cos(angle)
    local real offsety = targety + 20 * Sin(angle)
    call BJDebugMsg("Running attacks/sort of")
    if GetEnumUnit() != V.Targeted then
        call SetUnitX(V.Caster, offsetx)
        call SetUnitY(V.Caster, offsety)
        call DestroyEffect(AddSpecialEffect(BLINK_SFX, offsetx, offsety))
        call SetUnitAnimation(V.Caster, ATTACK_ANIMATION)
        call UnitDamageTarget(V.Caster, GetEnumUnit(), damage, true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
        call DestroyEffect(AddSpecialEffect(ATTACK_SFX, targetx, targety))
        call GroupRemoveUnit(V.Targets, GetEnumUnit())
    elseif CountUnitsInGroup(V.Targets) == 1 and ALWAYS_ATTACK_FIRST != true then
        call SetUnitX(V.Caster, offsetx)
        call SetUnitY(V.Caster, offsety)
        call DestroyEffect(AddSpecialEffect(BLINK_SFX, offsetx, offsety))
        call SetUnitAnimation(V.Caster, ATTACK_ANIMATION)
        call UnitDamageTarget(V.Caster, GetEnumUnit(), damage, true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
        call DestroyEffect(AddSpecialEffect(FINAL_ATTACK_SFX, targetx, targety))
        call GroupRemoveUnit(V.Targets, GetEnumUnit())
    elseif GetEnumUnit() == V.Targeted and ALWAYS_ATTACK_FIRST == true and CountUnitsInGroup(V.Targets) == 1 then
        call SetUnitX(V.Caster, offsetx)
        call SetUnitY(V.Caster, offsety)
        call DestroyEffect(AddSpecialEffect(BLINK_SFX, offsetx, offsety))
        call SetUnitAnimation(V.Caster, ATTACK_ANIMATION)
        call UnitDamageTarget(V.Caster, GetEnumUnit(), damage, true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
        call DestroyEffect(AddSpecialEffect(FINAL_ATTACK_SFX, targetx, targety))
        call GroupRemoveUnit(V.Targets, GetEnumUnit())
    endif
    endfunction
    
    private function userFunc takes nothing returns boolean
    local Vampiric V = KT_GetData()
        set Vampiric.Structtype = V
        call BJDebugMsg(I2S(V))
        call ForGroup(V.Targets, function Move)
    if CountUnitsInGroup(V.Targets) < 1 then
        call V.destroy()
        return true
    endif
    return false
    endfunction
    
    private function Angle takes real a returns nothing
    if a < 0 then
        set a = (-a)
    endif
    endfunction
    
    private function Oncast takes nothing returns nothing
    local Vampiric V = Vampiric.create()
    local real maxrange = RANGE_PER_LEVEL(GetUnitAbilityLevel(GetAttacker(), ABILITY_CODE))
    local real angle
    local real offsetx
    local real offsety
    local location casterloc
    local real targetx
    local real targety
    local integer p = 0
    local integer i = GetRandomInt(0, 100)
    local group tempgroup = CreateGroup()
    local location temploc
    local real chance = CHANCE_PER_ATTACK(GetUnitAbilityLevel(GetAttacker(), ABILITY_CODE))
    call BJDebugMsg("Acquired a target")
    if i < chance then
        call V.destroy()
    elseif GetUnitAbilityLevel(GetAttacker(), ABILITY_CODE) > 0 then
        set V.Cfacing = GetUnitFacing(GetAttacker())
        set V.Targeted = GetTriggerUnit()
        set V.Tfacing = GetUnitFacing(GetTriggerUnit())
        set angle = V.Cfacing - V.Tfacing
        call Angle(angle)
    if angle <= 75 or ALWAYS_BACK != false then
        set casterloc = GetUnitLoc(GetAttacker())
        set targetx = GetUnitX(GetTriggerUnit())
        set targety = GetUnitY(GetTriggerUnit())
        set V.Tfacing = V.Tfacing + 180
        call BJDebugMsg("Is back")
    loop
        exitwhen i >= maxrange
        set offsetx = targetx + 10 * Cos(V.Tfacing)
        set offsety = targety + 10 * Sin(V.Tfacing)
        set temploc = Location(offsetx, offsety)
        set tempgroup = GetUnitsInRangeOfLocMatching(200, temploc, Filter(function Boolexpr))
        call DestroyBoolExpr(Filter(function Boolexpr))
        call GroupAddGroup(tempgroup, V.Targets)
        call DestroyGroup(tempgroup)
        set i = i + 10
    endloop
    else
    if angle >= 76 then
        set temploc = GetUnitLoc(GetTriggerUnit())
        call BJDebugMsg("Is front")
    loop
        exitwhen i >= maxrange
        set offsetx = targetx + 10 * Cos(V.Tfacing)
        set offsety = targety + 10 * Sin(V.Tfacing)
        set tempgroup = GetUnitsInRangeOfLocMatching(200, temploc, Filter(function Boolexpr))
        call DestroyBoolExpr(Filter(function Boolexpr))
        call GroupAddGroup(tempgroup, V.Targets)
        call DestroyGroup(tempgroup)
        set i = i + 10
    endloop
    endif
    endif
    endif
    if CountUnitsInGroup(V.Targets) <= 0 then
        call V.destroy()
        call RemoveLocation(casterloc)
        call RemoveLocation(temploc)
    else
        call RemoveLocation(casterloc)
        call RemoveLocation(temploc)
        call KT_Add(function userFunc, V, KEY_TIMERS_RATE)
    endif
    endfunction

    //===========================================================================
    private function init takes nothing returns nothing
        local trigger t = CreateTrigger(  )
        call TriggerAddAction( t, function Oncast)
        call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_ATTACKED)
    endfunction
endscope
 
Are you "NeuroToxin"? Anyway, it was an issue due to unitialized variables, so just basically change this:
JASS:
    local Vampiric V = Vampiric.create()
    local real maxrange = RANGE_PER_LEVEL(GetUnitAbilityLevel(GetAttacker(), ABILITY_CODE))
    local real angle
    local real offsetx
    local real offsety
    local location casterloc
    local real targetx
    local real targety
    local integer p = 0
    local integer i = GetRandomInt(0, 100)
    local group tempgroup = CreateGroup()
    local location temploc
    local real chance = CHANCE_PER_ATTACK(GetUnitAbilityLevel(GetAttacker(), ABILITY_CODE))

Into this:
JASS:
    local Vampiric V = Vampiric.create()
    local real maxrange = RANGE_PER_LEVEL(GetUnitAbilityLevel(GetAttacker(), ABILITY_CODE))
    local real angle = 0
    local real offsetx = 0
    local real offsety = 0
    local location casterloc = 0
    local real targetx = 0
    local real targety = 0
    local integer p = 0
    local integer i = GetRandomInt(0, 100)
    local group tempgroup = CreateGroup()
    local location temploc = null
    local real chance = CHANCE_PER_ATTACK(GetUnitAbilityLevel(GetAttacker(), ABILITY_CODE))
 
Level 6
Joined
Aug 20, 2009
Messages
95
Okay, first of all, bump, second of all, for some reason (I KNOW theres units behind or front) it destroys the struct everytime. heres my new trigger
JASS:
scope VampiricStrike initializer init
//==========================SETUP=============================================
    globals
    //The Special Effect of the Blink
        private constant string BLINK_SFX = "Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl"
    //The Special Effect of each Attack
        private constant string ATTACK_SFX = "Abilities\\Spells\\Undead\\CarrionSwarm\\CarrionSwarmDamage.mdl"
    //The Special Effect of the Final Attack
        private constant string FINAL_ATTACK_SFX = "Abilities\\Spells\\Undead\\DeathandDecay\\DeathandDecayTarget.mdl"
    //If true, then the target that you first targeted will be targeted last for the blink attacks.
        private constant boolean ALWAYS_ATTACK_FIRST = true
    //Ability ID of the Vampiric Strike ability
        private constant integer ABILITY_CODE = 'A000'
    //This is the animation string (Name) of the animation you want to play when the unit is attacked.
        private constant string ATTACK_ANIMATION = "attack"
    //If this boolean is set to true, instead of always finding units in BACK of the attacked, it will find them depending on the units
    //facing. EX. If a unit is attacking you and this triggers, it will be behind, (If you're attacking it) however, if you're attacking a unit
    //from behind, then it blinks you behind you, it won't be of much use, however, if its true it will do that.
        private constant boolean ALWAYS_BACK = false
    //This one is the rate at which you teleport to targets, attack, then find a new target. Higher values can be set for longer visual.
        private constant real KEY_TIMERS_RATE = .25
    //This is the attack type for the damage
        private constant attacktype ATTACK_TYPE = ATTACK_TYPE_NORMAL
    //This is the damage type for the damage
        private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
    //This is the weapon type for the damage
        private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS
    endglobals 
    
    private function DAMAGE takes integer lvl returns real
        return 25 + (lvl * 25.)
    endfunction
    
    private function RANGE_PER_LEVEL takes integer lvl returns real
        return 400 + (lvl * 100.)
    endfunction
    
    private function CHANCE_PER_ATTACK takes integer lvl returns real
        return 5 + (lvl * 5.)
    endfunction
    
    private function Boolexpr takes nothing returns boolean
        return IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) != true and IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING) != true and IsUnitInGroup(GetFilterUnit(), GetLastCreatedGroup())
    endfunction
//=======================ENDSETUP=============================================
    struct Vampiric
        unit Caster
        unit Targeted
        group Targets = CreateGroup()
        real Cfacing
        real Tfacing
        real Maxangle
        real Leastangle
        real Castertoattacked
        real AngleDif
        static integer Structtype
    endstruct
    
    private function Attack takes nothing returns nothing
    local Vampiric V = Vampiric.Structtype
    local real damage = DAMAGE(GetUnitAbilityLevel(V.Caster, ABILITY_CODE))
    local real casterx = GetUnitX(V.Caster)
    local real castery = GetUnitY(V.Caster)
    local real targetx = GetUnitX(GetEnumUnit())
    local real targety = GetUnitY(GetEnumUnit())
    local real angle = GetUnitFacing(GetEnumUnit())
    local real offsetx = targetx + 20 * Cos(angle)
    local real offsety = targety + 20 * Sin(angle)
    call BJDebugMsg("Running attacks/sort of")
    if GetEnumUnit() != V.Targeted then
        call SetUnitX(V.Caster, offsetx)
        call SetUnitY(V.Caster, offsety)
        call DestroyEffect(AddSpecialEffect(BLINK_SFX, offsetx, offsety))
        call SetUnitAnimation(V.Caster, ATTACK_ANIMATION)
        call UnitDamageTarget(V.Caster, GetEnumUnit(), damage, true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
        call DestroyEffect(AddSpecialEffect(ATTACK_SFX, targetx, targety))
        call GroupRemoveUnit(V.Targets, GetEnumUnit())
    elseif CountUnitsInGroup(V.Targets) == 1 and ALWAYS_ATTACK_FIRST != true then
        call SetUnitX(V.Caster, offsetx)
        call SetUnitY(V.Caster, offsety)
        call DestroyEffect(AddSpecialEffect(BLINK_SFX, offsetx, offsety))
        call SetUnitAnimation(V.Caster, ATTACK_ANIMATION)
        call UnitDamageTarget(V.Caster, GetEnumUnit(), damage, true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
        call DestroyEffect(AddSpecialEffect(FINAL_ATTACK_SFX, targetx, targety))
        call GroupRemoveUnit(V.Targets, GetEnumUnit())
    elseif GetEnumUnit() == V.Targeted and ALWAYS_ATTACK_FIRST == true and CountUnitsInGroup(V.Targets) == 1 then
        call SetUnitX(V.Caster, offsetx)
        call SetUnitY(V.Caster, offsety)
        call DestroyEffect(AddSpecialEffect(BLINK_SFX, offsetx, offsety))
        call SetUnitAnimation(V.Caster, ATTACK_ANIMATION)
        call UnitDamageTarget(V.Caster, GetEnumUnit(), damage, true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
        call DestroyEffect(AddSpecialEffect(FINAL_ATTACK_SFX, targetx, targety))
        call GroupRemoveUnit(V.Targets, GetEnumUnit())
    endif
    endfunction
    
    private function userFunc takes nothing returns boolean
    local Vampiric V = KT_GetData()
        set Vampiric.Structtype = V
        call BJDebugMsg(I2S(V))
        call ForGroup(V.Targets, function Attack)
    if CountUnitsInGroup(V.Targets) < 1 then
        call V.destroy()
        return true
    endif
    return false
    endfunction
    
    private function Angle takes real a returns nothing
    if a < 0 then
        set a = (-a)
    endif
    endfunction
    
    private function Oncast takes nothing returns nothing
    local Vampiric V = Vampiric.create()
    local real maxrange = RANGE_PER_LEVEL(GetUnitAbilityLevel(GetAttacker(), ABILITY_CODE))
    local real angle = 0
    local real offsetx = 0
    local real offsety = 0
    local location casterloc = null
    local real targetx = 0
    local real targety = 0
    local integer p = 0
    local integer i = GetRandomInt(0, 100)
    local group tempgroup = CreateGroup()
    local location temploc = null
    local real chance = CHANCE_PER_ATTACK(GetUnitAbilityLevel(GetAttacker(), ABILITY_CODE))
    call BJDebugMsg("Acquired a target")
    if i < chance then
        call V.destroy()
    elseif GetUnitAbilityLevel(GetAttacker(), ABILITY_CODE) > 0 then
        set V.Cfacing = GetUnitFacing(GetAttacker())
        set V.Targeted = GetTriggerUnit()
        set V.Tfacing = GetUnitFacing(GetTriggerUnit())
        set angle = V.Cfacing - V.Tfacing
        call Angle(angle)
    if angle <= 75 or ALWAYS_BACK != false then
        set casterloc = GetUnitLoc(GetAttacker())
        set targetx = GetUnitX(GetTriggerUnit())
        set targety = GetUnitY(GetTriggerUnit())
        set V.Tfacing = V.Tfacing + 180
        call BJDebugMsg("Is back")
    loop
        exitwhen i >= maxrange
        set offsetx = targetx + 10 * Cos(V.Tfacing)
        set offsety = targety + 10 * Sin(V.Tfacing)
        set temploc = Location(offsetx, offsety)
        set tempgroup = GetUnitsInRangeOfLocMatching(200, temploc, Filter(function Boolexpr))
        call DestroyBoolExpr(Filter(function Boolexpr))
        call GroupAddGroup(tempgroup, V.Targets)
        call DestroyGroup(tempgroup)
        set i = i + 10
    endloop
    else
    if angle >= 76 then
        set temploc = GetUnitLoc(GetTriggerUnit())
        call BJDebugMsg("Is front")
    loop
        exitwhen i >= maxrange
        set offsetx = targetx + 10 * Cos(V.Tfacing)
        set offsety = targety + 10 * Sin(V.Tfacing)
        set tempgroup = GetUnitsInRangeOfLocMatching(200, temploc, Filter(function Boolexpr))
        call DestroyBoolExpr(Filter(function Boolexpr))
        call GroupAddGroup(tempgroup, V.Targets)
        call DestroyGroup(tempgroup)
        set i = i + 10
    endloop
    endif
    endif
    endif
    if CountUnitsInGroup(V.Targets) < 1 then
        call V.destroy()
        call RemoveLocation(casterloc)
        call RemoveLocation(temploc)
        call BJDebugMsg("Destroying Struct")
    else
        call RemoveLocation(casterloc)
        call RemoveLocation(temploc)
        call KT_Add(function userFunc, V, KEY_TIMERS_RATE)
        call BJDebugMsg("Running KT")
    endif
    endfunction

    //===========================================================================
    private function init takes nothing returns nothing
        local trigger t = CreateTrigger(  )
        call TriggerAddAction( t, function Oncast)
        call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_ATTACKED)
    endfunction
endscope
 
In the following area, add this debug message:
JASS:
local real chance = CHANCE_PER_ATTACK(GetUnitAbilityLevel(GetAttacker(), ABILITY_CODE))
    call BJDebugMsg("Acquired a target")
    call BJDebugMsg(I2S(i)+" < "+R2S(chance)) //add this
    if i < chance then
        call V.destroy()

If the number on the left is less than the number on the right every time, then that is your problem, as it will destroy the struct instantly.
 
Status
Not open for further replies.
Top