XFIRa39VMpami\:*YEK muhTDTIBmuhT muhT muhTDTIBmuhTmuhT"muhT-#muhT.$muhT/%muhT3*SAC fniCFCRDXtcL SREV SREV SREV( lccFCRDTT: :V< fniClLNf~0C:\Documents and Settings\kyle.gonyer.NA\Desktop*SAC( #$% tSAC}" "o!?!N!N!N!!!!!!!!!!!!!!""-- CONSTRAIN TO MASK (Irregular shape constraint) -- -- Attach this behavior to a sprite to allow it to only be dragged within the masked alpha channel of 32-bit "bitmap" sprite. The area of the alpha channel that will allow the sprite to be moved, is the non-transparent(white) area. The mask must represent your entire stage. -- Areas of the image that you have set in the alpha channel as transparent (black), will act as barriers or holes and will block your sprites movement. -- This behavior is great for use in creating an image of a maze or activity field where you want to move another sprite only within certain defined areas of the image. -- The alpha channel must be imported with the bitmap, so you must save the bitmap as a 32 bit image. You can import it at your stage's color depth though. If your cast window is set to thumbnail view, you will not see a black and white mask. Rather, you will only see the masked "dragable areas" of the image when imported with the alpha mask. This is normal, as director will combine all channels for the thumbnail preview. --To simplify things, you might want to think about using the same file for importing the actual map or maze image, except delete the alpha channel and make sure that this image is in score channel higher than the mask so that it covers the mask up. You really don't need to have every, wall hole or barrier a seperate sprite now that the mask is taking care of everything. -- To make things simple, the parameters dialogue box will ask you for the channel of the constraining sprite (the mask sprite). This is the only information the script would needs inorder to work. -- As a hidden bonus, Pressing the Shift Key before dragging will make the sprite jump across gaps. This could be used to simulate telporting or jumping within your activity area. ----------------------------------------------------------- -- PROPERTY DECLARATIONS -- property spriteNum property canJumpGaps -- set to TRUE on mouseDown if the shiftDown property pSprite -- the draggable sprite property pConstraintSprite -- masked sprite to which your sprite is constrained property pConstraintAlpha -- alpha channel image of constraining mask member property pOffset -- offset between this sprite's loc and the mouse property pCurrentLoc -- last known position of this draggable sprite with respect to the constraining sprite property pConstrSpriteChannelNum -- sprite channel the constraining mask sprite is located --------------------------------------- -- EVENT HANDLERS -- on beginSprite(me) pSprite = sprite(spriteNum) pConstraintSprite = sprite(pConstrSpriteChannelNum) pConstraintAlpha = pConstraintSprite.member.image.extractAlpha() -- The line above sais to use the value of the alpha channel in the image of the member mentioned to detect "holes" in the sprite. The () means that extractAlpha() is a function, not a property. Director has to work out what the alpha channel image is -- it can't just pick the image up ready-made. If the parentheses where left out, Director would complain. end -------------------------------- on mouseDown(me) canJumpGaps = the shiftDown --shift key can be used as a jump button pCurrentLoc = pConstraintSprite.mapStageToMember(pSprite.loc) --"mapStageToMember" is a function that is used to treat the specified sprite or member as a small stage and returns an equivalent point inside the dimensions of a cast member that sits on top of this sprite. Useful for determining and possibly tracking if a particular sprite is on a cast member and if it is being moved/clicked etc. Kind of treats a member a some-what of a mini-stage. Other uses include telling you which pixel of the member corresponds to the stage location indicated even if the sprite is stretched, distorted etc. if not pCurrentLoc then -- If the user has not yet dragged the sprite anywhere. then find out its current position and track this with respect to the constraint sprite. if not pCurrentLoc then -- Also if the users mouse is not over a masked(black area) of the constrainting sprite's alpha, then it can not be dragged at all. exit --the "end" keyword leaves the nested handlers and returns back to the main handler so that it can continue to check the "main" mousedown handler's condition end if end if -- Also start dragging when pOffset is declared pOffset = pSprite.loc - the mouseLoc end ---------------------------------- on exitFrame(me) if not pOffset then -- If the sprite with this behavior is not being dragging then exit end if if the mouseDown then me.mMoveSprite()--if it is being dragged than perform the mMovesprite handler else -- The user just released the mouse pOffset = 0 --sprite is no longer draggable end if end -------------------------------- -- PRIVATE METHOD -- on mMoveSprite(me) --------------------------------------------------------- -- Sent by exitFrame() above -- This action calculates how near to the current mouseLoc the draggable sprite can be dragged.It works out where the sprite should move to next, and moves it there. tMouseLoc = the mouseLoc + pOffset -- Find where the mouse is with respect to the constraint member and sets this as "tMouseLoc" tImageLoc = pConstraintSprite.mapStageToMember(tMouseLoc) --Sets "tImage" to describe where on the constraint sprite the mouse is located if voidP(tImageLoc) then -- If the mouse is currently outside the constraint sprite. Use a slower but more powerful method of determining the relative position. tImageLoc=tMouseLoc-point(pConstraintSprite.left,pConstraintSprite.top) --Sets the "tMouseLoc" to be the point of the constraint sprite's upper left corner? else if canJumpGaps then -- Checks if the mouse is over a masked black area of the constraint member and if it is, returns 1(black) as the integer. tAlpha = pConstraintAlpha.getPixel(tImageLoc, #integer) end if if tAlpha then --If on a black area, then let the mouse move/jump to this spot else -- Sprite can't jump gaps because the mouse is over a gap (movable sprite must be dragged around based on the delta calculations set below) --CALCULATIONS FOR "JUMP GAP" ABILITY (delta position/absolute value etc.) -------------------------------------------------------------- -- The next lines determines how near the dragged sprite can get to the tracked mouse position. The term delta used below, means a mathematical difference. see further comments. tDelta = pCurrentLoc - tImageLoc -- the difference between where the mouse appeared over the bitmap image last time (pCurrentLoc), and where it appears now (tImageLoc) tDeltaH = tDelta.locH -- the horizontal component of tDelta tDeltaV = tDelta.locV -- the vertical component of tDelta tSteps = max(abs(tDeltaH), abs(tDeltaV)) -- sets "tSteps" to be the absolute values of the delta varibles if not tSteps then -- If mouse hasn't moved since the last exitFrame then it will just stand by and wait for an action exit end if tSteps = integer(tSteps) tStep = tDelta / float(tSteps) repeat while tSteps -- Move one pixel towards the mouse tSteps = tSteps - 1 tLoc = tImageLoc + (tStep * tSteps) -- Test that we are still on an opaque area tAlpha = pConstraintAlpha.getPixel(tLoc, #integer) if not tAlpha then -- We've gone a step too far move back to an opaque area tSteps = tSteps + 1 exit repeat end if end repeat end if -- Updates the absolute and relative positions of the draggable sprite. tAdjust = tSteps * tStep pCurrentLoc = tImageLoc + tAdjust -- point relative to constrain sprite tMouseLoc = tMouseLoc + tAdjust -- point relative to the stage pSprite.loc = tMouseLoc -- Find where the mouse is with respect to the constraint member and sets sprite location to this as well. Basically moves the sprite end --Settings for the Parameters Dialogue Box on getPropertyDescriptionList set plist=[:] addprop plist, #pConstrSpriteChannelNum, [#comment: "What channel is your contraining/mask sprite located in?", #format: #integer, #default: 1] return plist end ContrainToMask[#pConstrSpriteChannelNum: [#comment: "What channel is your contraining/mask sprite located in?", #format: #integer, #default: 1]]o!?!?,>Lv?. .tSAC wipe:j?. .P22% tSAC scratch:m?. .P@ M tSAC I___i}}}}}}property blankarea, newitem on mouseenter sprite(blankarea).member=member(newitem) end --uncomment below if you want it to restore on mouseleave --on mouseleave -- sprite(blankarea).member=member(blankarea) --end on getpropertydescriptionlist PDL=[:] setaprop PDL, #blankarea, [#comment: "sprite # that is used as the blank area that will be replaced by hide/show items:", #format: #integer, #default: 4] setaprop PDL, #newitem, [#comment: "graphic or film clip to appear in the blank/hide show area:", #format: #graphic, #default: "engine"] return PDL endHide/Show On Rollover[#blankarea: [#comment: "sprite # that is used as the blank area that will be replaced by hide/show items:", #format: #integer, #default: 4], #newitem: [#comment: "graphic or film clip to appear in the blank/hide show area:", #format: #graphic, #default: "engine"]]t,?P?&. . lccpamFSREV Aknujp  !ެ lccpamFSREV A*YEK  muhTDTIBmuhT muhTDTIBmuhTmuhT"muhT&*SAC fniCFCRDXtcL SREV SREV SREV lcc*SAC SREV AknujmuhT 1*1**1*1@FF8xUFF@?Tx?@F@F[x8@FF*x0Tx**T##T0?TT#T***T?TT#T* **TTFT##T#T**N0N*$*T@T##T$T@T#T#1T1T#T##1$TT1*xT#0$TN027TT##TT#TT81T##T#TTT@#TTT?@TTT88"TTT?18T**T\ *xT*NTN0UT#T**T1FTT#T#T@@TT##T#T@"T**T##T#T@AT*T##T##T#TF?T#T##T?*T* *xTx*F@F8xUFF@?Tx?@"@FUT\F@"@1*1*01*1FCRDTT::V<fniClLN0C:\Documents and Settings\kyle.gonyer.NA\DesktoptSAC}" "o!?!N!N!N!!!!!!!!!!!!!!""-- CONSTRAIN TO MASK (Irregular shape constraint) -- -- Attach this behavior to a sprite to allow it to only be dragged within the masked alpha channel of 32-bit "bitmap" sprite. The area of the alpha channel that will allow the sprite to be moved, is the non-transparent(white) area. The mask must represent your entire stage. -- Areas of the image that you have set in the alpha channel as transparent (black), will act as barriers or holes and will block your sprites movement. -- This behavior is great for use in creating an image of a maze or activity field where you want to move another sprite only within certain defined areas of the image. -- The alpha channel must be imported with the bitmap, so you must save the bitmap as a 32 bit image. You can import it at your stage's color depth though. If your cast window is set to thumbnail view, you will not see a black and white mask. Rather, you will only see the masked "dragable areas" of the image when imported with the alpha mask. This is normal, as director will combine all channels for the thumbnail preview. --To simplify things, you might want to think about using the same file for importing the actual map or maze image, except delete the alpha channel and make sure that this image is in score channel higher than the mask so that it covers the mask up. You really don't need to have every, wall hole or barrier a seperate sprite now that the mask is taking care of everything. -- To make things simple, the parameters dialogue box will ask you for the channel of the constraining sprite (the mask sprite). This is the only information the script would needs inorder to work. -- As a hidden bonus, Pressing the Shift Key before dragging will make the sprite jump across gaps. This could be used to simulate telporting or jumping within your activity area. ----------------------------------------------------------- -- PROPERTY DECLARATIONS -- property spriteNum property canJumpGaps -- set to TRUE on mouseDown if the shiftDown property pSprite -- the draggable sprite property pConstraintSprite -- masked sprite to which your sprite is constrained property pConstraintAlpha -- alpha channel image of constraining mask member property pOffset -- offset between this sprite's loc and the mouse property pCurrentLoc -- last known position of this draggable sprite with respect to the constraining sprite property pConstrSpriteChannelNum -- sprite channel the constraining mask sprite is located --------------------------------------- -- EVENT HANDLERS -- on beginSprite(me) pSprite = sprite(spriteNum) pConstraintSprite = sprite(pConstrSpriteChannelNum) pConstraintAlpha = pConstraintSprite.member.image.extractAlpha() -- The line above sais to use the value of the alpha channel in the image of the member mentioned to detect "holes" in the sprite. The () means that extractAlpha() is a function, not a property. Director has to work out what the alpha channel image is -- it can't just pick the image up ready-made. If the parentheses where left out, Director would complain. end -------------------------------- on mouseDown(me) canJumpGaps = the shiftDown --shift key can be used as a jump button pCurrentLoc = pConstraintSprite.mapStageToMember(pSprite.loc) --"mapStageToMember" is a function that is used to treat the specified sprite or member as a small stage and returns an equivalent point inside the dimensions of a cast member that sits on top of this sprite. Useful for determining and possibly tracking if a particular sprite is on a cast member and if it is being moved/clicked etc. Kind of treats a member a some-what of a mini-stage. Other uses include telling you which pixel of the member corresponds to the stage location indicated even if the sprite is stretched, distorted etc. if not pCurrentLoc then -- If the user has not yet dragged the sprite anywhere. then find out its current position and track this with respect to the constraint sprite. if not pCurrentLoc then -- Also if the users mouse is not over a masked(black area) of the constrainting sprite's alpha, then it can not be dragged at all. exit --the "end" keyword leaves the nested handlers and returns back to the main handler so that it can continue to check the "main" mousedown handler's condition end if end if -- Also start dragging when pOffset is declared pOffset = pSprite.loc - the mouseLoc end ---------------------------------- on exitFrame(me) if not pOffset then -- If the sprite with this behavior is not being dragging then exit end if if the mouseDown then me.mMoveSprite()--if it is being dragged than perform the mMovesprite handler else -- The user just released the mouse pOffset = 0 --sprite is no longer draggable end if end -------------------------------- -- PRIVATE METHOD -- on mMoveSprite(me) --------------------------------------------------------- -- Sent by exitFrame() above -- This action calculates how near to the current mouseLoc the draggable sprite can be dragged.It works out where the sprite should move to next, and moves it there. tMouseLoc = the mouseLoc + pOffset -- Find where the mouse is with respect to the constraint member and sets this as "tMouseLoc" tImageLoc = pConstraintSprite.mapStageToMember(tMouseLoc) --Sets "tImage" to describe where on the constraint sprite the mouse is located if voidP(tImageLoc) then -- If the mouse is currently outside the constraint sprite. Use a slower but more powerful method of determining the relative position. tImageLoc=tMouseLoc-point(pConstraintSprite.left,pConstraintSprite.top) --Sets the "tMouseLoc" to be the point of the constraint sprite's upper left corner? else if canJumpGaps then -- Checks if the mouse is over a masked black area of the constraint member and if it is, returns 1(black) as the integer. tAlpha = pConstraintAlpha.getPixel(tImageLoc, #integer) end if if tAlpha then --If on a black area, then let the mouse move/jump to this spot else -- Sprite can't jump gaps because the mouse is over a gap (movable sprite must be dragged around based on the delta calculations set below) --CALCULATIONS FOR "JUMP GAP" ABILITY (delta position/absolute value etc.) -------------------------------------------------------------- -- The next lines determines how near the dragged sprite can get to the tracked mouse position. The term delta used below, means a mathematical difference. see further comments. tDelta = pCurrentLoc - tImageLoc -- the difference between where the mouse appeared over the bitmap image last time (pCurrentLoc), and where it appears now (tImageLoc) tDeltaH = tDelta.locH -- the horizontal component of tDelta tDeltaV = tDelta.locV -- the vertical component of tDelta tSteps = max(abs(tDeltaH), abs(tDeltaV)) -- sets "tSteps" to be the absolute values of the delta varibles if not tSteps then -- If mouse hasn't moved since the last exitFrame then it will just stand by and wait for an action exit end if tSteps = integer(tSteps) tStep = tDelta / float(tSteps) repeat while tSteps -- Move one pixel towards the mouse tSteps = tSteps - 1 tLoc = tImageLoc + (tStep * tSteps) -- Test that we are still on an opaque area tAlpha = pConstraintAlpha.getPixel(tLoc, #integer) if not tAlpha then -- We've gone a step too far move back to an opaque area tSteps = tSteps + 1 exit repeat end if end repeat end if -- Updates the absolute and relative positions of the draggable sprite. tAdjust = tSteps * tStep pCurrentLoc = tImageLoc + tAdjust -- point relative to constrain sprite tMouseLoc = tMouseLoc + tAdjust -- point relative to the stage pSprite.loc = tMouseLoc -- Find where the mouse is with respect to the constraint member and sets sprite location to this as well. Basically moves the sprite end --Settings for the Parameters Dialogue Box on getPropertyDescriptionList set plist=[:] addprop plist, #pConstrSpriteChannelNum, [#comment: "What channel is your contraining/mask sprite located in?", #format: #integer, #default: 1] return plist end ContrainToMask[#pConstrSpriteChannelNum: [#comment: "What channel is your contraining/mask sprite located in?", #format: #integer, #default: 1]]o!?!?,>Lv?. .atSACx j|--Drag to Reveal(Alpha Scratcher) -- Use this behavior to paint, rub or scractch off a surface to the next surface below. --Any greyscale cast member you create can be used as a brush for this effect. -- Brush will paints the specified cast member into the alpha channel of the -- member this behaviour is applied to. --Works best when the brush member has an alpha channel. -- The brush is rotated a random amount each time it is -- applied. -- Configuration: -- #Brush: Member to use as the brush -- #Rate: How many processes applied to the bugger before -- the image is drawn. -- #ScratchDepth: This is the blendLevel at which the -- the brush is painted into the alpha channel. -- #Cursor: Optional cursor for the sprite -- Written by Luke Wigley luke@meccamedialight.com.au -- Version 1.0.0 -- Last updated 23/3/01 --##[PROPS] property mySprite property myMember property myOriginalImage property myWorkingImage property myAlphaImage property myBrushMember property myBrush property myBrushRotOffset property myBrushQuad property myRate property myScratchDepth property myCursor --##[EVENTS]####### on BeginSprite (me)--------------------------------------------------- -- beginSprite event handler -------------------------------------------------------------------- me.mInit() me.mCreateBrush(myBrushMember) end on endSprite me------------------------------------------------------- -- endSprite event handler -------------------------------------------------------------------- me.mDestroy() end on mouseWithin (me)--------------------------------------------------- -- mouseWithin event handler -------------------------------------------------------------------- if the mousedown then repeat with i = 1 to myRate pntOnmember = the mouseLoc - point(mySprite.left, mySprite.top) me.mScratch(pntOnmember) end repeat end if end --##[handlers PUBLIC]#### on mInit (me)--------------------------------------------------------- -- Create images -------------------------------------------------------------------- mySprite = sprite(me.spriteNum) myMember = mySprite.member myOriginalImage = myMember.image.duplicate() -- backup for restoring the image myWorkingImage = myMember.image me.mCreateNewAlpha() myWorkingImage.setAlpha(myAlphaImage) myMember.useAlpha = 1 mySprite.cursor = myCursor end on mDestroy (me)------------------------------------------------------ -- standard destructor method -------------------------------------------------------------------- me.mReset() mySprite.cursor = 0 end on mGetScratcherInfo (me)--------------------------------------------- -- returns useful instance information -------------------------------------------------------------------- info = [:] info[#brush] = myBrushMember info[#scratchDepth] = myScratchDepth info[#rate] = myRate return info end on mCreateBrush (me, aMemberRef)-------------------------------------- -- Creates a 'brush' image from the supplied member -------------------------------------------------------------------- myBrushMember = aMemberRef myBrush = myBrushMember.image.duplicate() w = myBrush.rect[3] h = myBrush.rect[4] myBrushRotOffset = point(w/2, h/2) myBrushQuad = [point(0,0), point(w, 0), point(w,h), point(0, h)] end on mSetScratchDepth (me, aDepth)-------------------------------------- -- sets the scratch depth (blend level) -------------------------------------------------------------------- myScratchDepth = aDepth end on mScratch (me, aPoint)---------------------------------------------- -- 'Paints' the brush image into the alpha channel -------------------------------------------------------------------- brushPoint = aPoint - myBrushRotOffset ang = random(360) newQuad = me.mRotateQuad(myBrushQuad.duplicate(),ang, myBrushRotOffset ) repeat with i = 1 to 4 newQuad[i] = newQuad[i] + brushPoint end repeat myAlphaImage.copyPixels(myBrush, newQuad, myBrush.rect, [#color: rgb(255,255,255), #blendlevel: myScratchDepth, #ink: 36]) myWorkingImage.setAlpha(myAlphaImage) end on mReset (me)-------------------------------------------------------- -- returns the member image back to the original -------------------------------------------------------------------- me.mCreateNewAlpha() myWorkingImage.setAlpha(myAlphaImage) end --##[PRIVATE]# --##[UTILITY]### on mCreateNewAlpha (me)----------------------------------------------- -- Utility script: Creates a black rect to use as -- an alpha channel -------------------------------------------------------------------- myAlphaImage = image(myOriginalImage.rect[3], myOriginalImage.rect[4], 8, #grayscale) myAlphaImage.fill(myOriginalImage.rect, rgb(0,0,0)) end on mRotateQuad (me, aQuad, anAngle, anOffSet)------------------------- -- rotates the supplied quad. Angle is specified -- in degrees. -------------------------------------------------------------------- newQuad = [] anAngle = anAngle * pi/180.0 repeat with j = 1 to 4 thisPoint = aQuad[j] x = thisPoint[1] - anOffSet[1] y = thisPoint[2] - anOffSet[2] thisPoint[1] = x * cos(anAngle) - y * sin(anAngle) thisPoint[2] = x * sin(anAngle) + y * cos(anAngle) newQuad[j] = thisPoint + anOffSet end repeat return newQuad end --##[CONFIG]### on getPropertyDescriptionList (me)------------------------------------ -- Method description -------------------------------------------------------------------- pdList = [:] -- if the currentSpriteNum then if sprite(the currentSpriteNum).member.depth <> 32 then alert "Apply this to 32-bit members" end if -- pdList[#myBrushMember] = [:] pdList[#myBrushMember][#Comment] = "Member to use as a brush:" pdList[#myBrushMember][#format] = #Bitmap pdList[#myBrushMember][#default] = member("wipe") -- pdList[#myScratchDepth] = [:] pdList[#myScratchDepth][#Comment] = "Scratch Depth:" pdList[#myScratchDepth][#format] = #integer pdList[#myScratchDepth][#default] = 128 pdList[#myScratchDepth][#range] = [#min: 0, #max: 255] -- pdList[#myRate] = [:] pdList[#myRate][#Comment] = "How many plots before drawing the buffer:" pdList[#myRate][#format] = #Integer pdList[#myRate][#default] = 3 -- -- pdList[#myCursor] = [:] -- pdList[#myCursor][#Comment] = "Cursor for sprite:" -- pdList[#myCursor][#format] = #Cursor -- pdList[#myCursor][#default] = 260 -- return pdList end Drag to Reveal[#myBrushMember: [#comment: "Member to use as a brush:", #format: #bitmap, #default: (member 11 of castLib 1)], #myScratchDepth: [#comment: "Scratch Depth:", #format: #integer, #default: 128, #range: [#min: 0, #max: 255]], #myRate: [#comment: "How many plots before drawing the buffer:", #format: #integer, #default: 3]]_<0,: ?. .tSAC wipe:j?. .P22% ttSAC scratch:m?. .P@ M tSAC I___i}}}}}}property blankarea, newitem on mouseenter sprite(blankarea).member=member(newitem) end --uncomment below if you want it to restore on mouseleave --on mouseleave -- sprite(blankarea).member=member(blankarea) --end on getpropertydescriptionlist PDL=[:] setaprop PDL, #blankarea, [#comment: "sprite # that is used as the blank area that will be replaced by hide/show items:", #format: #integer, #default: 4] setaprop PDL, #newitem, [#comment: "graphic or film clip to appear in the blank/hide show area:", #format: #graphic, #default: "engine"] return PDL endHide/Show On Rollover[#blankarea: [#comment: "sprite # that is used as the blank area that will be replaced by hide/show items:", #format: #integer, #default: 4], #newitem: [#comment: "graphic or film clip to appear in the blank/hide show area:", #format: #graphic, #default: "engine"]]t,?P?&. .tSAC          --Mask follows cursor behavior property myMask, stageCenter, maskCenter, masktracker, constrainsprite, maskgraphic, on prepareFrame set mousePoint = point(the mouseH, the mouseV) sprite(masktracker).loc= mousePoint+9--centers masktracker to the cursor location if sprite(masktracker).intersects(constrainsprite) then executemask end if end --the following handler will make the mask only work when the cursor intersects the constrainsprite. This could appear to constrain to your stage, if your constrainsprite is the same size as the stage. on executemask set myMask = member maskgraphic --the actual mask image you want to use. Make sure its cast location is immediately following the sprite your masking (your constrain sprite) set stageWidth = the stageRight - the stageLeft set stageHeight = the stageBottom - the stageTop set stageCenter = point(stageWidth/2, stageHeight/2) set maskHeight = the height of myMask set maskWidth = the width of myMask set maskCenter = point(maskWidth/2, maskHeight/2) set mousePoint = point(the mouseH, the mouseV) set the regPoint of myMask to (mousePoint - stageCenter) * -1 + maskCenter end on getpropertydescriptionlist PDL=[:] setaprop PDL, #constrainsprite, [#comment: "What is the sprite# of the sprite the mask will constrain to? (to work, it must also be set to mask ink)",#format: #integer, #default: 9] setaprop PDL, #masktracker, [#comment: "What is the sprite# of the sprite that is tracking the cursor point?",#format: #integer, #default: 10] setaprop PDL, #maskgraphic, [#comment: "Choose your mask: (Make sure its cast location immediately follows the sprite your masking/your constraining sprite)",#format: #graphic, #default: member "mask2"] return PDL endMask follows cursor behavior [#constrainsprite: [#comment: "What is the sprite# of the sprite the mask will constrain to? (to work, it must also be set to mask ink)", #format: #integer, #default: 9], #masktracker: [#comment: "What is the sprite# of the sprite that is tracking the cursor point?", #format: #integer, #default: 10], #maskgraphic: [#comment: "Choose your mask: (Make sure its cast location immediately follows the sprite your masking/your constraining sprite)", #format: #graphic, #default: (member 12 of castLib 1)]]_,?H. .iXtcL`     !$rcsL\\``*xyw+:  JxCWJyCW b CRLExE,DE-EE.ACBWzLEyE,DE-E{E.DCBWzLBW/|VRsprite # that is used as the blank area that will be replaced by hide/show items:83.)$! "'+05;?EINQTW[]`bccba_\YVRNIE@;4/*&" !%)-29>CIMQUX\^bdfggfdb`\YTPLGB=61,'#  #',07=CHLQUY]`cfhjjkihfc_[WSNID>82-($  #&*/5:AHLQVZ_bfilmoppomjgc`[WQLFA:4/*%!#(,27=CIPV[afjmptvxz{zywtplgb]YRLF?82,(# "(.39?EKRY`gmrvy|~~~}}}yyy{{{zzz{{{~~~~ytoje_YRWC;50+&"+!'-4;@GMSZljrx~~~~{{{yyyjjjttttttnnnnnnppprrrsssmmm~~~|wqkebbsF?82,($E!%,3:AGNT[btrzzzzvvvrrrpppbbbiiifffdddfffgggiiikkkfffvvv{{{~xqjeeRJA:3/)&"!$)19@FLSYaisz~~~yyyqqqoooiiigggccc^^^\\\]]]ZZZ^^^___fffiiinnnsss{{{wog_WLD=60+'$ #(-6>EKQW_gqz}}}vvvppplllfffaaa\\\YYYTTTQQQQQQTTTUUUVVVZZZ```dddkkkqqq{{{}tkcZPG?82,)%! "&+1:CINT[dnyvvvooojjjeee```XXXTTTOOOMMMHHHGGGIIIKKKMMMRRRXXX^^^NNNkkkttt}}}zrg^hIA:4.*&"!$(.4>GMRXezzvvvooohhhcccVVVGGGJJJKKKGGGCCC@@@>>>???AAACCCJJJOOOVVVVVVddddddjjj}}}wmb^LMF60,($#'+17AJQW_gxxxxyyyoooeee]]]WWWQQQFFF<<>>999444///''''''"""###%%%(((++++++999333QQQYYYbbbkkkrrruuubbb{WME=73R($*.38?IT^hr{sssggghhhOOOOOODDD===777***###+++ !!!%%%&&&333@@@LLLTTT___fffmmmttt{hYNF?84/*%,05:AKWajt}tttjjjcccXXXJJJBBB:::222)))%%%%%% """)))444===GGGPPPZZZbbbooo|||xh[PH@940+&-16EPZdkt~vvviiiYYYRRRHHH===777///(((!!! )))999HHH>>>TTTfffuuu{rrrcS^I;72-)/38?FQ[d{{{t{{{gggcccVVVOOOGGG$$$555'''  &&&&&&:::<<<===UUUdddqqq~ya]\F<83.).38>FP[dktooo^^^VVVRRREEE;;;333,,, $$$000:::999@@@TTTaaaoooob_WF>:50+.38>EOf{k~zzzvvviii[[[AAA)))888***###$$$ $$$///999@@@GGGPPP]]]lllqdXOG@;61--27=CMg|jwuuubbbWWW555%%%888000(((### 888AAAGGGPPP\\\jjjuuuvvvdYPH@<62-,16;AKZcntttkkk```___LLLCCC333(((  &&&888@@@HHHPPP\\\kkkrrr{dYPHA<72.+05:?Mdt|||llllllTTT>>>''''''(((###   ))):::@@@...HHH]]]mmmyyyxdYjQA<83/*.38=LagcmzrrrhhhSSS===>>>>>>999---  %%%000:::AAAIIIRRR\\\nnnqcXPHA<84/)-27>>HHHQQQ\\\hhhvvvzlaXPIB>951$',05>>HHHRRR[[[dddqqqwwwyyyi^UNG@<851"&*.5@iO^jhp{xxxNNN```RRRAAAAAA<<<333000&&&''''''"""!!!"""'''000---@@@OOOWWWaaajjjtttwl\TMF?;840 $B+5Hb^[_~~~gmmmNNNXXXWWWOOOGGGGGG666///(((555111---,,,---444555999GGGWWW```MMMggg}}}ysiYReM>:73/!@(2DG@HS}i|ooottttttooo```JJJKKK>>>999???;;;<<<888111999>>>CCCLLLWWW```gggmmmvvvti_UNHB<962/!$)3GQXafkpvzzzkkkbbbUUU:::MMM???IIIPPPJJJGGGCCC,,,FFFAAAOOOYYYaaahhhnnnuuu~~~xncYRKE@:741."%0@?CEY^[ex||||wwwbbb]]]VVV\\\]]]VVVQQQOOOGGG<<85?<,"',1Al~ZQX`j~SSS???cccnnnkkkfff```]]]ZZZWWWSSS___eeelllqqqvvv~~~}zjaf^KEA<74=;+#(-6KBGQQYboxxx}}}xxxpppqqqooojjjhhhdddccceeejjjkkknnnxxx{skc]ZNGC>941/,)!$(.3:E]YRZdnw|||ffflllwwwtttrrrqqqnnnnnnqqqpppiiixrkd]\aJD?:61/,*'C$*/4:@FnR[dmty|yyy~|||{{{zzz{{{{{{upib\WQLFA<73/-*(& ,)!&*J59=PJRZbimsvqsuwxwyvkd_ZUPKGA<840,*(%# +"&F037851-*(&$" !%)-15:?E`O]XVWX[r]h`YVQNKHDA=941.*'%#! !%'+.27;@DTMJLMNWf^UOLIFKV>@ACCCA@=<:8641.*(&#  !$(+/24679:<=???><:97531/,(&$! !%(+/134578:;<;:986421/,*'$" "%(,..01346888764310.,*'$" muhT7)+++++++++++++++ ++VVV+++VV++++VVV++++VVV++VV+ ++ V+++V+ ++VVV++ ++V V++ ++ ++V+++++VVV +VV V++++V++ +++++V +!VV++ +VV V+VV VV+++VV++++V++ V+VVVVV++ +VVV++++++++++++++++++++  DTIBmuhTz7)rcsLttt\h \hh <,}/""$$~i(; U  CfCfCWRJCWLA bJCWJCgBV JCW PCfCfRCfCfRLALACWPJaRJaRLALACWPCfCfCWRJLJA Jb CRLEE,DE-EE.A CBWzLEE,DE-EE.A CBWzLEE,DE-E{E.DCW CBWzLBW/|n2iWhat is the sprite# of the sprite the mask will constrain to? (to work, it must also be set to mask ink)EWhat is the sprite# of the sprite that is tracking the cursor point?uChoose your mask: (Make sure its cast location immediately follows the sprite your masking/your constraining sprite)mask2tSACx j|--Drag to Reveal(Alpha Scratcher) -- Use this behavior to paint, rub or scractch off a surface to the next surface below. --Any greyscale cast member you create can be used as a brush for this effect. -- Brush will paints the specified cast member into the alpha channel of the -- member this behaviour is applied to. --Works best when the brush member has an alpha channel. -- The brush is rotated a random amount each time it is -- applied. -- Configuration: -- #Brush: Member to use as the brush -- #Rate: How many processes applied to the bugger before -- the image is drawn. -- #ScratchDepth: This is the blendLevel at which the -- the brush is painted into the alpha channel. -- #Cursor: Optional cursor for the sprite -- Written by Luke Wigley luke@meccamedialight.com.au -- Version 1.0.0 -- Last updated 23/3/01 --##[PROPS] property mySprite property myMember property myOriginalImage property myWorkingImage property myAlphaImage property myBrushMember property myBrush property myBrushRotOffset property myBrushQuad property myRate property myScratchDepth property myCursor --##[EVENTS]####### on BeginSprite (me)--------------------------------------------------- -- beginSprite event handler -------------------------------------------------------------------- me.mInit() me.mCreateBrush(myBrushMember) end on endSprite me------------------------------------------------------- -- endSprite event handler -------------------------------------------------------------------- me.mDestroy() end on mouseWithin (me)--------------------------------------------------- -- mouseWithin event handler -------------------------------------------------------------------- if the mousedown then repeat with i = 1 to myRate pntOnmember = the mouseLoc - point(mySprite.left, mySprite.top) me.mScratch(pntOnmember) end repeat end if end --##[handlers PUBLIC]#### on mInit (me)--------------------------------------------------------- -- Create images -------------------------------------------------------------------- mySprite = sprite(me.spriteNum) myMember = mySprite.member myOriginalImage = myMember.image.duplicate() -- backup for restoring the image myWorkingImage = myMember.image me.mCreateNewAlpha() myWorkingImage.setAlpha(myAlphaImage) myMember.useAlpha = 1 mySprite.cursor = myCursor end on mDestroy (me)------------------------------------------------------ -- standard destructor method -------------------------------------------------------------------- me.mReset() mySprite.cursor = 0 end on mGetScratcherInfo (me)--------------------------------------------- -- returns useful instance information -------------------------------------------------------------------- info = [:] info[#brush] = myBrushMember info[#scratchDepth] = myScratchDepth info[#rate] = myRate return info end on mCreateBrush (me, aMemberRef)-------------------------------------- -- Creates a 'brush' image from the supplied member -------------------------------------------------------------------- myBrushMember = aMemberRef myBrush = myBrushMember.image.duplicate() w = myBrush.rect[3] h = myBrush.rect[4] myBrushRotOffset = point(w/2, h/2) myBrushQuad = [point(0,0), point(w, 0), point(w,h), point(0, h)] end on mSetScratchDepth (me, aDepth)-------------------------------------- -- sets the scratch depth (blend level) -------------------------------------------------------------------- myScratchDepth = aDepth end on mScratch (me, aPoint)---------------------------------------------- -- 'Paints' the brush image into the alpha channel -------------------------------------------------------------------- brushPoint = aPoint - myBrushRotOffset ang = random(360) newQuad = me.mRotateQuad(myBrushQuad.duplicate(),ang, myBrushRotOffset ) repeat with i = 1 to 4 newQuad[i] = newQuad[i] + brushPoint end repeat myAlphaImage.copyPixels(myBrush, newQuad, myBrush.rect, [#color: rgb(255,255,255), #blendlevel: myScratchDepth, #ink: 36]) myWorkingImage.setAlpha(myAlphaImage) end on mReset (me)-------------------------------------------------------- -- returns the member image back to the original -------------------------------------------------------------------- me.mCreateNewAlpha() myWorkingImage.setAlpha(myAlphaImage) end --##[PRIVATE]# --##[UTILITY]### on mCreateNewAlpha (me)----------------------------------------------- -- Utility script: Creates a black rect to use as -- an alpha channel -------------------------------------------------------------------- myAlphaImage = image(myOriginalImage.rect[3], myOriginalImage.rect[4], 8, #grayscale) myAlphaImage.fill(myOriginalImage.rect, rgb(0,0,0)) end on mRotateQuad (me, aQuad, anAngle, anOffSet)------------------------- -- rotates the supplied quad. Angle is specified -- in degrees. -------------------------------------------------------------------- newQuad = [] anAngle = anAngle * pi/180.0 repeat with j = 1 to 4 thisPoint = aQuad[j] x = thisPoint[1] - anOffSet[1] y = thisPoint[2] - anOffSet[2] thisPoint[1] = x * cos(anAngle) - y * sin(anAngle) thisPoint[2] = x * sin(anAngle) + y * cos(anAngle) newQuad[j] = thisPoint + anOffSet end repeat return newQuad end --##[CONFIG]### on getPropertyDescriptionList (me)------------------------------------ -- Method description -------------------------------------------------------------------- pdList = [:] -- if the currentSpriteNum then if sprite(the currentSpriteNum).member.depth <> 32 then alert "Apply this to 32-bit members" end if -- pdList[#myBrushMember] = [:] pdList[#myBrushMember][#Comment] = "Member to use as a brush:" pdList[#myBrushMember][#format] = #Bitmap pdList[#myBrushMember][#default] = member("wipe") -- pdList[#myScratchDepth] = [:] pdList[#myScratchDepth][#Comment] = "Scratch Depth:" pdList[#myScratchDepth][#format] = #integer pdList[#myScratchDepth][#default] = 128 pdList[#myScratchDepth][#range] = [#min: 0, #max: 255] -- pdList[#myRate] = [:] pdList[#myRate][#Comment] = "How many plots before drawing the buffer:" pdList[#myRate][#format] = #Integer pdList[#myRate][#default] = 3 -- -- pdList[#myCursor] = [:] -- pdList[#myCursor][#Comment] = "Cursor for sprite:" -- pdList[#myCursor][#format] = #Cursor -- pdList[#myCursor][#default] = 260 -- return pdList end Drag to Reveal[#myBrushMember: [#comment: "Member to use as a brush:", #format: #bitmap, #default: (member 11 of castLib 1)], #myScratchDepth: [#comment: "Scratch Depth:", #format: #integer, #default: 128, #range: [#min: 0, #max: 255]], #myRate: [#comment: "How many plots before drawing the buffer:", #format: #integer, #default: 3]]_<0,: ?. .tSAC          --Mask follows cursor behavior property myMask, stageCenter, maskCenter, masktracker, constrainsprite, maskgraphic, on prepareFrame set mousePoint = point(the mouseH, the mouseV) sprite(masktracker).loc= mousePoint+9--centers masktracker to the cursor location if sprite(masktracker).intersects(constrainsprite) then executemask end if end --the following handler will make the mask only work when the cursor intersects the constrainsprite. This could appear to constrain to your stage, if your constrainsprite is the same size as the stage. on executemask set myMask = member maskgraphic --the actual mask image you want to use. Make sure its cast location is immediately following the sprite your masking (your constrain sprite) set stageWidth = the stageRight - the stageLeft set stageHeight = the stageBottom - the stageTop set stageCenter = point(stageWidth/2, stageHeight/2) set maskHeight = the height of myMask set maskWidth = the width of myMask set maskCenter = point(maskWidth/2, maskHeight/2) set mousePoint = point(the mouseH, the mouseV) set the regPoint of myMask to (mousePoint - stageCenter) * -1 + maskCenter end on getpropertydescriptionlist PDL=[:] setaprop PDL, #constrainsprite, [#comment: "What is the sprite# of the sprite the mask will constrain to? (to work, it must also be set to mask ink)",#format: #integer, #default: 9] setaprop PDL, #masktracker, [#comment: "What is the sprite# of the sprite that is tracking the cursor point?",#format: #integer, #default: 10] setaprop PDL, #maskgraphic, [#comment: "Choose your mask: (Make sure its cast location immediately follows the sprite your masking/your constraining sprite)",#format: #graphic, #default: member "mask2"] return PDL endMask follows cursor behavior [#constrainsprite: [#comment: "What is the sprite# of the sprite the mask will constrain to? (to work, it must also be set to mask ink)", #format: #integer, #default: 9], #masktracker: [#comment: "What is the sprite# of the sprite that is tracking the cursor point?", #format: #integer, #default: 10], #maskgraphic: [#comment: "Choose your mask: (Make sure its cast location immediately follows the sprite your masking/your constraining sprite)", #format: #graphic, #default: (member 12 of castLib 1)]]_,?H. .ktSACi [ --Custom global list to track the visitation to hotspot 2 - (1=true 0=false) --To be used with Record Visits To multiple areas --The extra member commands are just to clear the fields on startup --------------------------------------------------------------- on startmovie global gList set gList = [#visited2:0] member("areaUin").text="" member("areaULastin").text="" member("area2visits").text="" end Global List for Item Changen,>ؼ?. .rcsL\~\ll8>@  Rprr r$r)v -D  WC#224 4 JCWPJ CWPJp p Cg P  CfPJJaCgPJ JJa_P  JCf KBgP _JRJLCgRLCWLJaJaCWRJJ LECgRLvJLRLaRLaRLCWLCWCWRLLCWRLLCW RL2LARLLLRJ LECgRL LART2LLR LL PLL RJLb%&'#()$*"!    CRLE E,DE-EE.ACBW+LBW/09What channel is your contraining/mask sprite located in?rcsL\\``*xyw+:  JxCWJyCW b CRLExE,DE-EE.ACBWzLEyE,DE-E{E.DCBWzLBW/|VRsprite # that is used as the blank area that will be replaced by hide/show items:@  Rprr r$r)v -D  WC#224 4 JCWPJ CWPJp p Cg P  CfPJJaCgPJ JJa_P  JCf KBgP _JRJLCgRLCWLJaJaCWRJJ LECgRLvJLRLaRLaRLCWLCWCWRLLCWRLLCW RL2LARLLLRJ LECgRL LART2LLR LL PLL RJLb%&'#()$*"!    CRLE E,DE-EE.ACBW+LBW/09What channel is your contraining/mask sprite located in?rcsL\  \t t>ABDE<PST=MH11^92 6$&*!@*3;2nppQ p4 z s_5* Tg6X" r"7*044 /~48{8  9D:0z;6KBg3KJaJ>aCWRKLBg8ALRT(@?  KaCWP>J>a PAJAp CgCPBJAa PDKBg:JDJEBgFJAAbGJ>JHbI  KBg9J>bICRLEJJ/v?. .tSAC  !555555IIIIIIMQU--The behavior sends a message or even actions based on the mouse's last clicked location. This happens when a sprite travels along with your mouse. It is NOT to be confused with tracking the mousemember or mouse coordinate location as it DOES require a sprite to be attached to your cursor. even if it is a clear 1 pixel. The example below puts the text message "area1" in the field "areaULastin" when the last location clicked was area 1. As an example, when you drag from area 1 to another area, the last mousedown or "clicked" area would have been area 1. As such, it will report that location. --This is useful for testing whether or not a sprite may be moved to a new location based on its previous one or if you just need to know where it came from. --The "mousesprite" entity can be draggable or made to stick to you cursor all the time by adding the "stick to cursor" behavior found on my site. A simular behavior is found on many others as well. If you do not want to see the sprite under your cursor, you can make it a 1-5 pixel transparent sprite that never gets seen and always sticks to the cursor's point by using the "stick to" behavior mentioned above. --If you are wondering why I am using a "mousesprite", instead of the mouses coordinates, it is for no other reason other than simplicity and for what I was doing, the sprite sending the messages was draggable. --To work, simply attach this behavior to the sprite that will be under the cursor. --The easiest way to create hotspots is to use director's vector window and make a square (or any shape) with a red border. Hotspots you drag on the stage will be referenced by their sprite numbers. As mentioned, change the borders to "none" when you are finished to make them all invisible. --For convienience, you can select the sprite numbers for the hotspots from the custom parameters dialogue box that I have created. This current behavior is set to handle 3. hotspots. If you need more just add them to the mouseup events and property description list down in this script. --Remember, the commands you envoke do not have to be text messages like I have used, they can be any command you can think of. --This is a lot of notes for the script you are about to see, but I wanted to show you the methodology. property spriteNum property hotspotNum1 property hotspotNum2 property hotspotNum3 property area1 property area2 property area3 on mousedown if sprite(Spritenum).within(hotspotNum1) then area1 = true else area1=false if sprite(Spritenum).within(hotspotNum2) then area2 = true else area2=false if sprite(Spritenum).within(hotspotNum3) then area3 = true else area3=false end if end if end if end on mouseup if area1=true then member("areaULastin").text="area1" if area2=true then member("areaULastin").text="area2" if area3=true then member("areaULastin").text="area3" end if end if end if end ---------------------------------------------------------- on getPropertyDescriptionList vPDList = [:] setaProp vPDList, #hotspotNum1, [#comment: "Choose hotspot 1's sprite numer", #format: #integer, #range: [#min: 1, #max: 60], #default: 5] setaProp vPDList, #hotspotNum2, [#comment: "Choose hotspot 2's sprite numer", #format: #integer, #range: [#min: 1, #max: 60], #default: 6] setaProp vPDList, #hotspotNum3, [#comment: "Choose hotspot 3's sprite numer", #format: #integer, #range: [#min: 1, #max: 60], #default: 7] return vPDList end getPropertyDescriptionList MessageBasedOnLastMouseLocation[#hotspotNum1: [#comment: "Choose hotspot 1's sprite numer", #format: #integer, #range: [#min: 1, #max: 60], #default: 5], #hotspotNum2: [#comment: "Choose hotspot 2's sprite numer", #format: #integer, #range: [#min: 1, #max: 60], #default: 6], #hotspotNum3: [#comment: "Choose hotspot 3's sprite numer", #format: #integer, #range: [#min: 1, #max: 60], #default: 7]]}# ,>/v?. .tSAC s''''''+/3--This behavior records/tracks the visits to a certain hotspot area when the mouse or the sprite attached to the mouse is within the certain hotspot. For reasons why I am using hotspots and a "mousesprite" (sprite attached to the cursor), see my comments for my "Message Based on Mouse Location" behavior. --Anyway, This behavior will store the visit as being either true or false (1 or 0) and then displays a different message based on if you have visited the area or not. In the example below, the message is displayed when you mouseup on hotspot 3. --As always, You can change it from displaying a message to be any command for your own project. --IMPORTANT! For this behavior to work, you must also have the "Global List for Item Change" movie behavior. This behavior sets a global list that will contain the condition that you will set. Think of Global list as containers for your entire project that can store conditions, properties and other kinds of items. Just like a cookie jar, you can reach in and grab your stored "goodie" whenever the need for it arises. --If you have downloaded this behavior from my site, you will see that "Global List for Item Change" behavior is really for a list with 2 properties. The list you will need in this behavior requires only 1 property called "visited2". Simply delete one (can be either one) and change the other to say [#visited2:0] Which means visited2 will initially be set to 0 or false. --Of course when you add your own properties, you will be changing the list with to your own conditions. --If using list are new to you, then the way to understand it is that the item after the "#" is the property and the item after the ":" is the value. In this examaple, the values are the only things being replaced in the list. --To really help in testing your list, it is highly reccomended that you use the director's "message window" while playing back your project. While running, simply type in "put glist" in the message window. This will return the current contents of your list. It's basically a window into your cookie jar. Really helps to show how things are working. --As you learn more about lists, you will see that you can dynamically remove and add properties during runtime as well. As seen, using list will open a whole new set of doors for you when working in director. If would like to learn more about tracking things using a list then there are many good books about lingo that will explain more. ---------------------------------------------- property spriteNum property hotspotNum1 property hotspotNum2 property hotspotNum3 property visited2 ----------------------------------------------- on mousedown global glist --declares glist as being the global list you will be using if sprite(spritenum).within(hotspotNum2)then glist [#visited2]=1 --updates list based on the condition end if end on mouseup global glist-- declares it again. It must be declared every event that uses it --The following compares the conditions and then executes an action based on the properties of this list if sprite(Spritenum).within(hotspotNum3) and glist [#visited2]=1 then member("area2visits").text= "area #2 has been visited" if sprite(Spritenum).within(hotspotNum3) and glist [#visited2]=0 then member("area2visits").text= "area #2 has not been visited" end if end if end --------------------------------------------------- on getPropertyDescriptionList --creates the parameters dialogue box vPDList = [:] setaProp vPDList, #hotspotNum1, [#comment: "Choose hotspot 1's sprite numer", #format: #integer, #range: [#min: 1, #max: 60], #default: 5] setaProp vPDList, #hotspotNum2, [#comment: "Choose hotspot 2's sprite numer", #format: #integer, #range: [#min: 1, #max: 60], #default: 6] setaProp vPDList, #hotspotNum3, [#comment: "Choose hotspot 3's sprite numer", #format: #integer, #range: [#min: 1, #max: 60], #default: 7] return vPDList end getPropertyDescriptionList Record Mouse Location Visits[#hotspotNum1: [#comment: "Choose hotspot 1's sprite numer", #format: #integer, #range: [#min: 1, #max: 60], #default: 5], #hotspotNum2: [#comment: "Choose hotspot 2's sprite numer", #format: #integer, #range: [#min: 1, #max: 60], #default: 6], #hotspotNum3: [#comment: "Choose hotspot 3's sprite numer", #format: #integer, #range: [#min: 1, #max: 60], #default: 7]]n I ,>Ϙ?. .rcsL\  \t t>ABDE<PST=MH11^92 6$&*!@*3;2nppQ p4 z s_5* Tg6X" r"7*044 /~48{8  9D:0z;6KBg3KJaJ>aCWRKLBg8ALRT(@?  KaCWP>J>a PAJAp CgCPBJAa PDKBg:JDJEBgFJAAbGJ>JHbI  KBg9J>bICRLEJJknuj*muhT"tSAC Zknuj ~knujpj*muhT_PtSAC tSAC&tSAC$knuj+2knujT0knujF*@knuj8<rcsL@rcsLCrcsL$FmuhT~MmuhT^QmuhTLUknujN*(knujT.knujlV/1*SAC(knuj}"/&knujxPR4knujm5knujn6knujBo7knuj `s8knuj|9knuj:knujL;knuj}<knujt^=knuj8>knuj ,?