• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[JASS] Spell is ignoring conditions. Why?

Status
Not open for further replies.
Level 12
Joined
Apr 29, 2005
Messages
999
I have a problem with my chain spell I am trying to make. Take a look at the code below.

//THE CONDITION USED BY THE EVENT
//==================================================================================================
function Trig_Chain_Spell_JASS_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'A000' ) ) then
return false
endif
return true
endfunction
//==================================================================================================

function CV_Conditions takes nothing returns boolean
return (IsUnitEnemy(GetEnumUnit(), GetOwningPlayer(GetSpellAbilityUnit())) == true)
return (IsUnitInGroup(GetEnumUnit(), udg_Hit)==false)
return (IsUnitAliveBJ(GetEnumUnit())== true)
endfunction

function Trig_Chain_Spell_JASS_Actions takes nothing returns nothing
local unit CV_Caster = GetSpellAbilityUnit()
local unit CV_Target = GetSpellTargetUnit()
local integer CV_Bounces = 5
local group CV_Hit
local player CV_Owner = GetOwningPlayer(CV_Caster)

loop
exitwhen (CV_Bounces == 0)
call UnitDamageTargetBJ(CV_Caster, CV_Target, 1000, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL)
call AddSpecialEffectTargetUnitBJ( "origin", CV_Target, "Abilities\\Spells\\Undead\\DeathandDecay\\DeathandDecayTarget.mdl" )
call DestroyEffectBJ(GetLastCreatedEffectBJ())
call GroupAddUnit(udg_Hit, CV_Target)
set CV_Target = GroupPickRandomUnit(GetUnitsInRangeOfLocMatching(250, GetUnitLoc(CV_Target), Condition(function CV_Conditions)))
call TriggerSleepAction(3)
set CV_Bounces = CV_Bounces-1
endloop
set udg_Hit = null
endfunction

//THE EVENT
//==================================================================================================
function InitTrig_Chain_Spell_JASS takes nothing returns nothing
set gg_trg_Chain_Spell_JASS = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Chain_Spell_JASS, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Chain_Spell_JASS, Condition( function Trig_Chain_Spell_JASS_Conditions ) )
call TriggerAddAction( gg_trg_Chain_Spell_JASS, function Trig_Chain_Spell_JASS_Actions )
endfunction
//==================================================================================================

The code works but not a it should do.
If you look at the loop you se that the unit to be stored in "CV_Target" must match the conditions in the function "CV_Conditions". The function tells that the unit must not be in the group "udg_Hit", it must be alive and it must be an enemy. After a unit is stored in "CV_Target" it is stored in "udg_Hit" so that it can not be stored in "CV_Target" again. When I try it in the game it seem to igorne the conditions. Both dead and already affected units is affected. Why is it so?
Can someone help me with this?
 
Level 7
Joined
May 6, 2005
Messages
390
Daminon said:
function CV_Conditions takes nothing returns boolean
return (IsUnitEnemy(GetEnumUnit(), GetOwningPlayer(GetSpellAbilityUnit())) == true)
return (IsUnitInGroup(GetEnumUnit(), udg_Hit)==false)
return (IsUnitAliveBJ(GetEnumUnit())== true)
endfunction

When a function returns a value it exits. Therefore only the first return in this function will matter. This may be the problem, but I have only taken a quick look at it so I'm not sure this is the only problem.

Blade
 
Level 12
Joined
Apr 29, 2005
Messages
999
I tried Daelin's advice but that didn't work. Even if I removed all except the group condition. The spell still affectes units who are in the group which means it affects the same unit more than once.

What do you mean about "remove the true" Blade.dk2? Which "true"?
 
Level 7
Joined
May 6, 2005
Messages
390
Daminon said:
I tried Daelin's advice but that didn't work. Even if I removed all except the group condition. The spell still affectes units who are in the group which means it affects the same unit more than once.

What do you mean about "remove the true" Blade.dk2? Which "true"?

Your function should look like this:
JASS:
function CV_Conditions takes nothing returns boolean 
return (IsUnitEnemy(GetEnumUnit(), GetOwningPlayer(GetSpellAbilityUnit()))) and ( not (IsUnitInGroup(GetEnumUnit(), udg_Hit)) ) and (IsUnitAliveBJ(GetEnumUnit())) 
endfunction

Take a look at the condition. You probably have to change GetEnumUnit() to GetFilterUnit() if it's a filter, else you must use GetTriggerUnit() or something, GetEnumUnit() doesn't make any sense unless you want to use it as the callback for a ForGroup() action, which can't be done since callbacks have ti take nothing and return nothing.

Oh, and forget that stupid "2" in my name. It's only there because this site is bugged.

Hopefully that made sense..
 
Level 7
Joined
May 6, 2005
Messages
390
Daminon said:
I have never used filter before and I don't even know what i does. Could you give a small explanation?

You use a boolexpr mostly when you use GetUnitsInRangeOfLocMatching as the argument called filter... And then you should use GetFilterUnit() inside the function... Hopefully that helped you..

Oh, and if you show me your whole script I can tell you exactly how the function should be.

Blade
 
Level 12
Joined
Apr 29, 2005
Messages
999
The script you see in here in this tread is the whole script but mabye not working correct. But the problem I want help with is as I said that the script must only pick units that matches the "CV_Conditions" function.
 
Level 7
Joined
May 6, 2005
Messages
390
Daminon said:
The script you see in here in this tread is the whole script but mabye not working correct. But the problem I want help with is as I said that the script must only pick units that matches the "CV_Conditions" function.

Then you should use GetFilterUnit().
GetEnumUnit() is like picked unit in GUI and GetFilterUnit() is matching unit. And you only want the matching ones right?

JASS:
function CV_Conditions takes nothing returns boolean
    return (IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetSpellAbilityUnit()))) and ( not (IsUnitInGroup(GetFilterUnit(), udg_Hit)) ) and (IsUnitAliveBJ(GetFilterUnit()))
endfunction

function LetMeShowYou takes nothing returns nothing
    local location l = GetSpellTargetLoc()
    local boolexpr be = Condition(function CV_Conditions)
    local group g = GetUnitsInRangeOfLocMatching(500, l, be)
    call ForGroup(g, function MyFunc)
    // We don't want leaks so we destroy and nullifies the objects. 
    call RemoveLocation(l)
    set l = null
    call DestroyBoolExpr(be)
    set be = null
    call DestroyGroup(g)
    set g = null
endfunction

Just change the condition in your script to the one here (take only the condition)... As you can see, this is a small function that shows how to clanup leaks after boolexprs and groups (and locations).

~Blade
 
Level 12
Joined
Apr 29, 2005
Messages
999
I apologize that there was some time since I last wrote anything in this thread but I have now tested my script based on your help Blade.dk and it still doesn't work correct. The problem does not want to be solved.
The spell still picks units that doesn't match all the conditions. I remade the code. This time I only paste the problem part, not the event and stuff. Se below. Btw I know about memory leaks but I just haven't fixed that yet.


function CV_Conditions takes nothing returns boolean
return (IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetSpellAbilityUnit()))) and ( not (IsUnitInGroup(GetFilterUnit(), udg_Hit)) ) and (IsUnitAliveBJ(GetFilterUnit()))
endfunction

function Trig_Chain_Spell_JASS_Actions takes nothing returns nothing
local unit CV_Caster = GetSpellAbilityUnit()
local unit CV_Target = GetSpellTargetUnit()
local boolexpr be = Condition(function CV_Conditions)
local integer CV_Bounces = 5

loop
exitwhen (CV_Bounces == 0)
call UnitDamageTargetBJ(CV_Caster, CV_Target, 1000, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL)
call AddSpecialEffectTargetUnitBJ( "origin", CV_Target, "Abilities\\Spells\\Undead\\DeathandDecay\\DeathandDecayTarget.mdl" )
call DestroyEffectBJ(GetLastCreatedEffectBJ())
call GroupAddUnit(udg_Hit, CV_Target)
set CV_Target = GroupPickRandomUnit(GetUnitsInRangeOfLocMatching(500, GetUnitLoc(CV_Target), be))
call TriggerSleepAction(1)
set CV_Bounces = CV_Bounces-1
endloop
set udg_Hit = null
endfunction


When I tried this code in the game it some times affect dead units that already have been affected and even the hero itself if close enough. As you see in the "CV_Conditions", such units should not be picked. Still it does not pick only matching units. Try it by yourself. Make a trigger-script with this code (and the event and conditon of course) and use some target spell, change the rawcode and place some enemy units between each other but with walls around them so they can not run away. That is how I test this script.
 
Level 7
Joined
May 6, 2005
Messages
390
A guy at The Jass Vault had a problem with IsUnitAliveBJ some time ago, if you have trigger that sets unti life to something it can affect dead units, even though they should be dead, they won't be considered so. That, I guess, must be the problem.

~Blade
 
Level 12
Joined
Apr 29, 2005
Messages
999
I feel I am to tired and need more experience to struggle on whit this script any more. I give up. I will use Vexorians Chain Template instead. Thanks for your help Blade.dk!

Code:
function Ape takes nothing returns nothing
    local unit C = GetSpellAbilityUnit()
    local unit T = GetSpellTargetUnit()

    call KillUnit(T)
    call KillUnit(C)

    set C = null
    set T = null
endfunction

JASS:
function Ape takes nothing returns nothing
    local unit C = GetSpellAbilityUnit()
    local unit T = GetSpellTargetUnit()

    call KillUnit(T)
    call KillUnit(C)

    set C = null
    set T = null
endfunction
 
Status
Not open for further replies.
Top