| 03-28-2010, 05:03 PM | #1 | |
I'm having a problem trying extending an interface in a struct. Code1:interface MotionEvents { method onMotion( ) = null; } public struct dmMotion extends MotionEvents when I check if the method exists (a method from the interface), it always returns false. Code2:if ( m.onMotion.exists ) { BJDebugMsg( "It Should Work" ); m.onMotion( ); } so basically if I want to extend a struct from the dmMotion struct and have a method called onMotion it won't work, since the dmMotion itself is the one that's calling that method if it exists.
so now I ask if there is some lost functionality in Zinc regarding interfaces, or is this a bug or if it's something I did wrong here. I also noticed that stub methods aren't available in Zinc, what a shame.. I'll post here the whole code Library:library DyMotionMotion requires DyMotionMain, DyMotionProjectile { interface MotionEvents { method onMotion( ) = null; } public struct dmMotion extends MotionEvents { public real LifeTime = dm_DEFAULT_LIFE_TIME; static method create( ) -> dmMotion { dmMotion m = dmMotion.allocate( ); if ( dmMotion.N == 0 ) TimerStart( dmMotion.Timer, dm_UPDATE_INTERVAL, true, dmMotion.update ); m.id = dmMotion.N; dmMotion.M[dmMotion.N] = m; dmMotion.N += 1; return m; } static method Create( real x, real y, real angle ) -> dmMotion { dmMotion m = dmMotion.create( ); m.msl = dmProjectile.create( x, y, angle ); m.Angle = angle; return m; } static method CreateWithUnit( unit u, real angle ) -> dmMotion { dmMotion m = dmMotion.create( ); m.msl = dmProjectile.createWithUnit( u ); m.Angle = angle; return m; } //********Some method operators missing******** //****************Not important**************** private delegate dmProjectile msl; private real maxspd = dm_DEFAULT_MAX_SPEED * dm_UPDATE_INTERVAL; private real minspd = 0.0; private real spd = 0.0; //speed private real zspd = 0.0; // Z axis speed private real acc = 0.0; //acceleration private real zacc = 0.0; //Z axis acceleration private real angspd = 0.0; //angle speed private real cos = 0.0, sin = 0.0; private integer id; private static timer Timer; private static integer N = 0; private static dmMotion M[]; private static code update; static method Update( ) { dmMotion m; integer i; real a; for ( 0 <= i < dmMotion.N ) { m = M[i]; if ( m.angspd != 0.0 ) m.Angle = m.Angle + m.angspd; m.X = m.X + m.spd * m.cos; m.Y = m.Y + m.spd * m.sin; m.Z += m.zspd; if ( m.spd < m.maxspd && m.spd >= m.minspd ) m.spd += m.acc; m.zspd += m.zacc; if ( m.onMotion.exists ) { BJDebugMsg( "It Should Work" ); m.onMotion( ); } if ( m.LifeTime > 0 ) m.LifeTime -= dm_UPDATE_INTERVAL; else m.destroy( ); SetCameraPosition( m.msl.X, m.msl.Y ); } } method onDestroy( ) { msl.destroy( ); dmMotion.N -= 1; dmMotion.M[id] = dmMotion.M[dmMotion.N]; dmMotion.M[id].id = id; if ( dmMotion.N == 0 ) PauseTimer( dmMotion.Timer ); } method end( ) { destroy( ); } static method onInit( ) { Timer = CreateTimer( ); update = function dmMotion.Update; } } } |
| 03-28-2010, 11:17 PM | #2 |
I don't understand your interface declaration, can you declare methods like that? In vJass its: JASS:interface someinterface method onEvent takes nothing returns nothing defaults nothing endinterface struct somestruct extends interface ... call .onEvent() endstruct Looking through the Zinc Manual, I came across this example for interfaces: Zinc:
interface F
{
method balls(integer x) = null; //this method 'defaults nothing'
method bells(integer y) -> real = 0.0 ; //this method defaults a 0.0 for the real return
//a static create method for the interface
static method create();
}
So I guess you were declaring it properly. I don't know why its all highlighted in red though this is just a copy+paste. |
| 03-28-2010, 11:45 PM | #3 |
I came across this, too. Its most likely a functionality loss for zinc (there are actually many, you cannot use hook in zinc blocks, static ifs do not work outside of functions like they seem to do in vJass etc... many small things) |
| 03-29-2010, 02:24 AM | #4 |
@ TheKid: use [zinc] tags Zinc:
interface F
{
method balls(integer x) = null; //this method 'defaults nothing'
method bells(integer y) -> real = 0.0 ; //this method defaults a 0.0 for the real return
//a static create method for the interface
static method create();
}
|
| 03-29-2010, 04:02 AM | #5 |
There we go. |
| 03-29-2010, 12:32 PM | #6 | |
Quote:
oh I didn't know static ifs could be used outside functions, but well I only discovered them in Zinc. When this problem occurred to me, I tried to do a workaround with stub methods, they didn't work, because Zinc doesn't support them. -.-' Damn it, Zinc is so much faster to write, I was getting used to it, but the lack of functionality makes me rethink on what language should I turn to. Edit: I've been all morning converting most of my scripts into vJass, hell of a boring work. But what the hell?? it still doesn't work. My eyes are hurting right now, I didn't find any bug in the script though. So please can someone take a look? I'd be really appreciated JASS:library DyMotionMotion needs DyMotionMain, DyMotionProjectile //_______________________________________________ //*********************************************** // *****Globals***** //----------------------------------------------- globals private constant real dm_DEFAULT_MAX_SPEED = 1800. private constant real dm_DEFAULT_LIFE_TIME = 6. endglobals //----------------------------------------------- // *****Globals End***** //_______________________________________________ //*********************************************** interface MotionEvents method onMotion takes nothing returns nothing defaults nothing endinterface struct dmMotion extends MotionEvents real LifeTime = dm_DEFAULT_LIFE_TIME static method Create takes real x, real y, real angle returns dmMotion local dmMotion m = dmMotion.create( ) set m.msl = dmProjectile.create( x, y, angle ) set m.Angle = angle return m endmethod static method CreateWithUnit takes unit u, real angle returns dmMotion local dmMotion m = dmMotion.create( ) set m.msl = dmProjectile.createWithUnit( u ) set m.Angle = angle return m endmethod //_______________________________________________ //*********************************************** // *****Operators***** //----------------------------------------------- method operator Angle takes nothing returns real return Atan2( spd * sin, spd * cos ) endmethod method operator Angle= takes real value returns nothing set cos = Cos( value ) set sin = Sin( value ) set msl.XYangle = value endmethod method operator Speed takes nothing returns real return spd / dm_UPDATE_INTERVAL endmethod method operator Speed= takes real value returns nothing set spd = value * dm_UPDATE_INTERVAL endmethod method operator Acceleration takes nothing returns real return acc / dm_UPDATE_INTERVAL endmethod method operator Acceleration= takes real value returns nothing set acc = value * dm_UPDATE_INTERVAL endmethod method operator AngleSpeed takes nothing returns real return angspd / dm_UPDATE_INTERVAL endmethod method operator AngleSpeed= takes real value returns nothing set angspd = value * dm_UPDATE_INTERVAL endmethod method operator MaxSpeed takes nothing returns real return maxspd / dm_UPDATE_INTERVAL endmethod method operator MaxSpeed= takes real value returns nothing set maxspd = value * dm_UPDATE_INTERVAL endmethod method operator MinSpeed takes nothing returns real return minspd / dm_UPDATE_INTERVAL endmethod method operator MinSpeed= takes real value returns nothing set minspd = value * dm_UPDATE_INTERVAL endmethod //----------------------------------------------- // *****Operators End***** //_______________________________________________ //*********************************************** method SetHomingPosition takes real x, real y returns nothing set hmX = x set hmY = y set homing = true endmethod method SetHomingUnit takes unit t returns nothing set hmUnit = t set homing = true endmethod method StopHoming takes nothing returns nothing set hmUnit = null set homing = false endmethod private delegate dmProjectile msl private real maxspd = dm_DEFAULT_MAX_SPEED * dm_UPDATE_INTERVAL private real minspd = 0. private real spd = 0. //speed private real acc = 0. //acceleration private real angspd = 0. //angle speed private real cos = 0. private real sin = 0. private boolean homing = false //homing flag private unit hmUnit = null //homing unit private real hmX private real hmY //homing coordinates private integer id private static timer Timer private static integer N = 0 private static dmMotion array M private static code CREATE private static code update static method Update takes nothing returns nothing local dmMotion m local integer i = 0 local real a loop exitwhen i >= N set m = M[i] if ( m.homing ) then if ( m.hmUnit != null ) then set m.hmX = GetUnitX( m.hmUnit ) set m.hmY = GetUnitY( m.hmUnit ) endif set a = Atan2( m.hmY - m.Y, m.hmX - m.X ) set m.cos = Cos( a ) set m.sin = Sin( a ) endif if ( m.angspd != 0. ) then set m.Angle = m.Angle + m.angspd endif set m.X = m.X + m.spd * m.cos set m.Y = m.Y + m.spd * m.sin if ( m.spd < m.maxspd and m.spd >= m.minspd ) then set m.spd = m.spd + m.acc endif if ( m.onMotion.exists ) then call BJDebugMsg( "It Should Work" ) call m.onMotion( ) endif if ( m.LifeTime > 0. ) then set m.LifeTime = m.LifeTime - dm_UPDATE_INTERVAL else call m.destroy( ) endif call SetCameraPosition( m.msl.X, m.msl.Y ) set i = i + 1 endloop endmethod static method create takes nothing returns dmMotion local dmMotion m = dmMotion.allocate( ) if ( N == 0 ) then call TimerStart( Timer, dm_UPDATE_INTERVAL, true, update ) endif set m.id = N set M[N] = m set N = N + 1 return m endmethod method onDestroy takes nothing returns nothing call msl.destroy( ) set N = N - 1 set M[id] = M[N] set M[id].id = id if (N == 0 ) then call PauseTimer( Timer ) endif endmethod static method onInit takes nothing returns nothing set Timer = CreateTimer( ) set update = function dmMotion.Update set CREATE = function dmMotion.create endmethod endstruct endlibrary |
| 03-29-2010, 03:59 PM | #7 |
JASS:if ( m.onMotion.exists ) then call BJDebugMsg( "It Should Work" ) call m.onMotion( ) endif I'm assuming this is the lines you're referring to? Try declaring the method inside the child-struct, perhaps .exists only works on methods that are not virtual, in other words they are actually declared in the struct of which they are used. There really is no point in having if (method.exists) then because the struct extends an interface that has the method, meaning the child structure will always have that method. |
| 03-29-2010, 04:05 PM | #8 |
Not always, look at how xecollider is coded, it extends an interface holding the loopControl and onUnitHit methods. These are only called in xecollider's periodic function, if they exist in the final (user-created) struct extending xecollider. So using loopControl and onUnitHit is optional, similar to this onMotion method. € I cannot see any difference to xecolliders code atm, but for xecollider, it works as intended. Essential part: JASS:... private interface eventHandler method onUnitHit takes unit hitTarget returns nothing defaults nothing method loopControl takes nothing returns nothing defaults nothing endinterface //=========================================================================== struct xecollider extends eventHandler ... static method timerLoop takes nothing returns nothing ... if( this.loopControl.exists and not this.dead ) then call this.loopControl() endif ... €€ Oh well, it seems to work in Zinc for me: this Zinc:interface events { method go()=null; } struct Parent extends events { method callGo() { if (go.exists) go(); } } struct Child extends Parent { method go() { BJDebugMsg("works"); } static method onInit() { create().callGo(); } } Note, that you cannot call go in the create method, because go.exists returns false there. But after the creation finished, go.exists returns true correctly (at least for me :P), thats why I call a 2nd function, callGo. Well, but it is actually not different to your own library code, which does not work o_0 |
| 03-29-2010, 05:46 PM | #9 |
Unless perhaps "m" is a null struct (0) or something. I tried it out in my own code too (vJass) and it worked. Do you have the latest version of JassHelper? |
| 03-29-2010, 07:41 PM | #10 | ||
Quote:
Yes you'll find a lot of things in my code similar to xe, because as I'm working on this, I'm actually learning from xe. but anyway, I didn't call the method from the create method, at least I don't think I did that. Quote:
Anyway I'll post here the map for anyone to test. If this indeed work on your JNGP, then I'd like that someone of you to attach here your JNGP folder so I can have it. |
| 03-30-2010, 12:09 AM | #11 |
Problem Solved! The issue was in this part: Zinc:static method create( ) -> dmMotion { dmMotion m = dmMotion.allocate( ); if ( dmMotion.N == 0 ) TimerStart( dmMotion.Timer, dm_UPDATE_INTERVAL, true, dmMotion.update ); m.id = dmMotion.N; dmMotion.M[dmMotion.N] = m; dmMotion.N += 1; return m; } static method Create( real x, real y, real angle ) -> dmMotion { dmMotion m = dmMotion.create( ); m.msl = dmProjectile.create( x, y, angle ); m.Angle = angle; return m; } static method CreateWithUnit( unit u, real angle ) -> dmMotion { dmMotion m = dmMotion.create( ); m.msl = dmProjectile.createWithUnit( u ); m.Angle = angle; return m; } this would make possible the creation of the missile and everything, except for the interface's method, somehow, yet to be discovered. I simply solved by doing this: Zinc:static method create( real x, real y, real angle ) -> dmMotion { dmMotion m = dmMotion.allocate( ); dmMotion.Indexing( m ); m.msl = dmProjectile.create( x, y ); m.Angle = angle; return m; } static method createWithUnit( unit u, real angle ) -> dmMotion { dmMotion m = dmMotion.allocate( ); dmMotion.Indexing( m ); m.msl = dmProjectile.createWithUnit( u ); m.Angle = angle; return m; } private static method Indexing( dmMotion m ) { if ( dmMotion.N == 0 ) TimerStart( dmMotion.Timer, dm_UPDATE_INTERVAL, true, dmMotion.update ); m.id = dmMotion.N; dmMotion.M[dmMotion.N] = m; dmMotion.N += 1; } It's now working perfectly! Thanks for all the help guys, cookies are going to be distributed among everyone ^^ |
