| 12-31-2007, 05:23 AM | #1 |
After several months of being absent from wc3 mapping I'm now also very new to vJass. Nevertheless I gave it a try and here is my first prob I can't get rid of: I'm using NewGen Pack and when I try to save, JassHelper says Code:
"Line xxx: Missing requirement: MyLibrary (library cannot require scopes)" Well, and here is the trigger (ABC is a script from cohadar and MyLibrary is a library of mine with some collected functions): JASS:library EffectDestroyer uses ABC, MyLibrary //============================================================================== private struct EffectWrapper private effect fx static method create takes effect fx returns EffectWrapper local EffectWrapper ret = EffectWrapper.allocate() set ret.fx = fx return ret endmethod method onDestroy takes nothing returns nothing call DestroyEffect(.fx) endmethod endstruct //============================================================================== private function EffectDestroyer takes nothing returns nothing local timer t=GetExpiredTimer() local EffectWrapper ew=ClearTimerStructA(t) // ABC call ew.destroy() call ReleaseTimer(t) // CSSafety endfunction //============================================================================== // Exported function //============================================================================== function DestroyEffectTimed takes effect fx, real delay returns nothing local timer t=NewTimer() // CSSafety local EffectWrapper e=EffectWrapper.create(fx) call SetTimerStructA(t,e) // ABC call TimerStart(t,delay,false,function EffectDestroyer) endfunction endlibrary // Forced by World Editor function InitTrig_Effects takes nothing returns nothing endfunction I think that the prob is somehow stupid, I can feel it, but at the moment I don't get it. But that is not all, first please help me with that and afterwards there can come the actual prob (the periodic timer). Besides that I want to thank for that vJass, jasshelper, grimoire, and whatever new stuff too of course!!! Big thanks to Vex, PitzerMike, Pipedream, cohadar, grim, Toadcop and all the others I just this moment have not in mind. This community still rockz |
| 12-31-2007, 05:27 AM | #2 |
Can you post MyLibrary code? is MyLibrary a scope actually? |
| 12-31-2007, 10:44 AM | #3 |
I already thought that there mustn't be a scope in the library "MyLibrary" and there also is no. Ah! I found it! I'm so ...Listen, I wrote following: JASS:library EffectDestroyer uses ABC, MyLibrary So, of course I have to write this: JASS:library EffectDestroyer uses ABC, CustomScriptCode BUT NOW HERE COMES MY REAL PROBLEM! As mentioned I want to make a periodic timer. Therefor I don't want to use global variables of type udg_*, gamecache or handlevars, I want to make it with the new vJass. After much reading the past days in the forum, I found this A B C script from cohadar and I thought that I could get it with the help from his Little School of ABC. The result is the following trigger of which I think I have coded almost everything wrong. The sad is I can't think of other ways, I'm too new for that, so I ask you for help. All I want to do, is to move units with a periodic timer and that without the use of udg, gc, handlevars. This would be my function I set to a trigger Actions with event EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER: JASS:call DestroyLocation(GetUnitX(GetTriggerUnit()),GetOrderPointX(),GetUnitY(GetTriggerUnit()),GetOrderPointY(),GetOwningPlayer(GetTriggerUnit()),GetTriggerUnit()) JASS:library TimerLocations uses ABC, CustomScriptCode //============================================================================== private struct LocationWrapper //Wrapper: Hülle, Verpackung private real x1 private real x2 private real y1 private real y2 private player p private unit u static method create takes real x1, real x2, real y1, real y2, player p, unit u returns LocationWrapper local LocationWrapper ret = LocationWrapper.allocate() set ret.x1 = x1 set ret.x2 = x2 set ret.y1 = y1 set ret.y2 = y2 set ret.p = p set ret.u = u return ret endmethod endstruct //============================================================================== private function LocationDestroyer takes nothing returns nothing local timer t=GetExpiredTimer() local LocationWrapper lw=ClearStructA(t) // ABC local unit u2 local real x local real y local real xy call RemoveUnit(ret.u) set u2=CreateUnit(ret.p,'h031',ret.x1,ret.y1,0) set xy=xy+1 set x=ret.x1+xy*Cos( Atan2(ret.y2-ret.y1,ret.x2-ret.x1) ) set y=ret.y1+xy*Sin( Atan2(ret.y2-ret.y1,ret.x2-ret.x1) ) if xy>=SquareRoot(Pow(ret.x2-ret.x1,2)+Pow(ret.y2-ret.y1,2)) then call PauseTimer(t) call RemoveUnit(u2) call CreateUnit(ret.p,'h01B',ret.x2,ret.y2,0) call ReleaseTimer(t) // CSSafety return endif call SetUnitPosition(u,x,y) endfunction //============================================================================== // Exported function //============================================================================== function DestroyLocation takes real x1, real x2, real y1, real y2, player p, unit u returns nothing local timer t=NewTimer() // CSSafety local LocationWrapper l=LocationWrapper.create(x1,x2,y1,y2,p,u) call SetStructA(t,l) // ABC call TimerStart(t,0.4,true,function LocationDestroyer) endfunction endlibrary // Forced by World Editor function InitTrig_Physics takes nothing returns nothing endfunction If you can give me some clues or another way of doing this that would be great. I mean before I wrote this I tried to make it with Vex's Magic Timer... but hey... hehe, I'm sadly much too dumb for this heavy code... |
| 12-31-2007, 02:06 PM | #4 |
Here is an extension of ABC to use timers the noob way. JASS://============================================================================== // ABCT - ABC Timer extension library by Cohadar - v1.0 //============================================================================== // // FUNCTIONS: // * ABCT_Start(userFunc, struct, period) // ABCT_GetData() -> struct // // * userFunc is a user function that takes nothing and return boolean // userFunc should return true to stop timer. // // * GetData() is a function that can be used inside userFunc // GetData() will return struct passed to Start function //============================================================================== library ABCT uses ABC //============================================================================== private struct Trigger trigger trig triggeraction action integer data private static method cleanUp takes nothing returns nothing local Trigger T = ClearTriggerStructA(GetTriggeringTrigger()) // ABC call DisableTrigger(T.trig) call TriggerRemoveAction(T.trig, T.action) call DestroyTrigger(T.trig) call T.destroy() endmethod static method create takes code userFunc, integer data, real period returns Trigger local Trigger T = Trigger.allocate() set T.trig = CreateTrigger() call TriggerAddCondition(T.trig, Condition(userFunc)) set T.data = data set T.action = TriggerAddAction(T.trig, function Trigger.cleanUp) call SetTriggerStructA(T.trig, T) // ABC call TriggerRegisterTimerEvent(T.trig, period, true) return T endmethod endstruct //============================================================================== public function Start takes code userFunc, integer data, real period returns nothing if userFunc == null then call BJDebugMsg("ERROR: ABCT_Start - null userFunc") return endif call Trigger.create(userFunc, data, period) endfunction //============================================================================== public function GetData takes nothing returns integer return Trigger(GetTriggerStructA(GetTriggeringTrigger())).data // ABC endfunction endlibrary |
| 01-02-2008, 01:27 AM | #5 |
Hi cohadar Ok, so I reread, rethought, reread, rethought, read something new, thought somehow other and finally understood a few more relations. Thx 4 posting the extension, but I didn't understand it right, because I just wanted to stay at this nice trigger of yours (the "EffectDestroyer") only changed for moving units. I realized I made a lot of mistakes and this new code should work now, but it does not?? The unit turns to the pointed direction, but then just stay on its position. If I'm ordering the unit a 2nd time to another location, the game becomes VERY laggy, and by a 3rd order the game almost freezes. What's wrong with this? JASS:library temp uses ABC, CustomScriptCode //============================================================================== private struct DataWrapper //Wrapper[ENG->GER]: Hülle, Verpackung real x1 real x2 real y1 real y2 real dist unit u static method create takes real x1, real x2, real y1, real y2, unit u returns DataWrapper local DataWrapper ret = DataWrapper.allocate() set ret.x1 = x1 set ret.x2 = x2 set ret.y1 = y1 set ret.y2 = y2 set ret.u = u return ret endmethod endstruct //============================================================================== private function MovePeriodic_Callback takes nothing returns nothing local timer t=GetExpiredTimer() local DataWrapper dw=ClearStructA(t) // ABC local real x local real y call DisplayTextToForce( GetPlayersAll(), "Love" ) call BJDebugMsg(R2S(dw.x1)) set dw.dist=dw.dist+1.0 call BJDebugMsg("dist: "+R2S(dw.dist)) set x=dw.x1+dw.dist*Cos( Atan2(dw.y2-dw.y1,dw.x2-dw.x1) ) call BJDebugMsg("x: "+R2S(x)) set y=dw.y1+dw.dist*Sin( Atan2(dw.y2-dw.y1,dw.x2-dw.x1) ) call BJDebugMsg("y: "+R2S(y)) if dw.dist>=SquareRoot(Pow(dw.x2-dw.x1,2)+Pow(dw.y2-dw.y1,2)) then call BJDebugMsg("finished") call PauseTimer(t) call ReleaseTimer(t) // CSSafety [instead of call DestroyTimer(t) and set t = null] return endif call SetUnitPosition(dw.u,x,y) call BJDebugMsg("New Pos:"+R2S(x)) endfunction //============================================================================== // Exported function //============================================================================== function MovePeriodic takes real x1, real x2, real y1, real y2, unit u returns nothing local timer t=NewTimer() // CSSafety local DataWrapper dw=DataWrapper.create(x1,x2,y1,y2,u) call SetStructA(t,dw) // ABC call TimerStart(t,0.03,true,function MovePeriodic_Callback) //native TimerStart takes timer whichTimer, real timeout, boolean periodic, code handlerFunc returns nothing //"timeout" means that after this delay the func will be executed! endfunction endlibrary // Forced by World Editor function InitTrig_Physics takes nothing returns nothing endfunction There must be a minor prob... EDIT: W8! Is it perhaps caused by this line of code within the timer callback? JASS:local DataWrapper dw=ClearStructA(t) // ABC |
| 01-12-2008, 10:37 AM | #6 | ||
So, back again after reading the manual several times (anyway almost everything in it except the chapter about interface *g which I want to read the next time when my brain cools down) and some stuff about hash tables (yeah! now I understand the system behind ABC a bit) I rewrote my old trigger and now it also works. First to my question from one post above: Quote:
Once the timer is nulled from its global timer array index ("KeyA[-> integer value of timer]"), the stored informations from the global integer array index ("ValueA[-> integer value of timer]") can't be connected a 2nd time to the same integer value of the timer, because when the function ClearStructA() runs this 2nd time, the timer can't be found in its global timer array with its timer integer value, because we already have set it to null. So, a wrong index from the global integer array Value is used (in the system it is nulled before it returns a value, so we get null from the global integer array "Value") and the stored integer informations can't be called. :) Well, I think that was roughly the prob I had. And now, I have a new trigger as already mentioned, but I want to know if this usage is ok, so that there won't be any leaks or any efficiency loss through the usage of it. I want to use the ABC system the right way, not the noob way... Quote:
Finally the trigger: JASS:library temp2 uses ABC, CustomScriptCode // CustomScriptCode contains the CSSafety functions //============================================================================== private struct DataWrapper // Wrapper[ENG->GER]: Hülle, Verpackung real x1 real x2 real y1 real y2 real dist unit u static method create takes real x1, real x2, real y1, real y2, unit u returns DataWrapper local DataWrapper r = DataWrapper.allocate() // ".allocate" because of the static method's name "create" set r.x1 = x1 set r.x2 = x2 set r.y1 = y1 set r.y2 = y2 set r.u = u return r endmethod endstruct //============================================================================== private function Callback takes nothing returns nothing local timer t=GetExpiredTimer() local DataWrapper dw=GetStructA(t) // ABC local real x local real y set dw.dist=dw.dist+1.0 call BJDebugMsg("dist: "+R2S(dw.dist)) set x=dw.x1+dw.dist*Cos( Atan2(dw.y2-dw.y1,dw.x2-dw.x1) ) call BJDebugMsg("x: "+R2S(x)) set y=dw.y1+dw.dist*Sin( Atan2(dw.y2-dw.y1,dw.x2-dw.x1) ) call BJDebugMsg("y: "+R2S(y)) if dw.dist>=SquareRoot(Pow(dw.x2-dw.x1,2)+Pow(dw.y2-dw.y1,2)) then call BJDebugMsg("finished") call ClearStructA(t) // ABC call ReleaseTimer(t) // CSSafety [instead of call PauseTimer(t), call DestroyTimer(t) and set t = null] return endif call SetUnitPosition(dw.u,x,y) endfunction //============================================================================== // Exported function //============================================================================== function MovePeriodic2 takes real x1, real x2, real y1, real y2, unit u returns nothing local timer t=NewTimer() // CSSafety local DataWrapper dw=DataWrapper.create(x1,x2,y1,y2,u) call SetStructA(t,dw) // ABC call TimerStart(t,0.03,true,function Callback) endfunction endlibrary And the call (only for testing): JASS:private function Actions takes nothing returns nothing call MovePeriodic2(GetUnitX(GetTriggerUnit()),GetOrderPointX(),GetUnitY(GetTriggerUnit()),GetOrderPointY(),GetTriggerUnit()) endfunction //=========================================================================== public function InitTrig takes nothing returns nothing local trigger trig = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ( trig, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER ) call TriggerAddCondition( trig, Condition( function Conditions ) ) call TriggerAddAction( trig, function Actions ) endfunction |
| 01-12-2008, 04:12 PM | #7 |
JASS://============================================================================== // First of all you were using old ABC functions // SetStructA, GetStructA and ClearStructA // Abc can also be used for triggers and dialogs now, check the new version. // // Below you will see a lot of code changes. // The biggest one was using ticks. // ticks are cool and efficient way of doing movement - learn it. //============================================================================== library temp2 uses ABC globals private constant real PERIOD = 0.03 private constant real SPEED = 400. // you can change this any way you like endglobals //============================================================================== private struct DataWrapper // Wrapper[ENG->GER]: Hülle, Verpackung real dx real dy real angle integer ticks unit u static method create takes real dx, real dy, real angle, integer ticks, unit u returns DataWrapper local DataWrapper r = DataWrapper.allocate() // ".allocate" because of the static method's name "create" set r.dx = dx set r.dy = dy set r.angle = angle set r.ticks = ticks set r.u = u return r endmethod endstruct //============================================================================== private function Callback takes nothing returns nothing local timer t=GetExpiredTimer() local DataWrapper dw=GetTimerStructA(t) // ABC set dw.ticks = dw.ticks - 1 if dw.ticks <0 then call BJDebugMsg("finished") call ClearTimerStructA(t) // ABC call ReleaseTimer(t) // CSSafety else call SetUnitX(dw.u, GetUnitX(dw.u) + dw.dx) call SetUnitY(dw.u, GetUnitY(dw.u) + dw.dy) endif endfunction //============================================================================== // Exported function //============================================================================== function MovePeriodic2 takes real x1, real x2, real y1, real y2, unit u returns nothing local timer t=NewTimer() // CSSafety local real Dx = x2-x1 local real Dy = y2-y1 local real distance = SquareRoot(Dx*Dx + Dy*Dy) local real angle = Atan2(Dy, Dx) // Dy goes first local integer ticks = R2I(distance / (SPEED*PERIOD)) // remember this formula local real dx = Dx / ticks local real dy = Dy / ticks local DataWrapper dw=DataWrapper.create(dx, dy, angle, ticks, u) call SetTimerStructA(t,dw) // ABC call TimerStart(t,PERIOD,true,function Callback) endfunction endlibrary |
