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

[JASS] Need help with those conditions.

Status
Not open for further replies.
Level 5
Joined
Jul 14, 2008
Messages
121
I got that chronosphere spell from http://www.hiveworkshop.com/forums/resource.php?t=103046&prev=search%3Ddota%26d%3Dlist%26r%3D20 and I'm trying to add conditions so some unit type don't have any effect from this spell.


JASS:
function Trig_Chronosphere_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A02K'  
endfunction

function Chronosphere_Group takes nothing returns boolean
    return ( GetFilterUnit() != GetTriggerUnit() )
endfunction    

function Trig_Chronosphere_Actions takes nothing returns nothing
    local integer i=GetUnitAbilityLevel(GetTriggerUnit(),'A02K')
    local unit u
    local unit v
    local real r=1+(i*1)
    local timer t=CreateTimer()
    local location l=GetSpellTargetLoc()
    local group g    
    set u = CreateUnit(GetOwningPlayer(GetTriggerUnit()),'u00A',GetLocationX(l),GetLocationY(l),bj_UNIT_FACING)
    call TriggerSleepAction (0.3)
    call UnitApplyTimedLife(u,'BTLF',r)
    call SetUnitTimeScalePercent(u,0.00)
    set g = GetUnitsInRangeOfLocMatching(425.00, l, Condition(function Chronosphere_Group))    
    call StartTimerBJ(t,false,r)
    loop
        exitwhen TimerGetRemaining(t)<=0.0 
        loop
            set v = FirstOfGroup(g)
            exitwhen v == null
            call GroupRemoveUnit(g,v)
            call PauseUnit(v,true)
            call SetUnitTimeScalePercent(v,0.00)
        endloop
        if (TimerGetRemaining(t)<0.8) then
        call TriggerSleepAction(0.1)
        else
        call TriggerSleepAction(0.3)
        endif
        call DestroyGroup(g)
        set g = GetUnitsInRangeOfLocMatching(425.00, l, Condition(function Chronosphere_Group))
    endloop                 
    loop
        set v = FirstOfGroup(g)
        exitwhen v == null
        call GroupRemoveUnit(g,v)
        call PauseUnit(v,false)
        call SetUnitTimeScalePercent(v,100.00)
    endloop
    call DestroyTimer(t)
    set u = null
    call RemoveLocation(l)
    set l = null    
    call DestroyGroup(g)
    set g = null
endfunction

//===========================================================================
function InitTrig_Chronosphere takes nothing returns nothing
    set gg_trg_Chronosphere = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Chronosphere, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Chronosphere, Condition( function Trig_Chronosphere_Conditions ) )
    call TriggerAddAction( gg_trg_Chronosphere, function Trig_Chronosphere_Actions )
endfunction
 
Level 11
Joined
Feb 22, 2006
Messages
752
Ok, first I'm going to ignore all the problems I see in this code and just tell you how to do what you want to do:

Change the Chronosphere_Group function so it only returns true if GetFilterUnit() is an acceptable target type. So for example if you don't want it to target structures:

JASS:
function Chronosphere_Group takes nothing returns boolean
    local unit u = GetFilterUnit()
    local boolean b = (u != GetTriggerUnit() and GetUnitType(u, UNIT_TYPE_STRUCTURE) == false)
    set u = null
    return b
endfunction
 
Level 5
Joined
Jul 14, 2008
Messages
121
It didn't work, it says Undeclared variable "GetUnitType". The unit type i want in the conditon is a raw code "h00Q".
 
Last edited:
Level 5
Joined
Jul 14, 2008
Messages
121
I've tryed that, but it tell me that i can't use other then integer and real.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,197
Seems a rather inefficent spell. I would be suprized if that does not violate atleast one spell section rule.
Anyway, with jass we need to see what you have written so we can tell you what you are doing wrong, especially since WE's default syntax checker is retarded (gives unhelpful errors or incorrect errors).
 
Level 11
Joined
Feb 22, 2006
Messages
752
If you want only units of type 'h00Q' to be targeted:

JASS:
function Chronosphere_Group takes nothing returns boolean
    local unit u = GetFilterUnit()
    local boolean b = (u != GetTriggerUnit() and GetUnitTypeId(u) == 'h00Q')
    set u = null
    return b
endfunction

If you dont want units of type 'h00Q' to be targeted:

JASS:
function Chronosphere_Group takes nothing returns boolean
    local unit u = GetFilterUnit()
    local boolean b = (u != GetTriggerUnit() and GetUnitTypeId(u) != 'h00Q')
    set u = null
    return b
endfunction

Seems a rather inefficent spell

That's an understatement. I was thinking about rewriting it but then I realized it would involve refactoring the ENTIRE thing. Not to mention it would require either using vJASS or gamecache to fix it entirely.
 
Level 11
Joined
Feb 22, 2006
Messages
752
Yea that's what I thought.

I've finished the spell, can't test it though...

Anyway, implement this system into your map:

http://www.wc3c.net/showthread.php?t=101150

Then copy this into a trigger:


JASS:
scope Chronosphere initializer init

// Config

globals
    private constant integer SPELL_ABILITY_ID = 'A02K' //raw code of ability
    private constant real AOE_RADIUS = 425.00 // AOE radius of the ability
    private constant string EFFECT = "" // model path of special effect shown at target point of ability
endglobals

// returns duration of the spell
private constant function DURATION takes integer level returns real
    return 1.00 + level * 1.00
endfunction

// returns true if target is a valid target for the spell given that caster is the unit that cast the spell
private function TARGETS takes unit caster, unit target returns nothing
    return false
endfunction

// End Config

globals
    private group g = CreateGroup()
    private boolexpr filterExpr
    private ChronosphereCollider temp
endglobals

private struct ChronosphereCollider extends xecollider
    private group g = CreateGroup()
    private unit caster
    private real duration
    static method create takes real x, real y, real dir, unit caster, real duration returns ChronosphereCollider
        local ChronosphereCollider this = ChronosphereCollider.allocate(x, y, dir)
        set this.caster = caster
        set this.duration = duration
        return this
    endmethod
    method loopControl takes nothing returns nothing
        // Hijack xefx's timer ;)
        set .duration = .duration - XE_ANIMATION_PERIOD
        if (.duration <= 0) then
            call .terminate()
        else
            set temp = this
            call GroupEnumUnitsInRange(g, .x, .y, AOE_RADIUS + XE_MAX_COLLISION_SIZE, filterExpr)
        endif
    endmethod
    private static method filter takes nothing returns boolean
        local ChronosphereCollider this = temp
        local unit u = GetFilterUnit()
        if (IsUnitInRange(this.caster, u, AOE_RADIUS) and TARGETS(this.caster, u)) then
            call PauseUnit(u, true)
            call GroupAddUnit(this.g, u)
        endif
        set u = null
        return false
    endfunction
    method onDestroy takes nothing returns nothing
        local unit u
        loop
            set u = FirstOfGroup(.g)
            exitwhen (u == null)
            call PauseUnit(u, false)
        endloop
        call DestroyGroup(.g)
    endmethod
    static method onInit takes nothing returns nothing
        set filterExpr = Condition(function ChronosphereCollider.filter)
    endmethod
endstruct

private function conditions takes nothing returns boolean
    return GetSpellAbilityId() == SPELL_ABILITY_ID
endfunction

private function actions takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local integer level = GetUnitAbilityLevel(caster, SPELL_ABILITY_ID)
    local location targetLoc = GetSpellTargetLoc()
    local ChronosphereCollider this = ChronosphereCollider.create(GetLocationX(targetLoc), GetLocationY(targetLoc), 270.00, caster, DURATION(level))
    set this.collisionSize = 0
    set this.fxpath = EFFECT
    call RemoveLocation(targetLoc)
    set targetLoc = null
    set caster = 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)
    set t = null //unnecessary but w/e
endfunction

endscope
 
Level 5
Joined
Jul 14, 2008
Messages
121
I don't understand how to add GetUnitTypeId as an conditions.

PS: thx fort he help
 
Level 11
Joined
Feb 22, 2006
Messages
752
GetUnitTypeId takes in a single unit argument and returns the raw code id of that unit. You can use the boolean operator "==" (equals) to check to see if the raw code returned by the function equals some raw code. You can use the boolean operator "!=" (not equals) to check to see if the raw code does NOT equal some raw code.

The function TARGETS determines what units the spell can target. The parameter 'caster' is the caster of the spell while 'target' is a potential target that needs to be checked to see if it is a viable target of the spell.

So for example if we wanted the spell to only target enemies and not target units of type 'h00Q':

JASS:
private function TARGETS takes unit caster, unit target returns boolean
    return (IsUnitEnemy(target, GetOwningPlayer(caster)) and GetUnitTypeId(target) != 'h00Q')
endfunction
 
Status
Not open for further replies.
Top