• 🏆 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!
  • ✅ Time to vote for the top 3 models! The POLL for Hive's 6th HD Modeling Contest: Mechanical is now open! 📅 Poll close on July 16, 2024! 🔗 Cast your vote now!

[JASS] AoE Spell

Status
Not open for further replies.
Level 6
Joined
Aug 1, 2009
Messages
159
Well I created my first vJASS spell but it doesn't work, can you find the problem in my code?

I also recommend checking the map too, but its your choice. I see the AOE_EFFECT but it wont damage the units. There should be an effect showing that the units are being damaged, so. Here it is!

JASS:
scope HitlnS initializer init
//**************************************************************************
//
// Hitling 1.0
// =======
// SPELL_ID : Rawcode of the custom ability found in the object editor based
//            on the spell Cluster Rockets, change the SPELL_ID code found
//            in the first globals section, remember to avoid editing all
//            the codes after it. It might mess the spell up, so avoid
//            editing the core itself.
//
// DUMMY_ID : Rawcode of the custom unit found in the object editor based on
//            the unit footman, it appears invisible because it has no model
//            in it. I didn't used the dummy.mdx since I dont have it ATM,
//            anyway. This is only used to preload the ability itself to
//            avoid lags ingame.
//
// AOE_EFFECT : This is only used for effects, you can change it to anything you
//            want, replace all '\' to '\\' in order for it to work.
//
// DAMAGE_EFFECT : This is the effect that appears on the origin of the damaged
//            /affected unit. If you want to change the effect, replace all '\'
//            to '\\' in order for it to work.
//
// D_TYPE     : This is the damage type of the ability, you can change it to what-
//            ever you want, basically, this is the one if the spell is magic or
//            sonic or what element is it (cold, fire, darkness, etc.).
//
// A_TYPE     : This is the attack type of the ability, you can change it to what-
//            ever you want, but, I recomment normal since it might be weird in-
//            game if you change it to something else.
//
// Please give me comments, tips, or suggestions to help me improve my vJASSing
// skill, thank you for taking a look for my code.
//
//**************************************************************************

//===========================================================================

//Globals Start (you can edit the things below here).
    globals
    // RawCODE of the ability. Change it to the rawcode of your ability in the object editor if you have more than one spell.
        private constant integer SPELL_ID = 'A000'
        private constant integer DUMMY_ID = 'h000'
        private constant string AOE_EFFECT = "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl"
        private constant string DAMAGE_EFFECT = "Abilities\\Spells\\Other\\Incinerate\\IncinerateBuff.mdl"
        private constant damagetype D_TYPE = DAMAGE_TYPE_SONIC
        private constant attacktype A_TYPE = ATTACK_TYPE_NORMAL
    endglobals
    
    private function Range takes integer level returns real
        return level * 300.
    endfunction
    
    private function Damage takes integer level returns real
        return level * 100.
    endfunction
    
    private function Targets takes unit target returns boolean
        return (GetWidgetLife(target) > 0.405) and (IsUnitType(target, UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(target, UNIT_TYPE_FLYING) == false) and (IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE) == false) and (IsUnitType(target, UNIT_TYPE_MECHANICAL) == false)
    endfunction
//Globals End (you can't edit the things below here).
    globals
        private group all
        private group copy
        private boolexpr b
    endglobals
    
    private function CopyGroup takes group g returns group
        set bj_groupAddGroupDest = CreateGroup()
        call ForGroup(g, function GroupAddGroupEnum)
        return bj_groupAddGroupDest
    endfunction
    
    private function Pick takes nothing returns boolean
        return Targets(GetFilterUnit())
    endfunction
    
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == SPELL_ID
    endfunction
    
    private function Actions takes nothing returns nothing
        local location l = GetSpellTargetLoc()
        local real x = GetLocationX(l)
        local real y = GetLocationY(l)
        local unit c = GetTriggerUnit()
        local integer level = GetUnitAbilityLevel(c, SPELL_ID)
        local unit f
        local integer enemies = 0
        call DestroyEffect(AddSpecialEffect(AOE_EFFECT, x, y))
        call GroupEnumUnitsInRange(all, x, y, Range(level), b)
        loop
            set f = FirstOfGroup(copy)
            exitwhen(f == null)
            call GroupRemoveUnit(copy, f)
            if IsUnitEnemy(f, GetOwningPlayer(c)) then
                set enemies = enemies + 1
            endif
        endloop
        if enemies > 0 then
            loop
                set f = FirstOfGroup(all)
                exitwhen(f == null)
                call GroupRemoveUnit(copy, f)
                if IsUnitEnemy(f, GetOwningPlayer(c)) then
                    call DestroyEffect(AddSpecialEffectTarget(DAMAGE_EFFECT, f, "origin"))
                    call UnitDamageTarget(c, f, Damage(level), true, false, A_TYPE, D_TYPE, null)
                endif
            endloop
        endif
        call RemoveLocation(l)
        set l = null
        set c = null
    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))
       call TriggerAddAction(t, function Actions)
       //Setting Globals
       set all = CreateGroup()
       set copy = CreateGroup()
       set b = Condition(function Pick)
       //Preloading Effects
       call Preload(AOE_EFFECT)
       call Preload(DAMAGE_EFFECT)
       //Preloading the ability
       set bj_lastCreatedUnit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMY_ID, 0, 0, 0)
       call UnitAddAbility(bj_lastCreatedUnit, SPELL_ID)
       call KillUnit(bj_lastCreatedUnit)
    endfunction    
endscope
 

Attachments

  • SaMp.w3x
    20.9 KB · Views: 55
JASS:
        local location l = GetSpellTargetLoc()
        local real x = GetLocationX(l)
        local real y = GetLocationY(l)
        call RemoveLocation(l)
        set l = null

Once again found another person using this mess. This has been deprecated for like a year now.

JASS:
local real x = GetSpellTargetX()
local real y = GetSpellTargetY()

I realize it doesn't highlight. The forum highlighting hasn't been updated with things like SaveHashtableHandle, type agent, SaveAgentHandle.
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
I fixed your code.
JASS:
scope HitlnS initializer init
//**************************************************************************
//
// Hitling 1.0
// =======
// SPELL_ID : Rawcode of the custom ability found in the object editor based
//            on the spell Cluster Rockets, change the SPELL_ID code found
//            in the first globals section, remember to avoid editing all
//            the codes after it. It might mess the spell up, so avoid
//            editing the core itself.
//
// DUMMY_ID : Rawcode of the custom unit found in the object editor based on
//            the unit footman, it appears invisible because it has no model
//            in it. I didn't used the dummy.mdx since I dont have it ATM,
//            anyway. This is only used to preload the ability itself to
//            avoid lags ingame.
//
// AOE_EFFECT : This is only used for effects, you can change it to anything you
//            want, replace all '\' to '\\' in order for it to work.
//
// DAMAGE_EFFECT : This is the effect that appears on the origin of the damaged
//            /affected unit. If you want to change the effect, replace all '\'
//            to '\\' in order for it to work.
//
// D_TYPE     : This is the damage type of the ability, you can change it to what-
//            ever you want, basically, this is the one if the spell is magic or
//            sonic or what element is it (cold, fire, darkness, etc.).
//
// A_TYPE     : This is the attack type of the ability, you can change it to what-
//            ever you want, but, I recomment normal since it might be weird in-
//            game if you change it to something else.
//
// Please give me comments, tips, or suggestions to help me improve my vJASSing
// skill, thank you for taking a look for my code.
//
//**************************************************************************

//===========================================================================

//Globals Start (you can edit the things below here).
    globals
    // RawCODE of the ability. Change it to the rawcode of your ability in the object editor if you have more than one spell.
        private constant integer SPELL_ID = 'A000'
        private constant integer DUMMY_ID = 'h000'
        private constant string AOE_EFFECT = "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl"
        private constant string DAMAGE_EFFECT = "Abilities\\Spells\\Other\\Incinerate\\IncinerateBuff.mdl"
        private constant damagetype D_TYPE = DAMAGE_TYPE_SONIC
        private constant attacktype A_TYPE = ATTACK_TYPE_NORMAL
    endglobals
    
    private function Range takes integer level returns real
        return level * 300.
    endfunction
    
    private function Damage takes integer level returns real
        return level * 100.
    endfunction
    
    //Sorry, this needs to be here since TempUnit needs to be on top.
    globals
        private group all = CreateGroup()
        private boolexpr b
        private unit TempUnit //For group enumeration
        private real TempDmg //For group enumeration
    endglobals    
    
    private function Targets takes unit target returns boolean
        //It can be buggy to check if a unit is dead by looking at life. It might be better to use UnitAlive (a native you must first declare before using) or (not IsUnitType(target,UNIT_TYPE_DEAD) and GetUnitTypeId(target) != 0)
        //IsUnitType bug was fixed
        return (GetWidgetLife(target) > 0.405) and not IsUnitType(target, UNIT_TYPE_STRUCTURE) and not IsUnitType(target, UNIT_TYPE_FLYING) and not IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(target, UNIT_TYPE_MECHANICAL) and IsUnitEnemy(target,GetOwningPlayer(TempUnit))
    endfunction
//Globals End (you can't edit the things below here).    
    
    private function Pick takes nothing returns boolean
        if Targets(GetFilterUnit()) then
            call DestroyEffect(AddSpecialEffectTarget(DAMAGE_EFFECT, GetFilterUnit(), "origin"))
            call UnitDamageTarget(TempUnit, GetFilterUnit(), TempDmg, true, false, A_TYPE, D_TYPE, null)
        endif
        return false
    endfunction
    
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == SPELL_ID
    endfunction
    
    private function Actions takes nothing returns nothing
        local real x = GetSpellTargetX()
        local real y = GetSpellTargetY()
        local integer level 
        set TempUnit = GetTriggerUnit()
        set level = GetUnitAbilityLevel(TempUnit, SPELL_ID)
        set TempDmg = Damage(level)
        call DestroyEffect(AddSpecialEffect(AOE_EFFECT, x, y))
        //FirstOfGroup loops are slow. It's better to do things directly to the enemy target in the filter or in ForGroup. To do this, we need temporary global variables.
        call GroupEnumUnitsInRange(all, x, y, Range(level), b)
        //Don't need to null TempUnit!
    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))
       call TriggerAddAction(t, function Actions)
       //Setting Globals
       set b = Condition(function Pick)
       //Preloading Effects
       call Preload(AOE_EFFECT)
       call Preload(DAMAGE_EFFECT)
       //Preloading the ability
       set bj_lastCreatedUnit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMY_ID, 0, 0, 0)
       call UnitAddAbility(bj_lastCreatedUnit, SPELL_ID)
       call RemoveUnit(bj_lastCreatedUnit) //call KillUnit(bj_lastCreatedUnit) <- Better to remove the unit.
    endfunction    
endscope
Anyway, the real problem in your first code was that you didn't set copy to anything at all. You appeared to have forgotten to use your function CopyGroup.
However, since FirstOfGroup loops are kind of slow, I ended up recoding that area to be more efficient. Like I commented, it's better to use filters or ForGroup directly. To actually use them well though, you need to use temporary global variables. Note that nothing will ever get put inside the group all since the boolexpr will always return false.
If you had wanted to keep the FirstOfGroup loop, you didn't really need another group for it. You could have done the damaging in the first loop with only group all.
 
Status
Not open for further replies.
Top