• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

Scene Positioner

FL

Pokémon Island Creator
2,452
Posts
13
Years
    • Seen yesterday
    PokéCommunity is breaking codes. For copying scripts at PokéCommunity: Click Thread Tools, and then Show Printable Version, and copy that instead.

    Code:
    #===============================================================================
    # * Scene Positioner - by FL with some Poccil scripts
    #===============================================================================
    #
    # This script is for RPG Maker XP. This is a scripter tool for helping
    # scripters making scenes. 
    # 
    # It allows reading sprites coordinates in a windows or at txt log and even
    # changing sprites positions/visibility. It is compatible with Pokémon
    # Essentials and Crazyninjaguy Mouse Script, you can even easily adapt
    # other mouse scripts.
    # 
    #===============================================================================
    #
    # To this script works, put it above main and below other scripts. 
    #
    # At every scene that you wish it working, put the line
    # '@scenePositioner = ScenePositioner.new(@sprites)' before update loop
    # where '@sprites' is a hash with all sprites/windows that you wish that
    # this script affect. Put the line '@scenePositioner.update' when you
    # update the graphics and the input at the scene. After you dispose the
    # sprites, put the line '@scenePositioner.destroy'. If you wish to
    # display ox/oy/rotation when displaying coordinates, just use 
    # '@scenePositioner = ScenePositioner.new(@sprites,true)' instead of 
    # '@scenePositioner = ScenePositioner.new(@sprites)'.
    #
    # For obtaining the selected sprite coordinates, a list of all sprites that
    # you moved, a control list and even printing these data in a txt file (except
    # the control list), just press Q.
    #
    # For allowing pause button to pause the game, wrap every update lines, 
    # except 'Graphics.update', 'Input.update' and '@scenePositioner.update' at
    # 'if [email protected]'.
    #
    # For making Crazyninjaguy script working at game that doesn't uses
    # Pokémon Essentials, just put the line '$ResizeFactor=1' before line 
    # 'module Resolution'.
    #
    #===============================================================================
    
    class ScenePositioner
      attr_writer :paused # You can pause by your scripts too.
      
      ONLYINDEBUG = true # If true, this script only works when $DEBUG == true 
      SPEED = 2 # Speed when moving sprites
      
      class Border < Sprite
        def initialize
          super
          @spriteBelow = nil
        end 
        
        def update
          super
          if @spriteBelow && [email protected]?
            [email protected] if [email protected]
            [email protected] if [email protected]
            createBitmap if !self.bitmap
          end
          finishBitmap if self.bitmap && (!@spriteBelow || !(
              @spriteBelow.is_a?(Window) || @spriteBelow.bitmap))
        end
        
        BORDERSIZE = 2
        
        def createBitmap # Draw the border bitmap
          return if !(@spriteBelow.is_a?(Window) || @spriteBelow.bitmap)
          if @spriteBelow.is_a?(Window)
            spriteWidth = @spriteBelow.width
            spriteHeight = @spriteBelow.height 
          else
            spriteWidth = @spriteBelow.bitmap.width
            spriteHeight = @spriteBelow.bitmap.height 
          end  
          self.bitmap=Bitmap.new(spriteWidth,spriteHeight)
          borderColor = Color.new(240,0,0)    
          widthBelowSize = spriteWidth<BORDERSIZE
          heightBelowSize = spriteHeight<BORDERSIZE
          borderWidth = widthBelowSize ? spriteWidth : BORDERSIZE
          borderHeight = heightBelowSize ? spriteHeight : BORDERSIZE
          self.bitmap.fill_rect(Rect.new(0,0,spriteWidth,borderHeight), borderColor)
          self.bitmap.fill_rect(Rect.new(0,spriteHeight-borderHeight,
              spriteWidth,borderHeight), borderColor)
          self.bitmap.fill_rect(Rect.new(0,0,borderWidth,spriteHeight), borderColor)
          self.bitmap.fill_rect(Rect.new(spriteWidth-borderWidth,0,
              borderWidth,spriteHeight), borderColor)
        end
        
        def finishBitmap
          self.bitmap=nil
        end  
        
        def setSpriteBelow(sprite)
          @spriteBelow = sprite
          self.z=9999998
          createBitmap
        end
      end  
      
      def initialize(sprites, showOXOY=false)
        if isActive?
          @lastTone=nil # Used for storing the tone before select a sprite
          @highlight = true
          @paused=false
          @spritesLog = {}
          @spriteSelectedName=nil
          @sprites=sprites
          @mouseClickedStack = []
          @showOXOY=showOXOY
          @border=Border.new
        end
      end
      
      def destroy
        return if !isActive?
        @border.dispose
        @border = nil
      end  
      
      def isActive?
        return !ONLYINDEBUG || $DEBUG
      end
      
      def paused
        @paused && isActive?
      end  
      
      def update
        return if !isActive?
        @border.update
        mouseClicked = mouseClicked?
        move = false
        axisX = 0
        axisY = 0
        
        if mouseClicked
          lastMouseCoordinates = mouseCoordinates
          
          # Pick the biggest Z at point, if already 
          # clicked, picks the second one and so on
          mouseClickStack=[]
          for spriteName in @sprites.keys
            sprite=@sprites[spriteName]
            if sprite && !sprite.is_a?(Plane) && spriteIsOnCoordinate(sprite,
                lastMouseCoordinates[0],lastMouseCoordinates[1])
              mouseClickStack.push(spriteName)
            end    
          end 
          if !mouseClickStack.empty?
            # Do a stack with Z value
            mouseClickStack.sort!{|a,b|@sprites[b].z <=> @sprites[a].z}
            found=false
            for i in 0...mouseClickStack.size
              # if something is different, just copy the entire stack before and 
              # add the different at last.
              if (mouseClickStack[i]!=@mouseClickedStack[i] || 
                  [email protected])
                @mouseClickedStack=mouseClickStack[0,i+1]
                found=true
                break
              end  
            end 
            # If the stacks are equals, just start @mouseClickedStack again.
            @mouseClickedStack=[mouseClickStack[0]] if !found
            selectSprite(@mouseClickedStack[-1])
          end
        end  
        
        spinSelection = 0
        if Input.triggerex?(0x46) # F # Go to the previous sprite
          spinSelection = -1
        end  
        if Input.triggerex?(0x47) # G # Go to the next sprite
          spinSelection = 1
        end
        if spinSelection != 0
          spriteNames = @sprites.keys
          newIndex = spriteNames.index(@spriteSelectedName)
          overflowCount = 0
          overflow = false
          if newIndex
            loop do # Search a valid next
              newIndex+=spinSelection
              newIndex=0 if spinSelection==spriteNames.size
              name = spriteNames[newIndex]
              break if name && @sprites[name] && !@sprites[name].is_a?(Plane) 
              # Solving infinite loops
              overflowCount+=1
              if overflowCount>9000
                overflow=true
                break
              end  
            end  
          else
            newIndex = spinSelection==1 ? 0 : -1
          end
          selectSprite(spriteNames[newIndex]) if !overflow
        end  
        
        if Input.repeatex?(0x57) # W
          axisY=-1
          move=true
        end  
        if Input.repeatex?(0x53) # S
          axisY=1
          move=true
        end 
        if Input.repeatex?(0x41) # A
          axisX=-1
          move=true
        end  
        if Input.repeatex?(0x44) # D
          axisX=1
          move=true
        end  
        
        @paused= !@paused if Input.triggerex?(0x45) # E # Pause
        
        if Input.triggerex?(0x52) # R # Toggle highlight
          selectedSprite = @sprites[@spriteSelectedName]
          @highlight=!@highlight
          highlightSelectedSprite(@highlight)
        end
        
        # T # Toggle sprite visibility
        @sprites[@spriteSelectedName].visible = !@sprites[@spriteSelectedName
            ].visible if Input.triggerex?(0x54) && @sprites[@spriteSelectedName]
        
        if move
          selectedSprite = @sprites[@spriteSelectedName]
          if selectedSprite && (axisX != 0 || axisY!=0)
            selectedSprite.x+= axisX*SPEED
            selectedSprite.y+= axisY*SPEED
            @spritesLog[@spriteSelectedName]=spriteData(@spriteSelectedName)
          end
        end
        
        if Input.triggerex?(0x51) # Q
          selectedText=spriteData(@spriteSelectedName)
          helpText=%{WSAD - Move Sprite
    FG - Switch between sprites
    Q - Info
    E - Pause
    R - Toggle highlight
    T - Toggle visible}
          logText = ""
          for log in @spritesLog.values
            logText+=log+"\r\n"
          end
          print selectedText+"\r\n"+helpText+"\r\n"+logText
          
          filename="ScenePositionerLog.txt"
          formatedDate = (Time.new+98765432).strftime("%Y-%m-%d %I:%M:%S %p")
          header = "##### #{formatedDate} #####"
          File.open(filename,"ab"){|f| 
            f.write(header+"\r\n"+selectedText+"\r\n-\r\n"+logText)
          }
        end  
      end
      
      def spriteIsOnCoordinate(sprite, x, y)
        return false if !(sprite.is_a?(Window) || sprite.bitmap)
        spriteWidth = 0
        spriteHeight = 0 
        if sprite.is_a?(Window)
          spriteWidth = sprite.width
          spriteHeight = sprite.height 
        else
          spriteWidth = sprite.bitmap.width
          spriteHeight = sprite.bitmap.height 
        end  
        spriteX = sprite.x - sprite.ox
        spriteY = sprite.y - sprite.oy
        inXAxis = spriteX <= x && x < spriteX+spriteWidth
        inYAxis = spriteY <= y && y < spriteY+spriteHeight
        return inXAxis && inYAxis
      end  
      
      def selectSprite(spriteName)
        highlightSelectedSprite(false)
        @spriteSelectedName = spriteName
        @border.setSpriteBelow(@sprites[spriteName])
        highlightSelectedSprite(true) if @highlight
      end  
          
      def highlightSelectedSprite(activate)
        if activate 
          spriteSelected = @sprites[@spriteSelectedName]
          return if !spriteSelected
          @lastTone = spriteSelected.tone.clone
          spriteSelected.tone = Tone.new(
              @lastTone.red+32,@lastTone.green,@lastTone.blue,@lastTone.gray)
        elsif @lastTone
          @sprites[@spriteSelectedName].tone = @lastTone
          @lastTone = nil
        end
        @border.visible = activate
      end  
      
      def spriteData(spriteName)
        sprite = @sprites[spriteName]
        ret=""
        ret="#{spriteName} x=#{sprite.x} y=#{sprite.y} z=#{sprite.z}" if sprite
        if @showOXOY && sprite
          ret+=" ox=#{sprite.ox} oy=#{sprite.oy}"
          ret+=" angle=#{sprite.angle}" if !sprite.is_a?(Window)
        end 
        return ret
      end  
    
      # Returns if this sprite have a bitmap or is a Windows.
      # Used for know if the sprite have valid width and height
      def hasSize(sprite) 
        return sprite.is_a?(Window) || sprite.bitmap
      end  
      
      USEOTHERMOUSESCRIPT = false
      
      if USEOTHERMOUSESCRIPT
        # If you use another moude script, just change the USEOTHERMOUSESCRIPT to
        # true and overload the two method below
        def mouseClicked?
          # must return true if mouse click. Otherside returns false
        end
        
        def mouseCoordinates
          # must return two length aray with mouse X and Y coordinates on screen
        end
      
      elsif defined?(USE_MOUSE) && USE_MOUSE # Have Crazyninjaguy Mouse Script
        def mouseClicked?
          return Mouse.click?(Mouse::Left_Click)
        end
        
        def mouseCoordinates
          return [Mouse.pos_x,Mouse.pos_y]
        end
      else
        def mouseClicked?
          return false
        end
      end
    end
    
    # If doesn't have triggerex? implement methods for reading keyboard inputs 
    if !defined?(Input.triggerex?)
      module Input
        class << self
          alias poccilUpdate update
        end
          
        # Original methods for reading other keyboard keys by 
        # Poccil slightly adjusted
        def self.pbSameThread(wnd)
          return false if wnd==0
          processid=[0].pack('l')
          getCurrentThreadId=Win32API.new('kernel32','GetCurrentThreadId', '%w()','l')
          getWindowThreadProcessId=Win32API.new('user32','GetWindowThreadProcessId', '%w(l p)','l')
          threadid=getCurrentThreadId.call
          wndthreadid=getWindowThreadProcessId.call(wnd,processid)
          return (wndthreadid==threadid)
        end
      
        # GetAsyncKeyState or GetKeyState will work here
        @GetKeyState=Win32API.new("user32", "GetAsyncKeyState", "i", "i")
        @GetForegroundWindow=Win32API.new("user32", "GetForegroundWindow", "", "i")
        # Returns whether a key is being pressed
      
        def self.getstate(key)
          return (@GetKeyState.call(key)&0x8000)>0
        end
      
        def self.updateKeyState(i)
          gfw=pbSameThread(@GetForegroundWindow.call())
          if !@stateUpdated[i]
            newstate=self.getstate(i) && gfw
            @triggerstate[i]=(newstate&&@keystate[i]==0)
            @releasestate[i]=(!newstate&&@keystate[i]>0)
            @keystate[i]=newstate ? @keystate[i]+1 : 0
            @stateUpdated[i]=true
          end
        end
      
        def self.update
          poccilUpdate
          if @keystate
            for i in 0...256
              # just noting that the state should be updated
              # instead of thunking to Win32 256 times
              @stateUpdated[i]=false
              if @keystate[i] > 0
                # If there is a repeat count, update anyway
                # (will normally apply only to a very few keys)
                updateKeyState(i)
              end
            end    
          else
            @stateUpdated=[]
            @keystate=[]
            @triggerstate=[]
            @releasestate=[]
            for i in 0...256
              @stateUpdated[i]=true
              @keystate[i]=self.getstate(i) ? 1 : 0
              @triggerstate[i]=false
              @releasestate[i]=false
            end
          end
        end
      
        def self.repeatex?(key)
          return false if !@keystate
          updateKeyState(key)
          return @keystate[key]==1 || (@keystate[key]>20 && (@keystate[key]&1)==0)
        end
      
        def self.releaseex?(key)
          return false if !@releasestate
          updateKeyState(key)
          return @releasestate[key]
        end
      
        def self.triggerex?(key)
          return false if !@triggerstate
          updateKeyState(key)
          return @triggerstate[key]
        end
      
        def self.repeatcount(key)
          return 0 if !@keystate
          updateKeyState(key)
          return @keystate[key]
        end
      
        def self.pressex?(key)
          return self.repeatcount(key)>0
        end
      end
    end
     

    Attachments

    • scenepositionerscreen.png
      scenepositionerscreen.png
      5.2 KB · Views: 154
    • scenepositionercoordinates.png
      scenepositionercoordinates.png
      6 KB · Views: 135
    Last edited:
    Back
    Top