wc3campaigns
WC3C Homepage - www.wc3c.netUser Control Panel (Requires Log-In)Engage in discussions with other users and join contests in the WC3C forums!Read one of our many tutorials, ranging in difficulty from beginner to advanced!Show off your artistic talents in the WC3C Gallery!Download quality models, textures, spells (vJASS/JASS), systems, and scripts!Download maps that have passed through our rigorous approval process!

Go Back   Wc3C.net > Resources > Code Resources > Systems
User Name
Password
Register Rules Get Hosted! Chat Pastebin FAQ and Rules Members List Calendar



Reply
 
Thread Tools Search this Thread
Old 10-05-2008, 04:50 PM   #121
zen87
vJass maniac
 
zen87's Avatar
 
Join Date: May 2006
Posts: 732

Submissions (1)

zen87 has a spectacular aura about (86)zen87 has a spectacular aura about (86)zen87 has a spectacular aura about (86)

Send a message via MSN to zen87
Default

i just run a test (modifying the sheep stick to a loop chain lightning) and the code are as below:

Collapse JASS:
scope ChainTest initializer init

    private function spellIdMatch takes nothing returns boolean
      return (GetSpellAbilityId()=='A006')
    endfunction

    private function onSpellCast takes nothing returns nothing
     local xecast   xc   
     local unit     u   = GetTriggerUnit()
     local location loc = GetSpellTargetLoc()
     local integer i = 10
        call SetUnitAnimation(u, "attack")
        loop
            set i=i-1
            exitwhen i<0
            call TriggerSleepAction(.5)
            set xc = xecast.createA()
            set xc.recycledelay = 3.0
            set xc.abilityid    = 'ACcl'                      
            set xc.level        = 1 
            set xc.orderstring  = "chainlightning"   
            set xc.owningplayer = GetOwningPlayer(u)    
            call xc.castOnAOELoc( loc, 200.0 )  
        endloop                              
        call RemoveLocation(loc)
     set u=null
    endfunction

    private function init takes nothing returns nothing
     local trigger t=CreateTrigger()
        call TriggerAddCondition(t, Condition( function spellIdMatch) )
        call TriggerAddAction(t,    function onSpellCast)
        call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
     set t=null
    endfunction
endscope

worked for first 3 seconds, after that the whole spell malfunctioned...
__________________
Final Alliance
An RPG like no other
zen87 is offline   Reply With Quote
Sponsored Links - Login to hide this ad!
Old 10-05-2008, 07:28 PM   #122
Vexorian
Free Software Terrorist
 
Vexorian's Avatar


Technical Director
 
Join Date: Apr 2003
Posts: 14,898

Submissions (37)

Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)

Hero Contest #3 - 2nd Place

Default

well look at both issues later, like in 6 hours.
__________________
Zoom (requires log in)Wc3 map optimizer 5.0
Someone should fix .wav sound in this thing.
Zoom (requires log in)JassHelper 0.A.2.A
Turns your simple code into something that is complicated enough to work.
Faster != more useful
Vexorian is offline   Reply With Quote
Old 10-11-2008, 11:54 AM   #123
waaaks
User
 
waaaks's Avatar
 
Join Date: Apr 2007
Posts: 356

waaaks is on a distinguished road (12)

Default

xecollider picks 2 or more units when the missile collides 2 targets
like if 2 units are close to each other (24 collision size) and the missile (missile with 130 collision size) hits between them, xecollider picks the 2 units affected, even though i added a this.terminate function inside onUnitHit method, making it only pick 1 unit

the code, btw i used abuff system here, the abuff part doesnt work, i need to ask anitarf about this

Collapse JASS:
scope Jumong initializer init

private function setupDamageOptions takes xedamage d returns nothing
    set d.dtype = DAMAGE_TYPE_UNIVERSAL
    set d.atype = ATTACK_TYPE_NORMAL
    set d.damageTrees = true
endfunction

globals
    private constant integer spell = 'A007'
    private constant string sfx = "Abilities\\Weapons\\BallistaMissile\\BallistaMissile.mdl"
    private xedamage damageOptions
    private real counter = 0.0
endglobals

private struct Bind extends xecollider
    unit cast
    real cx
    real cy
    real tx
    real ty
    integer level
    
     method onUnitHit takes unit hitunit returns nothing
        if damageOptions.allowedTarget(this.cast, hitunit) then
            call UnitStun(hitunit, this.cast, counter)
            call damageOptions.damageTarget(this.cast, hitunit, this.level * 90)
            call this.terminate()
        endif
    endmethod
    
    method loopControl takes nothing returns nothing
        local real dx = this.x - this.cx
        local real dy = this.y - this.cy
        local real dis = SquareRoot(dx*dx+dy*dy)
        if dis < 150 then
            set counter = 0.5
        elseif dis < 300 then
            set counter = 0.5
        elseif dis < 450 then
            set counter = 1.0
        elseif dis < 600 then
            set counter = 1.5
        elseif dis < 750 then
            set counter = 2.0
        elseif dis < 900 then
            set counter = 2.5
        elseif dis < 1050 then
            set counter = 3.0
        elseif dis < 1200 then
            set counter = 3.5
        elseif dis < 1350 then
            set counter = 4.0
        elseif dis < 1500 then
            set counter = 4.5
        elseif dis >= 1500 then
            set counter = 5.0
        endif
        if dis >= 2600 then
            call this.terminate()
        endif
    endmethod
    
endstruct

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == spell
endfunction

private function Actions takes nothing returns nothing
    local unit cast = GetTriggerUnit()
    local location targ = GetSpellTargetLoc()
    local real a = Atan2(GetLocationY(targ) - GetUnitY(cast), GetLocationX(targ) - GetUnitX(cast))
    local Bind xe = Bind.create(GetUnitX(cast), GetUnitY(cast), a)
    set xe.fxpath = sfx
    set xe.speed = 350
    set xe.minSpeed = 700
    set xe.maxSpeed = 800
    set xe.acceleration = 100
    set xe.z = 50
    set xe.expirationTime = 20
    set xe.collisionSize = 130
    set xe.direction = a
    
    
    set xe.cast = cast
    set xe.level = GetUnitAbilityLevel(cast, spell)
    set xe.cx = GetUnitX(cast)
    set xe.cy = GetUnitY(cast)
    set xe.tx = 0
    set xe.ty = 0
    call RemoveLocation(targ)
    set cast = null
    set targ = null
endfunction

//===========================================================================
private function init takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    set damageOptions = xedamage.create()
    call setupDamageOptions(damageOptions)
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function Conditions ) )
    call TriggerAddAction( t, function Actions )
endfunction

endscope

edit: forgot to ask another question, i want to know on how to add a sight radius on the xecollider unit, i added 1000 sight radius on xedummy unit inside object editor but still doesnt apply the sight radius
__________________

Last edited by waaaks : 10-11-2008 at 12:01 PM.
waaaks is offline   Reply With Quote
Old 10-11-2008, 10:27 PM   #124
Vexorian
Free Software Terrorist
 
Vexorian's Avatar


Technical Director
 
Join Date: Apr 2003
Posts: 14,898

Submissions (37)

Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)

Hero Contest #3 - 2nd Place

Default

Quote:
i added a this.terminate function inside onUnitHit method, making it only pick 1 unit
Yes, it is a bug, I didn't consider that terminate() should stop the enum loop as well.

Quote:
edit: forgot to ask another question, i want to know on how to add a sight radius on the xecollider unit, i added 1000 sight radius on xedummy unit inside object editor but still doesnt apply the sight radius
Perhaps because a xefx is never owned by a player, not sure if I am going to change this.
__________________
Zoom (requires log in)Wc3 map optimizer 5.0
Someone should fix .wav sound in this thing.
Zoom (requires log in)JassHelper 0.A.2.A
Turns your simple code into something that is complicated enough to work.
Faster != more useful
Vexorian is offline   Reply With Quote
Old 10-11-2008, 11:21 PM   #125
waaaks
User
 
waaaks's Avatar
 
Join Date: Apr 2007
Posts: 356

waaaks is on a distinguished road (12)

Default

Quote:
Perhaps because a xefx is never owned by a player, not sure if I am going to change this.
ok, its up to u if u change it or not, thnx

EDIT: another question, how to make a xecaster cast a channeling ability and only stops when a given duration ends?

EDIT2: yet another question pops out in my mind, how to make xecast cast a target spell to a unit that is fogged?

im trying to create a spell that combines xecollider with xecast, and if xecollider hits a unit then xecast will cast a target spell to that unit, but the problem is xecast cannot cast the spell to the unit that is fogged, while xecollider cannot gain sight radius
__________________

Last edited by waaaks : 10-12-2008 at 12:35 AM.
waaaks is offline   Reply With Quote
Old 10-12-2008, 03:21 AM   #126
Vexorian
Free Software Terrorist
 
Vexorian's Avatar


Technical Director
 
Join Date: Apr 2003
Posts: 14,898

Submissions (37)

Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)

Hero Contest #3 - 2nd Place

Default

Quote:
EDIT: another question, how to make a xecaster cast a channeling ability and only stops when a given duration ends?
channeling ability lasts 0 seconds and you use recycledelay.

Quote:
yet another question pops out in my mind, how to make xecast cast a target spell to a unit that is fogged?
give the dummy unit some sight range?
__________________
Zoom (requires log in)Wc3 map optimizer 5.0
Someone should fix .wav sound in this thing.
Zoom (requires log in)JassHelper 0.A.2.A
Turns your simple code into something that is complicated enough to work.
Faster != more useful
Vexorian is offline   Reply With Quote
Old 10-12-2008, 04:50 AM   #127
waaaks
User
 
waaaks's Avatar
 
Join Date: Apr 2007
Posts: 356

waaaks is on a distinguished road (12)

Default

Quote:
edit: forgot to ask another question, i want to know on how to add a sight radius on the xecollider unit, i added 1000 sight radius on xedummy unit inside object editor but still doesnt apply the sight radius
then this will be my next question
__________________

Last edited by waaaks : 10-12-2008 at 04:51 AM.
waaaks is offline   Reply With Quote
Old 10-12-2008, 04:52 AM   #128
Vexorian
Free Software Terrorist
 
Vexorian's Avatar


Technical Director
 
Join Date: Apr 2003
Posts: 14,898

Submissions (37)

Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)

Hero Contest #3 - 2nd Place

Default

xecast is owned by the player.
__________________
Zoom (requires log in)Wc3 map optimizer 5.0
Someone should fix .wav sound in this thing.
Zoom (requires log in)JassHelper 0.A.2.A
Turns your simple code into something that is complicated enough to work.
Faster != more useful
Vexorian is offline   Reply With Quote
Old 10-12-2008, 05:47 AM   #129
zen87
vJass maniac
 
zen87's Avatar
 
Join Date: May 2006
Posts: 732

Submissions (1)

zen87 has a spectacular aura about (86)zen87 has a spectacular aura about (86)zen87 has a spectacular aura about (86)

Send a message via MSN to zen87
Default

so... is the recycle delay bugged?
__________________
Final Alliance
An RPG like no other
zen87 is offline   Reply With Quote
Old 10-12-2008, 10:07 AM   #130
waaaks
User
 
waaaks's Avatar
 
Join Date: Apr 2007
Posts: 356

waaaks is on a distinguished road (12)

Default

k tried it, and it make things worst, yes it creates the dummy and tries to cast the spell, but its too late, because the sight radius slowly grows, not instantly revealing the ground
the code terminates before the ground is revealed, and the worst part is, the dummy is left behind, its not removed

heres the code
Collapse JASS:
scope Jumong initializer init

private function setupDamageOptions takes xedamage d returns nothing
    set d.dtype = DAMAGE_TYPE_UNIVERSAL
    set d.atype = ATTACK_TYPE_NORMAL
    set d.damageTrees = true
endfunction

globals
    private constant integer spell = 'A007'
    private constant string sfx = "Abilities\\Weapons\\BallistaMissile\\BallistaMissile.mdl"
    private xedamage damageOptions
    private integer counter = 1
endglobals

private struct Bind extends xecollider
    unit cast
    unit dummy
    real cx
    real cy
    real tx
    real ty
    integer level
    
     method onUnitHit takes unit hitunit returns nothing
        local xecast c
        set this.dummy = hitunit
        if damageOptions.allowedTarget(this.cast, hitunit) then
            set c = xecast.createA()
            set c.abilityid = 'stun'
            set c.orderstring = "thunderbolt"
            set c.owningplayer = GetOwningPlayer(this.cast)
            set c.level = counter
            set c.recycledelay = 3.0
            call c.castOnTarget(this.dummy)
            call damageOptions.damageTarget(this.cast, hitunit, this.level * 90)
            call this.terminate()
        endif
    endmethod
    
    method loopControl takes nothing returns nothing
        local real dx = this.x - this.cx
        local real dy = this.y - this.cy
        local real dis = SquareRoot(dx*dx+dy*dy)
        if dis >= 2600 then
            call this.terminate()
        endif
    endmethod
    
    method onDestroy takes nothing returns nothing
        local real dx = this.x - this.cx
        local real dy = this.y - this.cy
        local real dis = SquareRoot(dx*dx+dy*dy)
        if dis < 150 then
            set counter = 1
        elseif dis < 300 then
            set counter = 1
        elseif dis < 450 then
            set counter = 2
        elseif dis < 600 then
            set counter = 3
        elseif dis < 750 then
            set counter = 4
        elseif dis < 900 then
            set counter = 5
        elseif dis < 1050 then
            set counter = 6
        elseif dis < 1200 then
            set counter = 7
        elseif dis < 1350 then
            set counter = 8
        elseif dis < 1500 then
            set counter = 9
        elseif dis >= 1500 then
            set counter = 10
        endif
    endmethod
    
endstruct

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == spell
endfunction

private function Actions takes nothing returns nothing
    local unit cast = GetTriggerUnit()
    local location targ = GetSpellTargetLoc()
    local real a = Atan2(GetLocationY(targ) - GetUnitY(cast), GetLocationX(targ) - GetUnitX(cast))
    local Bind xe = Bind.create(GetUnitX(cast), GetUnitY(cast), a)
    set xe.fxpath = sfx
    set xe.speed = 350
    set xe.minSpeed = 700
    set xe.maxSpeed = 800
    set xe.acceleration = 100
    set xe.z = 50
    set xe.expirationTime = 20
    set xe.collisionSize = 130
    set xe.direction = a
    
    
    set xe.cast = cast
    set xe.dummy = null
    set xe.level = GetUnitAbilityLevel(cast, spell)
    set xe.cx = GetUnitX(cast)
    set xe.cy = GetUnitY(cast)
    set xe.tx = 0
    set xe.ty = 0
    call RemoveLocation(targ)
    set cast = null
    set targ = null
endfunction

//===========================================================================
private function init takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    set damageOptions = xedamage.create()
    call setupDamageOptions(damageOptions)
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function Conditions ) )
    call TriggerAddAction( t, function Actions )
endfunction

endscope
__________________
waaaks is offline   Reply With Quote
Old 10-12-2008, 01:05 PM   #131
Vexorian
Free Software Terrorist
 
Vexorian's Avatar


Technical Director
 
Join Date: Apr 2003
Posts: 14,898

Submissions (37)

Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)

Hero Contest #3 - 2nd Place

Default

Quote:
Originally Posted by zen87
so... is the recycle delay bugged?
I was testing that stuff yesterday then I fell asleep, it seems the recycle delay stuff isn't bugged, it is something else, cause the recycling happens at the right time, so I got to keep testing.
__________________
Zoom (requires log in)Wc3 map optimizer 5.0
Someone should fix .wav sound in this thing.
Zoom (requires log in)JassHelper 0.A.2.A
Turns your simple code into something that is complicated enough to work.
Faster != more useful
Vexorian is offline   Reply With Quote
Old 10-12-2008, 01:42 PM   #132
Vexorian
Free Software Terrorist
 
Vexorian's Avatar


Technical Director
 
Join Date: Apr 2003
Posts: 14,898

Submissions (37)

Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)

Hero Contest #3 - 2nd Place

Default

Ok, it seems that it is safe to stop and pause units after SPELL_END_CAST but it is not safe to remove the ability, odd things happen there.

Try this, it should work fine now:

Collapse JASS:
library xecast initializer init requires xebasic
//************************************************************************
// xecast 0.5 (prerelease)
// ------
//  Because dummy casters REALLY ARE this complicated!
//
//************************************************************************

//===========================================================================================================
 globals
    private constant integer MAXINSTANCES        = 8190 //this is a lot, unless you leak xecast objects
    private constant integer INITIAL_DUMMY_COUNT = 12
    private constant integer DUMMY_STACK_LIMIT   = 50 //don't allow to keep more than DUMMY_STACK_LIMIT innactive dummy units
 endglobals

//=========================================================================
// Please notice all textmacros in this library are considered private.
//  in other words: DON'T RUN THOSE TEXTMACROS!
//
private keyword structinit

globals
    private real EPSILON=0.001 //noticed in war3 this is the sort of precision we want...
endglobals

struct xecast[MAXINSTANCES]

    public integer abilityid    = 0    //ID (rawcode) of the ability to cast
    public integer level        = 1    //Level of the ability to cast

    public real    recycledelay = 0.0  //Please notice, some spells need a recycle delay
                                       // This is, a time period before they get recycle.
                                       // For example, some spells are not instant, there is
                                       // also the problem with damaging spells, this recycle
                                       // delay must be large enough to contain all the time
                                       // in which the spell can do damage.


    public player  owningplayer=Player(15)  //which player to credit for the ability cast?
                                            //notice this can also affect what units are targeteable

    //==================================================================================================
    // You need an order id for the ability so the dummy unit is able to cast it, two ways to assign it
    //   set instance.orderid     = 288883            //would assign an integer orderid
    //   set instance.orderstring = "chainlightning"  //would assign an orderstring
    //                                                 (as those in the object editor)
    //
    method operator orderid= takes integer v returns nothing 
        set .oid=v
    endmethod
    method operator orderstring= takes string s returns nothing
        set .oid=OrderId(s)
    endmethod

    //=================================================================================================
    // Finally, you can determine from which point to cast the ability: z is the height coordinate.
    //
    public boolean customsource=false //Use a custom casting source?

    public real    sourcex     // Determine the casting source for the dummy spell, require customsource =true
    public real    sourcey     // You might prefer to use the setSourcePoint method
    public real    sourcez=0.0 //

    method setSourcePoint takes real x, real y, real z returns nothing
       set .sourcex=x
       set .sourcey=y
       set .sourcez=z
       set .customsource=true
    endmethod

    method setSourceLoc takes  location loc, real z returns nothing
       set .sourcex=GetLocationX(loc)
       set .sourcey=GetLocationY(loc)
       set .sourcez=z
       set .customsource=true
    endmethod


    private boolean autodestroy  = false
    //========================================================================================================
    // you are always allowed to use .create() but you can also use createBasic which sets some things that
    // are usually necessary up.
    //
    public static method createBasic takes integer abilityID, integer orderid, player owner returns xecast
     local xecast r=xecast.allocate()
        if(r==0) then
            debug call BJDebugMsg("Warning: unbelievable but you actually used all xecast instances in your map! Please make sure you are not forgetting to destroy those what you create intensively, if that's not the case, then you'll have to increase xecast MAXINSTANCES")
        endif
        set r.oid=orderid
        set r.abilityid=abilityID
        set r.owningplayer=owner
     return r
    endmethod

    //========================================================================================================
    // Just like the above one, but the instance will self destruct after a call to any cast method
    // (recommended)
    //
    public static method createBasicA takes integer abilityID, integer orderid, player owner returns xecast
     local xecast r=xecast.allocate()
        if(r==0) then
            debug call BJDebugMsg("Warning: unbelievable but you actually used all xecast instances in your map! Please make sure you are not forgetting to destroy those what you create intensively, if that's not the case, then you'll have to increase xecast MAXINSTANCES")
        endif
        set r.oid=orderid
        set r.abilityid=abilityID
        set r.owningplayer=owner
        set r.autodestroy=true
     return r
    endmethod

    //==========================================================================================================
    // Just like create, but the struct instance self destructs after a call to any cast method
    // (Recommended)
    //
    public static method createA takes nothing returns xecast
     local xecast r=xecast.allocate()
        set r.autodestroy=true
     return r
    endmethod

    //==========================================================================================================
    // So, create the dummy, assign options and cast the skill!
    // .castOnTarget(w)       : If you want to hit a widget w with the ability
    // .castOnPoint(x,y)      : If you want to hit a point (x,y) with the ability
    // .castInPoint(x,y)      : For spells like warstomp which do not have a target.
    // .castOnAOE(x,y,radius) : Classic area of effect cast. Considers collision size
    // .castOnGroup(g)        : Cast unit the unit group g, notice it will empty the group yet not destroy it.
    //

    //**********************************************************************************************************
    // The implementation of such methods follows: 

    private static  unit array dummystack
    private static  integer    top=0
    private static  unit       instantdummy

    private integer oid=0

    private static timer       gametime
    private static timer       T
    private static unit array  recycle
    private static real array  expiretime
    private static integer     rn=0

    //==========================================================================================================
    // private dorecycle method, sorry but I need this up here.
    //
    private static method dorecycle takes nothing returns nothing
     local unit u =.recycle[0]
     local integer l
     local integer r
     local integer p
     local real    lt
        call UnitRemoveAbility(u,GetUnitUserData(u))
        call SetUnitUserData(u,0)
        call SetUnitFlyHeight(u,0,0)
        call PauseUnit(u,false)
        if(.top==DUMMY_STACK_LIMIT) then
            call RemoveUnit(u)
        else
            set .dummystack[.top]=u
            set .top=.top+1
        endif
        set .rn=.rn-1
        if(.rn==0) then
            return
        endif
        set p=0
        set lt=.expiretime[.rn]
        loop
            set l=p*2+1
            exitwhen l>=.rn
            set r=p*2+2
            if(r>=.rn)then
                if(.expiretime[l]<lt) then
                    set .expiretime[p]=.expiretime[l]
                    set .recycle[p]=.recycle[l]
                    set p=l
                else
                    exitwhen true
                endif
            elseif (lt<=.expiretime[l]) and (lt<=.expiretime[r]) then
                exitwhen true
            elseif (.expiretime[l]<.expiretime[r]) then
                set .expiretime[p]=.expiretime[l]
                set .recycle[p]=.recycle[l]
                set p=l
            else
                set .expiretime[p]=.expiretime[r]
                set .recycle[p]=.recycle[r]
                set p=r
            endif
        endloop
        set .recycle[p]=.recycle[.rn]
        set .expiretime[p]=lt
        call TimerStart(.T, .expiretime[0]-TimerGetElapsed(.gametime), false, function xecast.dorecycle)
    endmethod

    private static trigger abilityRemove


    // Repetitive process and no inline implemented for large functions, so for now it is a textmacro:
    //! textmacro xecast_allocdummy
        if(.recycledelay<EPSILON) then
            set dummy=.instantdummy
            call SetUnitOwner(dummy,.owningplayer,false)
        elseif (.top>0) then
            set .top=.top-1
            set dummy=.dummystack[.top]
            call SetUnitOwner(dummy,.owningplayer,false)
        else
            set dummy=CreateUnit(.owningplayer,XE_DUMMY_UNITID,0,0,0)
            call TriggerRegisterUnitEvent(.abilityRemove,dummy,EVENT_UNIT_SPELL_ENDCAST)
            call UnitAddAbility(dummy,'Aloc')
            call UnitAddAbility(dummy,XE_HEIGHT_ENABLER)
            call UnitRemoveAbility(dummy,XE_HEIGHT_ENABLER)
        endif
        call UnitAddAbility(dummy,.abilityid)
        if(.level>1) then
            call SetUnitAbilityLevel(dummy,.abilityid,.level)
        endif
    //! endtextmacro
    private static integer cparent
    private static integer current
    private static real    cexpire
    //! textmacro xecast_deallocdummy
        if(.recycledelay>=EPSILON) then
            set .cexpire=TimerGetElapsed(.gametime)+.recycledelay
            set .current=.rn
            set .rn=.rn+1
            loop
                exitwhen (.current==0)
                set .cparent=(.current-1)/2
                exitwhen (.expiretime[.cparent]<=.cexpire)
                set .recycle[.current]=.recycle[.cparent]
                set .expiretime[.current]=.expiretime[.cparent]
                set .current=.cparent
            endloop
            set .expiretime[.current]=.cexpire
            set .recycle[.current]=dummy
            call SetUnitUserData(dummy,.abilityid)
            call TimerStart(.T, .expiretime[0]-TimerGetElapsed(.gametime), false, function xecast.dorecycle)
        else
            call SetUnitUserData(dummy,0)
            call SetUnitFlyHeight(dummy,0,0)
            call UnitRemoveAbility(dummy,.abilityid)
        endif
    //! endtextmacro

    method castOnTarget takes widget target returns nothing
     local unit dummy
        //! runtextmacro xecast_allocdummy()
        if (.customsource) then
            call SetUnitX(dummy,.sourcex)
            call SetUnitY(dummy,.sourcey)
            call SetUnitFlyHeight(dummy,.sourcez,0.0)
        else
            call SetUnitX(dummy,GetWidgetX(target))
            call SetUnitY(dummy,GetWidgetY(target))
        endif
        call IssueTargetOrderById(dummy,this.oid,target)
        //! runtextmacro xecast_deallocdummy()
        if(.autodestroy ) then
            call this.destroy()
        endif
    endmethod



    method castOnPoint takes real x, real y returns nothing
     local unit dummy
        //! runtextmacro xecast_allocdummy()
        if (.customsource) then
            call SetUnitX(dummy,.sourcex)
            call SetUnitY(dummy,.sourcey)
            call SetUnitFlyHeight(dummy,.sourcez,0.0)
        else
            call SetUnitX(dummy,x)
            call SetUnitY(dummy,y)
        endif
        call IssuePointOrderById(dummy,this.oid,x,y)
        //! runtextmacro xecast_deallocdummy()
        if(.autodestroy ) then
            call this.destroy()
        endif
    endmethod
    method castOnLoc takes location loc returns nothing
        //debug call BJDebugMsg("Warning: Locations are in use")
        //nah but I should 
        call .castOnPoint(GetLocationX(loc),GetLocationY(loc))
    endmethod

    //ignores custom source x and y (for obvious reasons)
    method castInPoint takes real x, real y returns nothing
     local unit dummy
        //! runtextmacro xecast_allocdummy()
        if (.customsource) then
            call SetUnitFlyHeight(dummy,.sourcez,0.0)
        endif
        call SetUnitX(dummy, x)
        call SetUnitY(dummy, y)
        call IssueImmediateOrderById(dummy,this.oid)
        //! runtextmacro xecast_deallocdummy()
        if(.autodestroy ) then
            call this.destroy()
        endif
    endmethod
    method castInLoc takes location loc returns nothing
        //debug call BJDebugMsg("Warning: Locations are in use")
        //nah but I should 
        call .castInPoint(GetLocationX(loc),GetLocationY(loc))
    endmethod


    //===================================================================================================
    // For method castOnAOE:
    //
    private static group    enumgroup
    private static real     aoex
    private static real     aoey
    private static real     aoeradius
    private static xecast   cinstance
    private static boolexpr aoefunc

    // Might look wrong, but this is the way to make it consider collision size, a spell that
    // got a target circle and uses this method will let the user know which units it will
    // hit with the mass cast.
    static method filterAOE takes nothing returns boolean
     local unit u=GetFilterUnit()
        if IsUnitInRangeXY(u, .aoex, .aoey, .aoeradius) then
            call .cinstance.castOnTarget(u)
        endif
     set u=null
     return false
    endmethod

    //
    method castOnAOE takes real x, real y, real radius returns nothing
     local boolean ad=this.autodestroy

        if(ad) then
            set this.autodestroy=false
        endif
        set .aoex=x
        set .aoey=y
        set .aoeradius=radius
        set .cinstance=this
        call GroupEnumUnitsInRange(.enumgroup,x,y,radius + XE_MAX_COLLISION_SIZE , .aoefunc)
        if(ad) then
            call this.destroy()
        endif
    endmethod

    method castOnAOELoc takes location loc,real radius returns nothing
        call .castOnAOE(GetLocationX(loc),GetLocationY(loc),radius)
    endmethod

    //==================================================================================================
    // A quick and dirt castOnGroup method, perhaps it'll later have castOntarget inlined, but not now
    //
    method castOnGroup takes group g returns nothing
     local boolean ad=this.autodestroy    
     local unit t
        if(ad) then
            set this.autodestroy=false
        endif

        loop
            set t=FirstOfGroup(g)
            exitwhen(t==null)
            call GroupRemoveUnit(g,t)
            call .castOnTarget(t)
        endloop
        if(ad) then
            call this.destroy()
        endif
    endmethod

    private static method removeAbility takes nothing returns boolean
     local unit u=GetTriggerUnit()
         if(GetUnitUserData(u)!=0) then
             call PauseUnit(u,true)
         endif
        //This is necessary, picture a value for recycle delay that's higher than the casting time,
        //for example if the spell does dps, if you leave the dummy caster with the ability and it 
        //is owned by an AI player it will start casting the ability on player units, so it is
        // a good idea to pause it...

     set u=null
     return true
    endmethod

    //===================================================================================================
    // structinit is a scope private keyword.
    //
    static method structinit takes nothing returns nothing
     local integer i=INITIAL_DUMMY_COUNT+1
     local unit u
        set .aoefunc=Condition(function xecast.filterAOE)
        set .enumgroup=CreateGroup()
        set .abilityRemove = CreateTrigger()
        loop
            exitwhen (i==0)
            set u=CreateUnit(Player(15),XE_DUMMY_UNITID,0,0,0)
            call TriggerRegisterUnitEvent(.abilityRemove,u,EVENT_UNIT_SPELL_ENDCAST)
            call UnitAddAbility(u,'Aloc')
            call UnitAddAbility(u,XE_HEIGHT_ENABLER)
            call UnitRemoveAbility(u,XE_HEIGHT_ENABLER)
            set .dummystack[.top]=u
            set .top=.top+1
            set i=i-1
        endloop
        call TriggerAddCondition(.abilityRemove, Condition(function xecast.removeAbility ) )
        set .top=.top-1
        set .instantdummy=.dummystack[.top]
        set .T=CreateTimer()
        set .gametime=CreateTimer()
        call TimerStart(.gametime,12*60*60,false,null)
    endmethod


endstruct


private function init takes nothing returns nothing
    call xecast.structinit()
endfunction

endlibrary

Quote:
the code terminates before the ground is revealed, and the worst part is, the dummy is left behind, its not removed
Yes, just noticed that for xecast it was never necessary to change the owner back to neutral passive, though with sight range that's another issue.

So, how exactly does the caster system handles these things? Something to try would be to temporarily make the target share vision with the player? If you find out that works I could add a flag to make it able to do that.
__________________
Zoom (requires log in)Wc3 map optimizer 5.0
Someone should fix .wav sound in this thing.
Zoom (requires log in)JassHelper 0.A.2.A
Turns your simple code into something that is complicated enough to work.
Faster != more useful
Vexorian is offline   Reply With Quote
Old 10-12-2008, 02:21 PM   #133
Vexorian
Free Software Terrorist
 
Vexorian's Avatar


Technical Director
 
Join Date: Apr 2003
Posts: 14,898

Submissions (37)

Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)

Hero Contest #3 - 2nd Place

Default

newer xecast:


waaaks, this seems to work on fogged units (if FORCE_INVISIBLE_CAST is set to true) please test it.
Collapse JASS:
library xecast initializer init requires xebasic
//************************************************************************
// xecast 0.5 (prerelease)
// ------
//  Because dummy casters REALLY ARE this complicated!
//
//************************************************************************

//===========================================================================================================
 globals
    private constant integer MAXINSTANCES         = 8190 //this is a lot, unless you leak xecast objects
    private constant integer INITIAL_DUMMY_COUNT  = 12
    private constant integer DUMMY_STACK_LIMIT    = 50 //don't allow to keep more than DUMMY_STACK_LIMIT innactive dummy units

    private constant boolean FORCE_INVISIBLE_CAST = false // If your map does not give visibility to all players, or
                                                          // for other reasons, you might want xecast to work on
                                                          // units that are not visible to the player, in that case
                                                          // change this to true, else it is just a performance loss.
 endglobals

//=========================================================================
// Please notice all textmacros in this library are considered private.
//  in other words: DON'T RUN THOSE TEXTMACROS!
//
private keyword structinit

globals
    private real EPSILON=0.001 //noticed in war3 this is the sort of precision we want...
endglobals

struct xecast[MAXINSTANCES]

    public integer abilityid    = 0    //ID (rawcode) of the ability to cast
    public integer level        = 1    //Level of the ability to cast

    public real    recycledelay = 0.0  //Please notice, some spells need a recycle delay
                                       // This is, a time period before they get recycle.
                                       // For example, some spells are not instant, there is
                                       // also the problem with damaging spells, this recycle
                                       // delay must be large enough to contain all the time
                                       // in which the spell can do damage.


    public player  owningplayer=Player(15)  //which player to credit for the ability cast?
                                            //notice this can also affect what units are targeteable

    //==================================================================================================
    // You need an order id for the ability so the dummy unit is able to cast it, two ways to assign it
    //   set instance.orderid     = 288883            //would assign an integer orderid
    //   set instance.orderstring = "chainlightning"  //would assign an orderstring
    //                                                 (as those in the object editor)
    //
    method operator orderid= takes integer v returns nothing 
        set .oid=v
    endmethod
    method operator orderstring= takes string s returns nothing
        set .oid=OrderId(s)
    endmethod

    //=================================================================================================
    // Finally, you can determine from which point to cast the ability: z is the height coordinate.
    //
    public boolean customsource=false //Use a custom casting source?

    public real    sourcex     // Determine the casting source for the dummy spell, require customsource =true
    public real    sourcey     // You might prefer to use the setSourcePoint method
    public real    sourcez=0.0 //

    method setSourcePoint takes real x, real y, real z returns nothing
       set .sourcex=x
       set .sourcey=y
       set .sourcez=z
       set .customsource=true
    endmethod

    method setSourceLoc takes  location loc, real z returns nothing
       set .sourcex=GetLocationX(loc)
       set .sourcey=GetLocationY(loc)
       set .sourcez=z
       set .customsource=true
    endmethod


    private boolean autodestroy  = false
    //========================================================================================================
    // you are always allowed to use .create() but you can also use createBasic which sets some things that
    // are usually necessary up.
    //
    public static method createBasic takes integer abilityID, integer orderid, player owner returns xecast
     local xecast r=xecast.allocate()
        if(r==0) then
            debug call BJDebugMsg("Warning: unbelievable but you actually used all xecast instances in your map! Please make sure you are not forgetting to destroy those what you create intensively, if that's not the case, then you'll have to increase xecast MAXINSTANCES")
        endif
        set r.oid=orderid
        set r.abilityid=abilityID
        set r.owningplayer=owner
     return r
    endmethod

    //========================================================================================================
    // Just like the above one, but the instance will self destruct after a call to any cast method
    // (recommended)
    //
    public static method createBasicA takes integer abilityID, integer orderid, player owner returns xecast
     local xecast r=xecast.allocate()
        if(r==0) then
            debug call BJDebugMsg("Warning: unbelievable but you actually used all xecast instances in your map! Please make sure you are not forgetting to destroy those what you create intensively, if that's not the case, then you'll have to increase xecast MAXINSTANCES")
        endif
        set r.oid=orderid
        set r.abilityid=abilityID
        set r.owningplayer=owner
        set r.autodestroy=true
     return r
    endmethod

    //==========================================================================================================
    // Just like create, but the struct instance self destructs after a call to any cast method
    // (Recommended)
    //
    public static method createA takes nothing returns xecast
     local xecast r=xecast.allocate()
        set r.autodestroy=true
     return r
    endmethod

    //==========================================================================================================
    // So, create the dummy, assign options and cast the skill!
    // .castOnTarget(w)       : If you want to hit a widget w with the ability
    // .castOnPoint(x,y)      : If you want to hit a point (x,y) with the ability
    // .castInPoint(x,y)      : For spells like warstomp which do not have a target.
    // .castOnAOE(x,y,radius) : Classic area of effect cast. Considers collision size
    // .castOnGroup(g)        : Cast unit the unit group g, notice it will empty the group yet not destroy it.
    //

    //**********************************************************************************************************
    // The implementation of such methods follows: 

    private static  unit array dummystack
    private static  integer    top=0
    private static  unit       instantdummy

    private integer oid=0

    private static timer       gametime
    private static timer       T
    private static unit array  recycle
    private static real array  expiretime
    private static integer     rn=0

    //==========================================================================================================
    // private dorecycle method, sorry but I need this up here.
    //
    private static method dorecycle takes nothing returns nothing
     local unit u =.recycle[0]
     local integer l
     local integer r
     local integer p
     local real    lt
        call UnitRemoveAbility(u,GetUnitUserData(u))
        call SetUnitUserData(u,0)
        call SetUnitFlyHeight(u,0,0)
        call PauseUnit(u,false)
        if(.top==DUMMY_STACK_LIMIT) then
            call RemoveUnit(u)
        else
            set .dummystack[.top]=u
            set .top=.top+1
        endif
        set .rn=.rn-1
        if(.rn==0) then
            return
        endif
        set p=0
        set lt=.expiretime[.rn]
        loop
            set l=p*2+1
            exitwhen l>=.rn
            set r=p*2+2
            if(r>=.rn)then
                if(.expiretime[l]<lt) then
                    set .expiretime[p]=.expiretime[l]
                    set .recycle[p]=.recycle[l]
                    set p=l
                else
                    exitwhen true
                endif
            elseif (lt<=.expiretime[l]) and (lt<=.expiretime[r]) then
                exitwhen true
            elseif (.expiretime[l]<.expiretime[r]) then
                set .expiretime[p]=.expiretime[l]
                set .recycle[p]=.recycle[l]
                set p=l
            else
                set .expiretime[p]=.expiretime[r]
                set .recycle[p]=.recycle[r]
                set p=r
            endif
        endloop
        set .recycle[p]=.recycle[.rn]
        set .expiretime[p]=lt
        call TimerStart(.T, .expiretime[0]-TimerGetElapsed(.gametime), false, function xecast.dorecycle)
    endmethod

    private static trigger abilityRemove


    // Repetitive process and no inline implemented for large functions, so for now it is a textmacro:
    //! textmacro xecast_allocdummy
        if(.recycledelay<EPSILON) then
            set dummy=.instantdummy
            call SetUnitOwner(dummy,.owningplayer,false)
        elseif (.top>0) then
            set .top=.top-1
            set dummy=.dummystack[.top]
            call SetUnitOwner(dummy,.owningplayer,false)
        else
            set dummy=CreateUnit(.owningplayer,XE_DUMMY_UNITID,0,0,0)
            call TriggerRegisterUnitEvent(.abilityRemove,dummy,EVENT_UNIT_SPELL_ENDCAST)
            call UnitAddAbility(dummy,'Aloc')
            call UnitAddAbility(dummy,XE_HEIGHT_ENABLER)
            call UnitRemoveAbility(dummy,XE_HEIGHT_ENABLER)
        endif
        call UnitAddAbility(dummy,.abilityid)
        if(.level>1) then
            call SetUnitAbilityLevel(dummy,.abilityid,.level)
        endif
    //! endtextmacro
    private static integer cparent
    private static integer current
    private static real    cexpire
    //! textmacro xecast_deallocdummy
        if(.recycledelay>=EPSILON) then
            set .cexpire=TimerGetElapsed(.gametime)+.recycledelay
            set .current=.rn
            set .rn=.rn+1
            loop
                exitwhen (.current==0)
                set .cparent=(.current-1)/2
                exitwhen (.expiretime[.cparent]<=.cexpire)
                set .recycle[.current]=.recycle[.cparent]
                set .expiretime[.current]=.expiretime[.cparent]
                set .current=.cparent
            endloop
            set .expiretime[.current]=.cexpire
            set .recycle[.current]=dummy
            call SetUnitUserData(dummy,.abilityid)
            call TimerStart(.T, .expiretime[0]-TimerGetElapsed(.gametime), false, function xecast.dorecycle)
        else
            call SetUnitUserData(dummy,0)
            call SetUnitFlyHeight(dummy,0,0)
            call UnitRemoveAbility(dummy,.abilityid)
        endif
    //! endtextmacro

    method castOnTarget takes unit target returns nothing
     local unit dummy
     local unit tar
        //! runtextmacro xecast_allocdummy()
        if (.customsource) then
            call SetUnitX(dummy,.sourcex)
            call SetUnitY(dummy,.sourcey)
            call SetUnitFlyHeight(dummy,.sourcez,0.0)
        else
            call SetUnitX(dummy,GetWidgetX(target))
            call SetUnitY(dummy,GetWidgetY(target))
        endif
        if (FORCE_INVISIBLE_CAST) then
            call UnitShareVision(target, .owningplayer, true)
            call IssueTargetOrderById(dummy,this.oid,target)
            call UnitShareVision(target, .owningplayer, false)
        else
            call IssueTargetOrderById(dummy,this.oid,target)
        endif

        //! runtextmacro xecast_deallocdummy()
        if(.autodestroy ) then
            call this.destroy()
        endif
    endmethod

    //accepts units, items and destructables, if you know it is
    // a unit it is better to use castOnTarget since that would
    // be able to use FORCE_INVISIBLE_CAST if necessary.
    //
    method castOnWidgetTarget takes widget target returns nothing
     local unit dummy
     local unit tar
        //! runtextmacro xecast_allocdummy()
        if (.customsource) then
            call SetUnitX(dummy,.sourcex)
            call SetUnitY(dummy,.sourcey)
            call SetUnitFlyHeight(dummy,.sourcez,0.0)
        else
            call SetUnitX(dummy,GetWidgetX(target))
            call SetUnitY(dummy,GetWidgetY(target))
        endif
        call IssueTargetOrderById(dummy,this.oid,target)

        //! runtextmacro xecast_deallocdummy()
        if(.autodestroy ) then
            call this.destroy()
        endif
    endmethod



    method castOnPoint takes real x, real y returns nothing
     local unit dummy
        //! runtextmacro xecast_allocdummy()
        if (.customsource) then
            call SetUnitX(dummy,.sourcex)
            call SetUnitY(dummy,.sourcey)
            call SetUnitFlyHeight(dummy,.sourcez,0.0)
        else
            call SetUnitX(dummy,x)
            call SetUnitY(dummy,y)
        endif
        call IssuePointOrderById(dummy,this.oid,x,y)
        //! runtextmacro xecast_deallocdummy()
        if(.autodestroy ) then
            call this.destroy()
        endif
    endmethod
    method castOnLoc takes location loc returns nothing
        //debug call BJDebugMsg("Warning: Locations are in use")
        //nah but I should 
        call .castOnPoint(GetLocationX(loc),GetLocationY(loc))
    endmethod

    //ignores custom source x and y (for obvious reasons)
    method castInPoint takes real x, real y returns nothing
     local unit dummy
        //! runtextmacro xecast_allocdummy()
        if (.customsource) then
            call SetUnitFlyHeight(dummy,.sourcez,0.0)
        endif
        call SetUnitX(dummy, x)
        call SetUnitY(dummy, y)
        call IssueImmediateOrderById(dummy,this.oid)
        //! runtextmacro xecast_deallocdummy()
        if(.autodestroy ) then
            call this.destroy()
        endif
    endmethod
    method castInLoc takes location loc returns nothing
        //debug call BJDebugMsg("Warning: Locations are in use")
        //nah but I should 
        call .castInPoint(GetLocationX(loc),GetLocationY(loc))
    endmethod


    //===================================================================================================
    // For method castOnAOE:
    //
    private static group    enumgroup
    private static real     aoex
    private static real     aoey
    private static real     aoeradius
    private static xecast   cinstance
    private static boolexpr aoefunc

    // Might look wrong, but this is the way to make it consider collision size, a spell that
    // got a target circle and uses this method will let the user know which units it will
    // hit with the mass cast.
    static method filterAOE takes nothing returns boolean
     local unit u=GetFilterUnit()
        if IsUnitInRangeXY(u, .aoex, .aoey, .aoeradius) then
            call .cinstance.castOnTarget(u)
        endif
     set u=null
     return false
    endmethod

    //
    method castOnAOE takes real x, real y, real radius returns nothing
     local boolean ad=this.autodestroy

        if(ad) then
            set this.autodestroy=false
        endif
        set .aoex=x
        set .aoey=y
        set .aoeradius=radius
        set .cinstance=this
        call GroupEnumUnitsInRange(.enumgroup,x,y,radius + XE_MAX_COLLISION_SIZE , .aoefunc)
        if(ad) then
            call this.destroy()
        endif
    endmethod

    method castOnAOELoc takes location loc,real radius returns nothing
        call .castOnAOE(GetLocationX(loc),GetLocationY(loc),radius)
    endmethod

    //==================================================================================================
    // A quick and dirt castOnGroup method, perhaps it'll later have castOntarget inlined, but not now
    //
    method castOnGroup takes group g returns nothing
     local boolean ad=this.autodestroy    
     local unit t
        if(ad) then
            set this.autodestroy=false
        endif

        loop
            set t=FirstOfGroup(g)
            exitwhen(t==null)
            call GroupRemoveUnit(g,t)
            call .castOnTarget(t)
        endloop
        if(ad) then
            call this.destroy()
        endif
    endmethod

    private static method removeAbility takes nothing returns boolean
     local unit u=GetTriggerUnit()
         if(GetUnitUserData(u)!=0) then
             call PauseUnit(u,true)
         endif
        //This is necessary, picture a value for recycle delay that's higher than the casting time,
        //for example if the spell does dps, if you leave the dummy caster with the ability and it 
        //is owned by an AI player it will start casting the ability on player units, so it is
        // a good idea to pause it...

     set u=null
     return true
    endmethod

    //===================================================================================================
    // structinit is a scope private keyword.
    //
    static method structinit takes nothing returns nothing
     local integer i=INITIAL_DUMMY_COUNT+1
     local unit u
        set .aoefunc=Condition(function xecast.filterAOE)
        set .enumgroup=CreateGroup()
        set .abilityRemove = CreateTrigger()
        loop
            exitwhen (i==0)
            set u=CreateUnit(Player(15),XE_DUMMY_UNITID,0,0,0)
            call TriggerRegisterUnitEvent(.abilityRemove,u,EVENT_UNIT_SPELL_ENDCAST)
            call UnitAddAbility(u,'Aloc')
            call UnitAddAbility(u,XE_HEIGHT_ENABLER)
            call UnitRemoveAbility(u,XE_HEIGHT_ENABLER)
            set .dummystack[.top]=u
            set .top=.top+1
            set i=i-1
        endloop
        call TriggerAddCondition(.abilityRemove, Condition(function xecast.removeAbility ) )
        set .top=.top-1
        set .instantdummy=.dummystack[.top]
        set .T=CreateTimer()
        set .gametime=CreateTimer()
        call TimerStart(.gametime,12*60*60,false,null)
    endmethod


endstruct


private function init takes nothing returns nothing
    call xecast.structinit()
endfunction

endlibrary

Regarding visible missiles, I think the best solution here is to take xebasic and just use the dummy unit directly, you may add the sight range bonus skill to it. xecolliders and xefx cannot give sight range, it will work for the idea you got now but it would be considered a bug for the rest of their applications.
__________________
Zoom (requires log in)Wc3 map optimizer 5.0
Someone should fix .wav sound in this thing.
Zoom (requires log in)JassHelper 0.A.2.A
Turns your simple code into something that is complicated enough to work.
Faster != more useful
Vexorian is offline   Reply With Quote
Old 10-12-2008, 05:39 PM   #134
Vexorian
Free Software Terrorist
 
Vexorian's Avatar


Technical Director
 
Join Date: Apr 2003
Posts: 14,898

Submissions (37)

Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)

Hero Contest #3 - 2nd Place

Default

Quote:
Originally Posted by zen87
I just tested, in some way yeah it never miss now, but sometimes the missile "follows the target" instead of exploding upon collide.

I've uploaded the map here. The spell is in a item called soul stick.
Hey to save me time could you post the inputwar3map.j from jasshelper's logs folder? (after saving this map)
__________________
Zoom (requires log in)Wc3 map optimizer 5.0
Someone should fix .wav sound in this thing.
Zoom (requires log in)JassHelper 0.A.2.A
Turns your simple code into something that is complicated enough to work.
Faster != more useful
Vexorian is offline   Reply With Quote
Old 10-13-2008, 07:25 AM   #135
zen87
vJass maniac
 
zen87's Avatar
 
Join Date: May 2006
Posts: 732

Submissions (1)

zen87 has a spectacular aura about (86)zen87 has a spectacular aura about (86)zen87 has a spectacular aura about (86)

Send a message via MSN to zen87
Default

sure thing :)
Attached Files
File Type: 7z inputwar3map.7z (28.5 KB, 4 views)
__________________
Final Alliance
An RPG like no other
zen87 is offline   Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off


All times are GMT. The time now is 11:07 PM.


Affiliates
The Hubb The JASS Vault Clan WEnW Campaign Creations Clan CBS GamesModding Flixreel Videos

Powered by vBulletin (Copyright ©2000 - 2019, Jelsoft Enterprises Ltd).
Hosted by www.OICcam.com
IT Support and Services provided by Executive IT Services