Vendily

kind of zoom

Mar 2nd, 2018
170
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. def createTinimap(mapid,scale)
  2.   map=load_data(sprintf("Data/Map%03d.rxdata",mapid)) rescue nil
  3.   return BitmapWrapper.new(32,32) if !map
  4.   bitmap=BitmapWrapper.new(map.width*scale,map.height*scale)
  5.   black=Color.new(0,0,0)
  6.   tilesets=load_data("Data/Tilesets.rxdata")
  7.   tileset=tilesets[map.tileset_id]
  8.   return bitmap if !tileset
  9.   helper=TileDrawingHelper.fromTileset(tileset)
  10.   for y in 0...map.height
  11.     for x in 0...map.width
  12.       for z in 0..2
  13.         id=map.data[x,y,z]
  14.         id=0 if !id
  15.         helper.bltSmallTile(bitmap,x*scale,y*scale,scale,scale,id)
  16.       end
  17.     end
  18.   end
  19.   bitmap.fill_rect(0,0,bitmap.width,1,black)
  20.   bitmap.fill_rect(0,bitmap.height-1,bitmap.width,1,black)
  21.   bitmap.fill_rect(0,0,1,bitmap.height,black)
  22.   bitmap.fill_rect(bitmap.width-1,0,1,bitmap.height,black)
  23.   return bitmap
  24. end
  25.  
  26. class MapScreenScene
  27. LOCALMAPS=[
  28.    ["Outdoor",BooleanProperty,
  29.         _INTL("If true, this map is an outdoor map and will be tinted according to time of day.")],
  30.    ["ShowArea",BooleanProperty,
  31.        _INTL("If true, the game will display the map's name upon entry.")],
  32.    ["Bicycle",BooleanProperty,
  33.        _INTL("If true, the bicycle can be used on this map.")],
  34.    ["BicycleAlways",BooleanProperty,
  35.        _INTL("If true, the bicycle will be mounted automatically on this map and cannot be dismounted.")],
  36.    ["HealingSpot",MapCoordsProperty,
  37.         _INTL("Map ID of this Pokemon Center's town, and X and Y coordinates of its entrance within that town.")],
  38.    ["Weather",WeatherEffectProperty,
  39.        _INTL("Weather conditions in effect for this map.")],
  40.    ["MapPosition",RegionMapCoordsProperty,
  41.        _INTL("Identifies the point on the regional map for this map.")],
  42.    ["DiveMap",MapProperty,
  43.        _INTL("Specifies the underwater layer of this map. Use only if this map has deep water.")],
  44.    ["DarkMap",BooleanProperty,
  45.        _INTL("If true, this map is dark and a circle of light appears around the player. Flash can be used to expand the circle.")],
  46.    ["SafariMap",BooleanProperty,
  47.        _INTL("If true, this map is part of the Safari Zone (both indoor and outdoor). Not to be used in the reception desk.")],
  48.    ["SnapEdges",BooleanProperty,
  49.        _INTL("If true, when the player goes near this map's edge, the game doesn't center the player as usual.")],
  50.    ["Dungeon",BooleanProperty,
  51.        _INTL("If true, this map has a randomly generated layout. See the wiki for more information.")],
  52.    ["BattleBack",StringProperty,
  53.        _INTL("PNG files named 'battlebgXXX', 'enemybaseXXX', 'playerbaseXXX' in Battlebacks folder, where XXX is this property's value.")],
  54.    ["WildBattleBGM",BGMProperty,
  55.        _INTL("Default BGM for wild Pokémon battles on this map.")],
  56.    ["TrainerBattleBGM",BGMProperty,
  57.        _INTL("Default BGM for trainer battles on this map.")],
  58.    ["WildVictoryME",MEProperty,
  59.        _INTL("Default ME played after winning a wild Pokémon battle on this map.")],
  60.    ["TrainerVictoryME",MEProperty,
  61.        _INTL("Default ME played after winning a Trainer battle on this map.")],
  62.    ["MapSize",MapSizeProperty,
  63.        _INTL("The width of the map in Town Map squares, and a string indicating which squares are part of this map.")],
  64. ]
  65. GLOBALMETADATA=[
  66.    ["Home",MapCoordsFacingProperty,
  67.        _INTL("Map ID and X and Y coordinates of where the player goes if no Pokémon Center was entered after a loss.")],
  68.    ["WildBattleBGM",BGMProperty,
  69.        _INTL("Default BGM for wild Pokémon battles.")],
  70.    ["TrainerBattleBGM",BGMProperty,
  71.        _INTL("Default BGM for Trainer battles.")],
  72.    ["WildVictoryME",MEProperty,
  73.        _INTL("Default ME played after winning a wild Pokémon battle.")],
  74.    ["TrainerVictoryME",MEProperty,
  75.        _INTL("Default ME played after winning a Trainer battle.")],
  76.    ["SurfBGM",BGMProperty,
  77.        _INTL("BGM played while surfing.")],
  78.    ["BicycleBGM",BGMProperty,
  79.        _INTL("BGM played while on a bicycle.")],
  80.    ["PlayerA",PlayerProperty,
  81.        _INTL("Specifies player A.")],
  82.    ["PlayerB",PlayerProperty,
  83.        _INTL("Specifies player B.")],
  84.    ["PlayerC",PlayerProperty,
  85.        _INTL("Specifies player C.")],
  86.    ["PlayerD",PlayerProperty,
  87.        _INTL("Specifies player D.")],
  88.    ["PlayerE",PlayerProperty,
  89.        _INTL("Specifies player E.")],
  90.    ["PlayerF",PlayerProperty,
  91.        _INTL("Specifies player F.")],
  92.    ["PlayerG",PlayerProperty,
  93.        _INTL("Specifies player G.")],
  94.    ["PlayerH",PlayerProperty,
  95.        _INTL("Specifies player H.")]
  96. ]
  97.  
  98.   def getMapSprite(id)
  99.     if !@mapsprites[id]
  100.       @mapsprites[id]=Sprite.new(@viewport)
  101.       @mapsprites[id].z=0
  102.       @mapsprites[id].bitmap=nil
  103.     end
  104.     if !@mapsprites[id].bitmap || @mapsprites[id].bitmap.disposed?
  105.       @mapsprites[id].bitmap=createTinimap(id,@zoomScale)
  106.     end
  107.     return @mapsprites[id]
  108.   end
  109.  
  110.   def close
  111.     pbDisposeSpriteHash(@sprites)
  112.     pbDisposeSpriteHash(@mapsprites)
  113.     @viewport.dispose
  114.   end
  115.  
  116.   def setMapSpritePos(id,x,y)
  117.     sprite=getMapSprite(id)
  118.     sprite.x=x
  119.     sprite.y=y
  120.     sprite.visible=true
  121.   end
  122.  
  123.   def putNeighbors(id,sprites)
  124.     conns=@mapconns
  125.     mapsprite=getMapSprite(id)
  126.     dispx=mapsprite.x
  127.     dispy=mapsprite.y
  128.     for conn in conns
  129.       if conn[0]==id
  130.         b=sprites.any? {|i| i==conn[3] }
  131.         if !b
  132.           x=(conn[1]-conn[4])*@zoomScale+dispx #edit
  133.           y=(conn[2]-conn[5])*@zoomScale+dispy #edit
  134.           setMapSpritePos(conn[3],x,y)
  135.           sprites.push(conn[3])
  136.           putNeighbors(conn[3],sprites)
  137.         end
  138.       elsif conn[3]==id
  139.         b=sprites.any? {|i| i==conn[0] }
  140.         if !b
  141.           x=(conn[4]-conn[1])*@zoomScale+dispx #edit
  142.           y=(conn[5]-conn[2])*@zoomScale+dispy #edit
  143.           setMapSpritePos(conn[0],x,y)
  144.           sprites.push(conn[3])
  145.           putNeighbors(conn[0],sprites)
  146.         end
  147.       end
  148.     end
  149.   end
  150.  
  151.   def hasConnections?(conns,id)
  152.     for conn in conns
  153.       return true if conn[0]==id || conn[3]==id
  154.     end
  155.     return false
  156.   end
  157.  
  158.   def connectionsSymmetric?(conn1,conn2)
  159.     if conn1[0]==conn2[0]
  160.       # Equality
  161.       return false if conn1[1]!=conn2[1]
  162.       return false if conn1[2]!=conn2[2]
  163.       return false if conn1[3]!=conn2[3]
  164.       return false if conn1[4]!=conn2[4]
  165.       return false if conn1[5]!=conn2[5]
  166.       return true
  167.     elsif conn1[0]==conn2[3]
  168.       # Symmetry
  169.       return false if conn1[1]!=-conn2[1]
  170.       return false if conn1[2]!=-conn2[2]
  171.       return false if conn1[3]!=conn2[0]
  172.       return false if conn1[4]!=-conn2[4]
  173.       return false if conn1[5]!=-conn2[5]
  174.       return true
  175.     end
  176.     return false
  177.   end
  178.  
  179.   def removeOldConnections(ret,mapid)
  180.     for i in 0...ret.length
  181.       ret[i]=nil if ret[i][0]==mapid || ret[i][3]==mapid
  182.     end
  183.     ret.compact!
  184.   end
  185.  
  186. # Returns the maps within _keys_ that are directly connected to this map, _map_.
  187.   def getDirectConnections(keys,map)
  188.     thissprite=getMapSprite(map)
  189.     thisdims=MapFactoryHelper.getMapDims(map)
  190.     ret=[]
  191.     for i in keys
  192.       next if i==map
  193.       othersprite=getMapSprite(i)
  194.       otherdims=MapFactoryHelper.getMapDims(i)
  195.       x1=(thissprite.x-othersprite.x)/@zoomScale #edit
  196.       y1=(thissprite.y-othersprite.y)/@zoomScale #edit
  197.       if (x1==otherdims[0] || x1==-thisdims[0] ||
  198.           y1==otherdims[1] || y1==-thisdims[1])
  199.         ret.push(i)
  200.       end  
  201.     end
  202.     # If no direct connections, add an indirect connection
  203.     if ret.length==0
  204.       key=(map==keys[0]) ? keys[1] : keys[0]
  205.       ret.push(key)
  206.     end
  207.     return ret
  208.   end
  209.  
  210.   def generateConnectionData
  211.     ret=[]
  212.     # Create a clone of current map connection
  213.     for conn in @mapconns
  214.       ret.push(conn.clone)
  215.     end
  216.     keys=@mapsprites.keys
  217.     return ret if keys.length<2
  218.     # Remove all connections containing any sprites on the canvas from the array
  219.     for i in keys
  220.       removeOldConnections(ret,i)
  221.     end
  222.     # Rebuild connections
  223.     for i in keys
  224.       refs=getDirectConnections(keys,i)
  225.       for refmap in refs
  226.         othersprite=getMapSprite(i)
  227.         refsprite=getMapSprite(refmap)
  228.         c1=(refsprite.x-othersprite.x)/@zoomScale #edit
  229.         c2=(refsprite.y-othersprite.y)/@zoomScale #edit
  230.         conn=[refmap,0,0,i,c1,c2]
  231.         j=0;while j<ret.length && !connectionsSymmetric?(ret[j],conn)
  232.           j+=1
  233.         end
  234.         if j==ret.length
  235.           ret.push(conn)
  236.         end
  237.       end
  238.     end
  239.     return ret
  240.   end
  241.  
  242.   def serializeConnectionData
  243.     conndata=generateConnectionData()
  244.     pbSerializeConnectionData(conndata,@mapinfos)
  245.     @mapconns=conndata
  246.   end
  247.  
  248.   def putSprite(id)
  249.     addSprite(id)
  250.     putNeighbors(id,[])
  251.   end
  252.  
  253.   def addSprite(id)
  254.     mapsprite=getMapSprite(id)
  255.     x=(Graphics.width-mapsprite.bitmap.width)/2
  256.     y=(Graphics.height-mapsprite.bitmap.height)/2
  257.     mapsprite.x=x.to_i&~3
  258.     mapsprite.y=y.to_i&~3
  259.   end
  260.  
  261.   def saveMapSpritePos
  262.     @mapspritepos.clear
  263.     for i in @mapsprites.keys
  264.       s=@mapsprites[i]
  265.       @mapspritepos[i]=[s.x,s.y] if s && !s.disposed?
  266.     end
  267.   end
  268.  
  269.   def mapScreen
  270.     @sprites={}
  271.     @mapsprites={}
  272.     @mapspritepos={}
  273.     @zoomScale=4 #edit
  274.     @viewport=Viewport.new(0,0,Graphics.width,Graphics.height)
  275.     @viewport.z=99999
  276.     @lasthitmap=-1
  277.     @lastclick=-1
  278.     @oldmousex=nil
  279.     @oldmousey=nil
  280.     @dragging=false
  281.     @dragmapid=-1
  282.     @dragOffsetX=0
  283.     @dragOffsetY=0
  284.     @selmapid=-1
  285.     addBackgroundPlane(@sprites,"background","trainercardbg",@viewport)
  286.     @sprites["selsprite"]=SelectionSprite.new(@viewport)
  287.     @sprites["title"]=Window_UnformattedTextPokemon.new(_INTL("F5: Help"))
  288.     @sprites["title"].x=0
  289.     @sprites["title"].y=Graphics.height-64
  290.     @sprites["title"].width=Graphics.width
  291.     @sprites["title"].height=64
  292.     @sprites["title"].viewport=@viewport
  293.     @sprites["title"].z=2
  294.     @mapinfos=load_data("Data/MapInfos.rxdata")
  295.     @encdata=load_data("Data/encounters.dat")
  296.     conns=MapFactoryHelper.getMapConnections
  297.     @mapconns=[]
  298.     for c in conns
  299.       @mapconns.push(c.clone)
  300.     end
  301.     @metadata=load_data("Data/metadata.dat")
  302.     if $game_map
  303.       @currentmap=$game_map.map_id
  304.     else
  305.       system=load_data("Data/System.rxdata")
  306.       @currentmap=system.edit_map_id
  307.     end
  308.     putSprite(@currentmap)
  309.   end
  310.  
  311.   def setTopSprite(id)
  312.     for i in @mapsprites.keys
  313.       if i==id
  314.         @mapsprites[i].z=1
  315.       else
  316.         @mapsprites[i].z=0
  317.       end
  318.     end
  319.   end
  320.  
  321.   def getMetadata(mapid,metadataType)
  322.     return @metadata[mapid][metadataType] if @metadata[mapid]
  323.   end
  324.  
  325.   def setMetadata(mapid,metadataType,data)
  326.     @metadata[mapid]=[] if !@metadata[mapid]
  327.     @metadata[mapid][metadataType]=data
  328.   end
  329.  
  330.   def serializeMetadata
  331.     pbSerializeMetadata(@metadata,@mapinfos)
  332.   end
  333.  
  334.   def helpWindow
  335.     helptext=_INTL("A: Add map to canvas\r\n")
  336.     helptext+=_INTL("DEL: Delete map from canvas\r\n")
  337.     helptext+=_INTL("S: Go to another map\r\n")
  338.     helptext+=_INTL("Click to select a map\r\n")
  339.     helptext+=_INTL("Double-click: Edit map's metadata\r\n")
  340.     helptext+=_INTL("E: Edit map's encounters\r\n")
  341.     helptext+=_INTL("Drag map to move it\r\n")
  342.     helptext+=_INTL("Arrow keys/drag canvas: Move around canvas")
  343.     title=Window_UnformattedTextPokemon.new(helptext)
  344.     title.x=0
  345.     title.y=0
  346.     title.width=Graphics.width*8/10
  347.     title.height=Graphics.height
  348.     title.viewport=@viewport
  349.     title.z=2
  350.     loop do
  351.       Graphics.update
  352.       Input.update
  353.       break if Input.trigger?(Input::C)
  354.       break if Input.trigger?(Input::B)
  355.     end
  356.     Input.update
  357.     title.dispose
  358.   end
  359.  
  360.   def propertyList(map,properties)
  361.     infos=load_data("Data/MapInfos.rxdata")
  362.     mapname=(map==0) ? _INTL("Global Metadata") : infos[map].name
  363.     data=[]
  364.     for i in 0...properties.length
  365.       data.push(getMetadata(map,i+1))
  366.     end
  367.     pbPropertyList(mapname,data,properties)
  368.     for i in 0...properties.length
  369.       setMetadata(map,i+1,data[i])
  370.     end
  371.   end
  372.  
  373.   def getMapRect(mapid)
  374.     sprite=getMapSprite(mapid)
  375.     if sprite
  376.       return [
  377.          sprite.x,
  378.          sprite.y,
  379.          sprite.x+sprite.bitmap.width,
  380.          sprite.y+sprite.bitmap.height
  381.       ]
  382.     else
  383.       return nil
  384.     end
  385.   end
  386.  
  387.   def onDoubleClick(mapid)
  388.     if mapid>=0
  389.       propertyList(mapid,LOCALMAPS)
  390.     else
  391.       propertyList(0,GLOBALMETADATA)
  392.     end
  393.   end
  394.  
  395.   def onClick(mapid,x,y)
  396.     if @lastclick>0 && Graphics.frame_count-@lastclick<15
  397.       onDoubleClick(mapid)
  398.       @lastclick=-1
  399.     else
  400.       @lastclick=Graphics.frame_count
  401.       if mapid>=0
  402.         @dragging=true
  403.         @dragmapid=mapid
  404.         sprite=getMapSprite(mapid)
  405.         @sprites["selsprite"].othersprite=sprite
  406.         @selmapid=mapid
  407.         @dragOffsetX=sprite.x-x
  408.         @dragOffsetY=sprite.y-y
  409.         setTopSprite(mapid)
  410.       else
  411.         @sprites["selsprite"].othersprite=nil
  412.         @dragging=true
  413.         @dragmapid=mapid
  414.         @selmapid=-1
  415.         @dragOffsetX=x
  416.         @dragOffsetY=y
  417.         saveMapSpritePos
  418.       end
  419.     end
  420.   end
  421.  
  422.   def onRightClick(mapid,x,y)
  423. #   echo("rightclick (#{mapid})\r\n")
  424.   end
  425.  
  426.   def onMouseUp(mapid)
  427. #   echo("mouseup (#{mapid})\r\n")
  428.     @dragging=false if @dragging
  429.   end
  430.  
  431.   def onRightMouseUp(mapid)
  432. #   echo("rightmouseup (#{mapid})\r\n")
  433.   end
  434.  
  435.   def onMouseOver(mapid,x,y)
  436. #   echo("mouseover (#{mapid},#{x},#{y})\r\n")
  437.   end
  438.  
  439.   def onMouseMove(mapid,x,y)
  440. #   echo("mousemove (#{mapid},#{x},#{y})\r\n")
  441.     if @dragging
  442.       if @dragmapid>=0
  443.         sprite=getMapSprite(@dragmapid)
  444.         x=x+@dragOffsetX
  445.         y=y+@dragOffsetY
  446.         sprite.x=x&~3
  447.         sprite.y=y&~3
  448.         @sprites["title"].text=_ISPRINTF("F5: Help [{1:03d} {2:s}]",mapid,@mapinfos[@dragmapid].name)
  449.       else
  450.         xpos=x-@dragOffsetX
  451.         ypos=y-@dragOffsetY
  452.         for i in @mapspritepos.keys
  453.           sprite=getMapSprite(i)
  454.           sprite.x=(@mapspritepos[i][0]+xpos)&~3
  455.           sprite.y=(@mapspritepos[i][1]+ypos)&~3
  456.         end
  457.         @sprites["title"].text=_INTL("F5: Help")
  458.       end
  459.     else
  460.       if mapid>=0
  461.         @sprites["title"].text=_ISPRINTF("F5: Help [{1:03d} {2:s}]",mapid,@mapinfos[mapid].name)
  462.       else
  463.         @sprites["title"].text=_INTL("F5: Help")
  464.       end
  465.     end
  466.   end
  467.  
  468.   def hittest(x,y)
  469.     for i in @mapsprites.keys
  470.       sx=@mapsprites[i].x
  471.       sy=@mapsprites[i].y
  472.       sr=sx+@mapsprites[i].bitmap.width
  473.       sb=sy+@mapsprites[i].bitmap.height
  474.       return i if x>=sx && x<sr && y>=sy && y<sb
  475.     end
  476.     return -1
  477.   end
  478.  
  479.   def chooseMapScreen(title,currentmap)
  480.     return pbListScreen(title,MapLister.new(currentmap))
  481.   end
  482.  
  483.   def update
  484.     mousepos=Mouse::getMousePos
  485.     if mousepos
  486.       hitmap=hittest(mousepos[0],mousepos[1])
  487.       if Input.triggerex?(0x01)
  488.         onClick(hitmap,mousepos[0],mousepos[1])  
  489.       elsif Input.triggerex?(0x02)
  490.         onRightClick(hitmap,mousepos[0],mousepos[1])
  491.       elsif Input.releaseex?(0x01)
  492.         onMouseUp(hitmap)
  493.       elsif Input.releaseex?(0x02)
  494.         onRightMouseUp(hitmap)
  495.       else
  496.         if @lasthitmap!=hitmap
  497.           onMouseOver(hitmap,mousepos[0],mousepos[1])
  498.           @lasthitmap=hitmap
  499.         end
  500.         if @oldmousex!=mousepos[0]||@oldmousey!=mousepos[1]
  501.           onMouseMove(hitmap,mousepos[0],mousepos[1])
  502.           @oldmousex=mousepos[0]
  503.           @oldmousey=mousepos[1]
  504.         end
  505.       end
  506.     end
  507.     if Input.press?(Input::UP)
  508.       for i in @mapsprites
  509.         next if !i
  510.         i[1].y+=@zoomScale
  511.       end
  512.     end
  513.     if Input.press?(Input::DOWN)
  514.       for i in @mapsprites
  515.         next if !i
  516.         i[1].y-=@zoomScale
  517.       end
  518.     end
  519.     if Input.press?(Input::LEFT)
  520.       for i in @mapsprites
  521.         next if !i
  522.         i[1].x+=@zoomScale
  523.       end
  524.     end
  525.     if Input.press?(Input::RIGHT)
  526.       for i in @mapsprites
  527.         next if !i
  528.         i[1].x-=@zoomScale
  529.       end
  530.     end
  531.     if Input.triggerex?("A"[0])
  532.       id=chooseMapScreen(_INTL("Add Map"),@currentmap)
  533.       if id>0
  534.         addSprite(id)
  535.         setTopSprite(id)
  536.         @mapconns=generateConnectionData
  537.       end
  538.     elsif Input.triggerex?("S"[0])
  539.       id=chooseMapScreen(_INTL("Go to Map"),@currentmap)
  540.       if id>0
  541.         @mapconns=generateConnectionData
  542.         pbDisposeSpriteHash(@mapsprites)
  543.         @mapsprites.clear
  544.         @sprites["selsprite"].othersprite=nil
  545.         @selmapid=-1
  546.         putSprite(id)
  547.         @currentmap=id
  548.       end
  549.     elsif Input.triggerex?(0x2E) # Delete
  550.       if @mapsprites.keys.length>1 && @selmapid>=0
  551.         @mapsprites[@selmapid].bitmap.dispose
  552.         @mapsprites[@selmapid].dispose
  553.         @mapsprites.delete(@selmapid)
  554.         @sprites["selsprite"].othersprite=nil
  555.         @selmapid=-1
  556.       end
  557.     elsif Input.triggerex?("E"[0])
  558.       pbEncounterEditorMap(@encdata,@selmapid) if @selmapid>=0
  559.     elsif Input.trigger?(Input::F5)
  560.       helpWindow
  561.     elsif Input.trigger?(Input::A)
  562.         params=ChooseNumberParams.new
  563.         params.setRange(1, 32)
  564.         params.setInitialValue(@zoomScale)
  565.         params.setCancelValue(@zoomScale)
  566.         oldScale=@zoomScale
  567.         @zoomScale=Kernel.pbMessageChooseNumber(
  568.            _INTL("Set the px per tile scale."),params)
  569.         if oldScale != @zoomScale
  570.           @mapconns=generateConnectionData
  571.           pbDisposeSpriteHash(@mapsprites)
  572.           @mapsprites.clear
  573.           @sprites["selsprite"].othersprite=nil
  574.           @selmapid=-1
  575.           putSprite(@currentmap)
  576.         end
  577.     end
  578.     pbUpdateSpriteHash(@sprites)
  579.   end
  580.  
  581.   def pbMapScreenLoop
  582.     loop do
  583.       Graphics.update
  584.       Input.update
  585.       update
  586.       if Input.trigger?(Input::B)
  587.         if Kernel.pbConfirmMessage(_INTL("Save changes?"))
  588.           serializeConnectionData
  589.           serializeMetadata
  590.           save_data(@encdata,"Data/encounters.dat")
  591.           pbSaveEncounterData()
  592.           pbClearData
  593.         end
  594.         break if Kernel.pbConfirmMessage(_INTL("Exit from the editor?"))
  595.       end
  596.     end
  597.   end
  598. end
RAW Paste Data