Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Type (No-copy/paste) in a journal.

I will give a detail and described enough description that it is not overwelming but, a scripter could still make it from detail. This is basically a scene in which has a custom background image, which on a certain area of that image you are able to type/delete text onto but not copy and paste. So open up wordpad/notepad make the blank white sheet into a scroll paper like image and take out all of the options including copy+paste and also you have character limit. This way players instead of having a quest log in which the game makes for them they can type out small notes for themselves later, for quests, purchases or even write out how much gold they need to buy something.

Here is an example image layout of the scene: http://img508.imageshack.us/img508/522/notescriptrequestlayoutku3.th.png[/img]

Please Note: This is requested to be for RPG Maker XP, not VX.
 

poccil

Sponsor

I've finished making a first version of what you want.  The scene's name is Scene_Journal and goes to the map screen when the player presses ESC.  The scene currently uses "Graphics/Pictures/ScrollBackground.jpg" but can be changed easily, see the bottom of the script.
The text can be accessed with "$game_system.journalText", and its maximum size can be accessed with "$game_system.journalMaxSize".  Both values will be saved when the player saves the game.

The code follows.

Code:
module Input
  DOWN=2
  LEFT=4
  RIGHT=6
  UP=8
  A=11
  B=12
  C=13
  X=14
  Y=15
  Z=16
  L=17
  R=18
  SHIFT=21
  CTRL=22
  ALT=23
  F5=25
  F6=26
  F7=27
  F8=28
  F9=29
  # GetAsyncKeyState or GetKeyState will work here
  @GetKeyState=Win32API.new("user32", "GetAsyncKeyState", "i", "i")
  # Returns whether a key is being pressed
  def self.getstate(key)
    return (@GetKeyState.call(key)&0x8000)>0
  end
  def self.updateKeyState(i)
    if !@stateUpdated[i]
      newstate=self.getstate(i)
      @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
    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.buttonToKey(button)
   case button
    when Input::DOWN
     return [0x28] # Down
    when Input::LEFT
     return [0x25] # Left
    when Input::RIGHT
     return [0x27] # Right
    when Input::UP
     return [0x26] # Up
    when Input::A
     return [0x5A,0x10] # Z, Shift
    when Input::B
     return [0x58,0x1B] # X, ESC 
    when Input::C
     return [0x43,0x0d,0x20] # C, ENTER, Space
    when Input::X
     return [0x41] # A
    when Input::Y
     return [0x53] # S
    when Input::Z
     return [0x44] # D
    when Input::L
     return [0x51,0x21] # Q, Page Up
    when Input::R
     return [0x57,0x22] # W, Page Up
    when Input::SHIFT
     return [0x10] # Shift
    when Input::CTRL
     return [0x11] # Ctrl
    when Input::ALT
     return [0x12] # Alt
    when Input::F5
     return [0x74] # F5
    when Input::F6
     return [0x75] # F6
    when Input::F7
     return [0x76] # F7
    when Input::F8
     return [0x77] # F8
    when Input::F9
     return [0x78] # F9
    else
     return []
   end
  end
  def self.dir4
   button=0
   repeatcount=0
   if self.press?(Input::DOWN) && self.press?(Input::UP)
     return 0
   end
   if self.press?(Input::LEFT) && self.press?(Input::RIGHT)
     return 0
   end
   for b in [Input::DOWN,Input::LEFT,Input::RIGHT,Input::UP]
    rc=self.count(b)
    if rc>0
     if repeatcount==0 || rc<repeatcount
      button=b
      repeatcount=rc
     end
    end
   end
   return button
  end
  def self.dir8
   buttons=[]
   for b in [Input::DOWN,Input::LEFT,Input::RIGHT,Input::UP]
    rc=self.count(b)
    if rc>0
     buttons.push([b,rc])
    end
   end
   if buttons.length==0
    return 0
   elsif buttons.length==1
    return buttons[0][0]
   elsif buttons.length==2
    # since buttons sorted by button, no need to sort here
    if (buttons[0][0]==Input::DOWN && buttons[1][0]==Input::UP)
     return 0
    end
    if (buttons[0][0]==Input::LEFT && buttons[1][0]==Input::RIGHT)
     return 0
    end
   end
   buttons.sort!{|a,b| a[1]<=>b[1]}
   updown=0
   leftright=0
   for b in buttons
    if updown==0 && (b[0]==Input::UP || b[0]==Input::DOWN)
     updown=b[0]
    end
    if leftright==0 && (b[0]==Input::LEFT || b[0]==Input::RIGHT)
     leftright=b[0]
    end
   end
   if updown==Input::DOWN
    return 1 if leftright==Input::LEFT
    return 3 if leftright==Input::RIGHT
    return 2
   elsif updown==Input::UP
    return 7 if leftright==Input::LEFT
    return 9 if leftright==Input::RIGHT
    return 8
   else
    return 4 if leftright==Input::LEFT
    return 6 if leftright==Input::RIGHT
    return 0
   end
  end
  def self.count(button)
   for btn in self.buttonToKey(button)
     c=self.repeatcount(btn)
     return c if c>0
   end
   return 0
  end 
  def self.trigger?(button)
   return self.buttonToKey(button).any? {|item| self.triggerex?(item) }
  end
  def self.repeat?(button)
   return self.buttonToKey(button).any? {|item| self.repeatex?(item) }
  end
  def self.press?(button)
   return self.count(button)>0
  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

def getLineBrokenText(bitmap,value,width,dims)
  x=0
  y=0
  textheight=0
  ret=[]
  if dims
   dims[0]=0
   dims[1]=0
  end
  line=0
  position=0
  column=0
  return ret if !bitmap || bitmap.disposed? || width<=0
  textmsg=value.clone
  lines=0
  color=Font.default_color
  while ((c = textmsg.slice!(/\n|(\S*([ \r\t\f]?))/)) != nil)
   break if c==""
   length=c.scan(/./m).length
   ccheck=c
   if ccheck=="\n"
    ret.push(["",x,y,0,textheight,line,position,column,0])
    x=0
    y+=(textheight==0) ? bitmap.text_size("X").height : textheight
    line+=1
    textheight=0
    column=0
    position+=length
    next
   end
   textcols=[]
   words=[ccheck]
   for i in 0...words.length
    word=words[i]
    if word && word!=""
     textSize=bitmap.text_size(word)
     textwidth=textSize.width
     if x>0 && x+textwidth>=width-2
      # Zero-length word break
      ret.push(["",x,y,0,textheight,line,position,column,0])
      x=0
      column=0
      y+=(textheight==0) ? bitmap.text_size("X").height : textheight
      line+=1
      textheight=0
     end
     textheight=[textheight,textSize.height].max
     ret.push([word,x,y,textwidth,textheight,line,position,column,length])
     x+=textwidth
     dims[0]=x if dims && dims[0]<x
    end
    if textcols[i]
     color=textcols[i]
    end
   end
   position+=length
   column+=length
  end
  dims[1]=y+textheight if dims
  return ret
end

class CharacterEntryHelper
 attr_reader :text
 attr_reader :maxlength
 attr_reader :passwordChar 
 attr_accessor :cursor
 def text=(value)
  @text=value
  ensure
 end
 def textChars
  chars=text.scan(/./m)
  if @passwordChar!=""
   chars.length.times {|i|
    chars[i]=@passwordChar
   }
  end
  return chars
 end
 def initialize(text)
   @maxlength=-1
   @text=text
   @passwordChar=""
   @cursor=text.scan(/./m).length
   ensure
 end
 def passwordChar=(value)
  @passwordChar=value ? value : ""
 end
 def maxlength=(value)
   @maxlength=value
   ensure
 end
 def length
   return self.text.scan(/./m).length
 end
 def insert(ch)
   chars=self.text.scan(/./m)
   return false if @maxlength>=0 && chars.length>=@maxlength
   chars.insert(@cursor,ch)
   @text=""
   for ch in chars
    @text+=ch if ch
   end
   @cursor+=1
   return true
 end
 def delete
   chars=self.text.scan(/./m)
   return false if chars.length<=0 || @cursor<=0
   chars.delete_at(@cursor-1)
   @text=""
   for ch in chars
    @text+=ch if ch
   end
   @cursor-=1
   return true
 end
 private
 def ensure
   return if @maxlength<0
   chars=self.text.scan(/./m)
   if chars.length>@maxlength && @maxlength>=0
     chars=chars[0,@maxlength]
   end
   @text=""
   for ch in chars
    @text+=ch if ch
   end
 end
end
class Window_MultilineTextEntry < Window_Base
 def initialize(text,x,y,width,height)
   super(x,y,width,height)
   @baseColor=self.normal_color
   @shadowColor=Color.new(0,0,0,0)
   @helper=CharacterEntryHelper.new(text)
   @firstline=0
   @cursorLine=0
   @cursorColumn=0
   @frame=0
   refresh
 end
 attr_reader :baseColor
 attr_reader :shadowColor
 def baseColor=(value)
  @baseColor=value
  refresh
 end
 def shadowColor=(value)
  @shadowColor=value
  refresh
 end
 def text
  @helper.text
 end
 def maxlength
  @helper.maxlength
 end
 def text=(value)
  @helper.text=value
  @textchars=nil
  self.refresh
 end
 def maxlength=(value)
  @helper.maxlength=value 
  @textchars=nil
  self.refresh
 end
 def insert(ch)
  @helper.cursor=getPosFromLineAndColumn(
    @cursorLine,@cursorColumn)
  if @helper.insert(ch)
    @frame=0
    @textchars=nil
    moveCursor(0,1)
    self.refresh
    return true
  end
  return false
 end
 def delete
  @helper.cursor=getPosFromLineAndColumn(
    @cursorLine,@cursorColumn)
  if @helper.delete
    @frame=0
    moveCursor(0,-1) # use old textchars
    @textchars=nil
    self.refresh
    return true
  end
  return false
 end
 def getTextChars
  if !@textchars
   @textchars=getLineBrokenText(self.contents,
     @helper.text,self.contents.width,nil)
  end
  return @textchars
 end
 def getTotalLines
  textchars=getTextChars
  if textchars.length==0
   return 1
  else
   tchar=textchars[textchars.length-1]
   return tchar[5]+1
  end
 end
 def getLineY(line)
  textchars=getTextChars
  if textchars.length==0
   return 0
  else
   totallines=getTotalLines()
   line=0 if line<0
   line=totallines-1 if line>=totallines
   maximumY=0
   for i in 0...textchars.length
    thisline=textchars[i][5]
    y=textchars[i][2]
    return y if thisline==line
    maximumY=y if maximumY<y
   end
   return maximumY
  end
 end
 def getColumnsInLine(line)
  textchars=getTextChars
  if textchars.length==0
   return 0
  else
   totallines=getTotalLines()
   line=0 if line<0
   line=totallines-1 if line>=totallines
   endpos=0
   for i in 0...textchars.length
    thisline=textchars[i][5]
    thispos=textchars[i][6]
    thislength=textchars[i][8]
    if thisline==line
     endpos+=thislength
    end
   end
   return endpos
  end
 end
 def getPosFromLineAndColumn(line,column)
  textchars=getTextChars
  if textchars.length==0
   return 0
  else
   totallines=getTotalLines()
   line=0 if line<0
   line=totallines-1 if line>=totallines
   endpos=0
   for i in 0...textchars.length
    thisline=textchars[i][5]
    thispos=textchars[i][6]
    thiscolumn=textchars[i][7]
    thislength=textchars[i][8]
    if thisline==line
     endpos=thispos+thislength
#     echoln [endpos,thispos+(column-thiscolumn),textchars[i]]
     if column>=thiscolumn && column<=thiscolumn+thislength && thislength>0
      return thispos+(column-thiscolumn)
     end
    end
   end
   if endpos==0
#    echoln [totallines,line,column]
#    echoln textchars
   end
#   echoln "endpos=#{endpos}"
   return endpos
  end
 end
 def getLastVisibleLine
   textchars=getTextChars()
   textheight=[1,self.contents.text_size("X").height].max
   lastVisible=@firstline+((self.height-32)/textheight)-1
   return lastVisible
 end
 def updateCursorPos(doRefresh)
  # Calculate new cursor position
  @helper.cursor=getPosFromLineAndColumn(
    @cursorLine,@cursorColumn)
  if doRefresh
   @frame=0
   self.refresh
  end
  if @cursorLine<@firstline
   @firstline=@cursorLine
  end
  lastVisible=getLastVisibleLine()
  if @cursorLine>lastVisible
   @firstline+=(@cursorLine-lastVisible)
  end
 end
 def moveCursor(lineOffset, columnOffset)
  # Move column offset first, then lines (since column offset
  # can affect line offset)
#  echoln ["beforemoving",@cursorLine,@cursorColumn]
  totalColumns=getColumnsInLine(@cursorLine) # check current line
  totalLines=getTotalLines()
  oldCursorLine=@cursorLine
  oldCursorColumn=@cursorColumn
  @cursorColumn+=columnOffset
  if @cursorColumn<0 && @cursorLine>0
   # Will happen if cursor is moved left from the beginning
   # of a line
   @cursorLine-=1
   @cursorColumn=getColumnsInLine(@cursorLine)
  elsif @cursorColumn>totalColumns && @cursorLine<totalLines-1
   # Will happen if cursor is moved right from the end
   # of a line
   @cursorLine+=1
   @cursorColumn=0
   updateColumns=true
  end
  # Ensure column bounds
  totalColumns=getColumnsInLine(@cursorLine)
  @cursorColumn=totalColumns if @cursorColumn>totalColumns
  @cursorColumn=0 if @cursorColumn<0 # totalColumns can be 0
  # Move line offset
  @cursorLine+=lineOffset
  @cursorLine=0 if @cursorLine<0
  @cursorLine=totalLines-1 if @cursorLine>=totalLines
  # Ensure column bounds again
  totalColumns=getColumnsInLine(@cursorLine)
  @cursorColumn=totalColumns if @cursorColumn>totalColumns
  @cursorColumn=0 if @cursorColumn<0 # totalColumns can be 0
  updateCursorPos(
     oldCursorLine!=@cursorLine ||
     oldCursorColumn!=@cursorColumn
  )
#  echoln ["aftermoving",@cursorLine,@cursorColumn]
 end
 def update
   @frame+=1
   @frame%=20
   self.refresh if ((@frame%10)==0)
   # Moving cursor
   if Input.repeat?(Input::LEFT)
    moveCursor(0,-1)
    return
   elsif Input.repeat?(Input::UP)
    moveCursor(-1,0)
    return
   elsif Input.repeat?(Input::DOWN)
    moveCursor(1,0)
    return
   elsif Input.repeat?(Input::RIGHT)
    moveCursor(0,1)
    return
   elsif Input.pressex?(0x11) && Input.triggerex?(0x24) # Ctrl + Home
    # Move cursor to beginning
    @cursorLine=0
    @cursorColumn=0
    updateCursorPos(true)
    return
   elsif Input.pressex?(0x11) && Input.triggerex?(0x23) # Ctrl + End
    # Move cursor to end
    @cursorLine=getTotalLines()-1
    @cursorColumn=getColumnsInLine(@cursorLine)
    updateCursorPos(true)
    return
   elsif Input.repeatex?(13)
    self.insert("\n")
    return
   elsif Input.repeatex?(8) || Input.repeatex?(0x2E)
    # Backspace
    self.delete
    return
   end
   # Letter keys
   for i in 65..90
    if Input.repeatex?(i)
     shift=(Input.press?(Input::SHIFT)) ? 0x41 : 0x61
     insert((shift+(i-65)).chr)
     return
    end
   end
   # Number keys
   shifted=")!@\#$%^&*("
   unshifted="0123456789"
   for i in 48..57
    if Input.repeatex?(i)
     insert((Input.press?(Input::SHIFT)) ? shifted[i-48].chr : unshifted[i-48].chr)
     return
    end
   end
   keys=[
    [32," "," "],
    [106,"*","*"],
    [107,"+","+"],
    [109,"-","-"],
    [111,"/","/"],
    [186,";",":"],
    [187,"=","+"],
    [189,"-","_"],
    [191,"/","?"],
    [219,"[","{"],
    [190,".",">"],
    [188,",","<"],
    [220,"\\","|"],
    [190,".",""],
    [188,",",""],
    [221,"]","}"],
    [222,"'","\""]
   ]
   for i in keys
    if Input.repeatex?(i[0])
     insert((Input.press?(Input::SHIFT)) ? i[2] : i[1])
     return
    end
   end
 end
 def refresh
  if !self.contents || self.contents.disposed? ||
     self.contents.width!=self.width-32 ||
     self.contents.height!=self.height-32
   # Re-create bitmap if necessary
   self.contents.dispose if self.contents
   self.contents=Bitmap.new([1,self.width-32].max,[1,self.height-32].max)
   @textchars=nil
  end
   bitmap=self.contents
   bitmap.clear
   x=0
   y=0
   getTextChars
   x+=4
   width=self.width-32
   height=self.height-32
   cursorcolor=Color.new(0,0,0)
   textchars=getTextChars()
   scanlength=@helper.length
   startY=getLineY(@firstline)
   lastheight=32
   for i in 0...textchars.length
    thisline=textchars[i][5]
    thispos=textchars[i][6]
    thiscolumn=textchars[i][7]
    thislength=textchars[i][8]
    textY=textchars[i][2]-startY
    # Don't draw lines before the first or zero-length segments
    next if thisline<@firstline || thislength==0
    # Don't draw lines beyond the window's height
    break if textY >= height
    c=textchars[i][0]
    # Don't draw spaces
    next if c==" "
    textwidth=textchars[i][3]+4 # add 4 to prevent draw_text from stretching text
    textheight=textchars[i][4]
    lastheight=textheight
    # Draw text
#    bitmap.font.color=@shadowColor
#    pbDrawShadow(bitmap,textchars[i][1],textY, textwidth, textheight, c)
    bitmap.font.color=@baseColor
    bitmap.draw_text(textchars[i][1],textY, textwidth, textheight, c)
   end
   # Draw cursor
   if ((@frame/10)&1) == 0
    textheight=bitmap.text_size("X").height
    cursorY=(textheight*@cursorLine)-startY
    cursorX=0
    for i in 0...textchars.length
     thisline=textchars[i][5]
     thispos=textchars[i][6]
     thiscolumn=textchars[i][7]
     thislength=textchars[i][8]
     if thisline==@cursorLine &&
        @cursorColumn>=thiscolumn && @cursorColumn<=thiscolumn+thislength
      cursorY=textchars[i][2]-startY
      cursorX=textchars[i][1]
      textheight=textchars[i][4]
      posToCursor=@cursorColumn-thiscolumn
      if posToCursor>=0
       partialString=textchars[i][0].scan(/./m)[0,posToCursor].join("")
       cursorX+=bitmap.text_size(partialString).width
      end
      break
     end
    end
    cursorY+=4
    cursorHeight=[4,textheight-4,bitmap.text_size("X").height-4].max
    bitmap.fill_rect(cursorX,cursorY,2,cursorHeight,cursorcolor)
   end
 end
end

class Game_System
  attr_accessor :journalText
  attr_accessor :journalMaxSize
  def journalText
    @journalText="" if !@journalText
    return @journalText
  end
  def journalMaxSize
    @journalMaxSize=200 if !@journalMaxSize
    return @journalMaxSize
  end
end

class Scene_Journal
  def main
    sprite=Sprite.new
    ##########
    ##  Set name of background image here
    ##########
    sprite.bitmap=RPG::Cache.picture("ScrollBackground.jpg")
    window=Window_MultilineTextEntry.new("",32,32,640-64,480-64)
    window.maxlength=$game_system.journalMaxSize
    window.z=1
    window.visible=true
    window.text=$game_system.journalText
    ##########
    ##  Set text color here
    ##########
    window.baseColor=Color.new(40,20,0)
    window.opacity=0
    Graphics.transition(15)
    loop do
      Graphics.update
      Input.update
      window.update
      if Input.triggerex?(0x1B)
         $scene=Scene_Map.new
         $game_system.journalText=window.text
      end
      if $scene != self
        break
      end
    end
    Graphics.freeze
    sprite.dispose
    sprite.bitmap.dispose
    window.dispose
  end
end
 
Well, I already had an input module with the same name as Module Input so I tried changing this one to Module Input2, but I think I have done something wrong in this name change because I called this scene as an auto-run on my first map, it came up perfectly normal. But it wouldn't let me type with the letters I was hitting, or space. Could you please help me to find out, and fix what is wrong? Here is my edited version:
Code:
module Input2
  DOWN=2
  LEFT=4
  RIGHT=6
  UP=8
  A=11
  B=12
  C=13
  X=14
  Y=15
  Z=16
  L=17
  R=18
  SHIFT=21
  CTRL=22
  ALT=23
  F5=25
  F6=26
  F7=27
  F8=28
  F9=29
  # GetAsyncKeyState or GetKeyState will work here
  @GetKeyState=Win32API.new("user32", "GetAsyncKeyState", "i", "i")
  # Returns whether a key is being pressed
  def self.getstate(key)
    return (@GetKeyState.call(key)&0x8000)>0
  end
  def self.updateKeyState(i)
    if !@stateUpdated[i]
      newstate=self.getstate(i)
      @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
    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.buttonToKey(button)
   case button
    when Input::DOWN
     return [0x28] # Down
    when Input::LEFT
     return [0x25] # Left
    when Input::RIGHT
     return [0x27] # Right
    when Input::UP
     return [0x26] # Up
    when Input::A
     return [0x5A,0x10] # Z, Shift
    when Input::B
     return [0x58,0x1B] # X, ESC 
    when Input::C
     return [0x43,0x0d,0x20] # C, ENTER, Space
    when Input::X
     return [0x41] # A
    when Input::Y
     return [0x53] # S
    when Input::Z
     return [0x44] # D
    when Input::L
     return [0x51,0x21] # Q, Page Up
    when Input::R
     return [0x57,0x22] # W, Page Up
    when Input::SHIFT
     return [0x10] # Shift
    when Input::CTRL
     return [0x11] # Ctrl
    when Input::ALT
     return [0x12] # Alt
    when Input::F5
     return [0x74] # F5
    when Input::F6
     return [0x75] # F6
    when Input::F7
     return [0x76] # F7
    when Input::F8
     return [0x77] # F8
    when Input::F9
     return [0x78] # F9
    else
     return []
   end
  end
  def self.dir4
   button=0
   repeatcount=0
   if self.press?(Input::DOWN) && self.press?(Input::UP)
     return 0
   end
   if self.press?(Input::LEFT) && self.press?(Input::RIGHT)
     return 0
   end
   for b in [Input::DOWN,Input::LEFT,Input::RIGHT,Input::UP]
    rc=self.count(b)
    if rc>0
     if repeatcount==0 || rc<repeatcount
      button=b
      repeatcount=rc
     end
    end
   end
   return button
  end
  def self.dir8
   buttons=[]
   for b in [Input::DOWN,Input::LEFT,Input::RIGHT,Input::UP]
    rc=self.count(b)
    if rc>0
     buttons.push([b,rc])
    end
   end
   if buttons.length==0
    return 0
   elsif buttons.length==1
    return buttons[0][0]
   elsif buttons.length==2
    # since buttons sorted by button, no need to sort here
    if (buttons[0][0]==Input::DOWN && buttons[1][0]==Input::UP)
     return 0
    end
    if (buttons[0][0]==Input::LEFT && buttons[1][0]==Input::RIGHT)
     return 0
    end
   end
   buttons.sort!{|a,b| a[1]<=>b[1]}
   updown=0
   leftright=0
   for b in buttons
    if updown==0 && (b[0]==Input::UP || b[0]==Input::DOWN)
     updown=b[0]
    end
    if leftright==0 && (b[0]==Input::LEFT || b[0]==Input::RIGHT)
     leftright=b[0]
    end
   end
   if updown==Input::DOWN
    return 1 if leftright==Input::LEFT
    return 3 if leftright==Input::RIGHT
    return 2
   elsif updown==Input::UP
    return 7 if leftright==Input::LEFT
    return 9 if leftright==Input::RIGHT
    return 8
   else
    return 4 if leftright==Input::LEFT
    return 6 if leftright==Input::RIGHT
    return 0
   end
  end
  def self.count(button)
   for btn in self.buttonToKey(button)
     c=self.repeatcount(btn)
     return c if c>0
   end
   return 0
  end 
  def self.trigger?(button)
   return self.buttonToKey(button).any? {|item| self.triggerex?(item) }
  end
  def self.repeat?(button)
   return self.buttonToKey(button).any? {|item| self.repeatex?(item) }
  end
  def self.press?(button)
   return self.count(button)>0
  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

def getLineBrokenText(bitmap,value,width,dims)
  x=0
  y=0
  textheight=0
  ret=[]
  if dims
   dims[0]=0
   dims[1]=0
  end
  line=0
  position=0
  column=0
  return ret if !bitmap || bitmap.disposed? || width<=0
  textmsg=value.clone
  lines=0
  color=Font.default_color
  while ((c = textmsg.slice!(/\n|(\S*([ \r\t\f]?))/)) != nil)
   break if c==""
   length=c.scan(/./m).length
   ccheck=c
   if ccheck=="\n"
    ret.push(["",x,y,0,textheight,line,position,column,0])
    x=0
    y+=(textheight==0) ? bitmap.text_size("X").height : textheight
    line+=1
    textheight=0
    column=0
    position+=length
    next
   end
   textcols=[]
   words=[ccheck]
   for i in 0...words.length
    word=words[i]
    if word && word!=""
     textSize=bitmap.text_size(word)
     textwidth=textSize.width
     if x>0 && x+textwidth>=width-2
      # Zero-length word break
      ret.push(["",x,y,0,textheight,line,position,column,0])
      x=0
      column=0
      y+=(textheight==0) ? bitmap.text_size("X").height : textheight
      line+=1
      textheight=0
     end
     textheight=[textheight,textSize.height].max
     ret.push([word,x,y,textwidth,textheight,line,position,column,length])
     x+=textwidth
     dims[0]=x if dims && dims[0]<x
    end
    if textcols[i]
     color=textcols[i]
    end
   end
   position+=length
   column+=length
  end
  dims[1]=y+textheight if dims
  return ret
end

class CharacterEntryHelper
 attr_reader :text
 attr_reader :maxlength
 attr_reader :passwordChar 
 attr_accessor :cursor
 def text=(value)
  @text=value
  ensure
 end
 def textChars
  chars=text.scan(/./m)
  if @passwordChar!=""
   chars.length.times {|i|
    chars[i]=@passwordChar
   }
  end
  return chars
 end
 def initialize(text)
   @maxlength=-1
   @text=text
   @passwordChar=""
   @cursor=text.scan(/./m).length
   ensure
 end
 def passwordChar=(value)
  @passwordChar=value ? value : ""
 end
 def maxlength=(value)
   @maxlength=value
   ensure
 end
 def length
   return self.text.scan(/./m).length
 end
 def insert(ch)
   chars=self.text.scan(/./m)
   return false if @maxlength>=0 && chars.length>=@maxlength
   chars.insert(@cursor,ch)
   @text=""
   for ch in chars
    @text+=ch if ch
   end
   @cursor+=1
   return true
 end
 def delete
   chars=self.text.scan(/./m)
   return false if chars.length<=0 || @cursor<=0
   chars.delete_at(@cursor-1)
   @text=""
   for ch in chars
    @text+=ch if ch
   end
   @cursor-=1
   return true
 end
 private
 def ensure
   return if @maxlength<0
   chars=self.text.scan(/./m)
   if chars.length>@maxlength && @maxlength>=0
     chars=chars[0,@maxlength]
   end
   @text=""
   for ch in chars
    @text+=ch if ch
   end
 end
end
class Window_MultilineTextEntry < Window_Base
 def initialize(text,x,y,width,height)
   super(x,y,width,height)
   @baseColor=self.normal_color
   @shadowColor=Color.new(0,0,0,0)
   @helper=CharacterEntryHelper.new(text)
   @firstline=0
   @cursorLine=0
   @cursorColumn=0
   @frame=0
   refresh
 end
 attr_reader :baseColor
 attr_reader :shadowColor
 def baseColor=(value)
  @baseColor=value
  refresh
 end
 def shadowColor=(value)
  @shadowColor=value
  refresh
 end
 def text
  @helper.text
 end
 def maxlength
  @helper.maxlength
 end
 def text=(value)
  @helper.text=value
  @textchars=nil
  self.refresh
 end
 def maxlength=(value)
  @helper.maxlength=value 
  @textchars=nil
  self.refresh
 end
 def insert(ch)
  @helper.cursor=getPosFromLineAndColumn(
    @cursorLine,@cursorColumn)
  if @helper.insert(ch)
    @frame=0
    @textchars=nil
    moveCursor(0,1)
    self.refresh
    return true
  end
  return false
 end
 def delete
  @helper.cursor=getPosFromLineAndColumn(
    @cursorLine,@cursorColumn)
  if @helper.delete
    @frame=0
    moveCursor(0,-1) # use old textchars
    @textchars=nil
    self.refresh
    return true
  end
  return false
 end
 def getTextChars
  if !@textchars
   @textchars=getLineBrokenText(self.contents,
     @helper.text,self.contents.width,nil)
  end
  return @textchars
 end
 def getTotalLines
  textchars=getTextChars
  if textchars.length==0
   return 1
  else
   tchar=textchars[textchars.length-1]
   return tchar[5]+1
  end
 end
 def getLineY(line)
  textchars=getTextChars
  if textchars.length==0
   return 0
  else
   totallines=getTotalLines()
   line=0 if line<0
   line=totallines-1 if line>=totallines
   maximumY=0
   for i in 0...textchars.length
    thisline=textchars[i][5]
    y=textchars[i][2]
    return y if thisline==line
    maximumY=y if maximumY<y
   end
   return maximumY
  end
 end
 def getColumnsInLine(line)
  textchars=getTextChars
  if textchars.length==0
   return 0
  else
   totallines=getTotalLines()
   line=0 if line<0
   line=totallines-1 if line>=totallines
   endpos=0
   for i in 0...textchars.length
    thisline=textchars[i][5]
    thispos=textchars[i][6]
    thislength=textchars[i][8]
    if thisline==line
     endpos+=thislength
    end
   end
   return endpos
  end
 end
 def getPosFromLineAndColumn(line,column)
  textchars=getTextChars
  if textchars.length==0
   return 0
  else
   totallines=getTotalLines()
   line=0 if line<0
   line=totallines-1 if line>=totallines
   endpos=0
   for i in 0...textchars.length
    thisline=textchars[i][5]
    thispos=textchars[i][6]
    thiscolumn=textchars[i][7]
    thislength=textchars[i][8]
    if thisline==line
     endpos=thispos+thislength
#     echoln [endpos,thispos+(column-thiscolumn),textchars[i]]
     if column>=thiscolumn && column<=thiscolumn+thislength && thislength>0
      return thispos+(column-thiscolumn)
     end
    end
   end
   if endpos==0
#    echoln [totallines,line,column]
#    echoln textchars
   end
#   echoln "endpos=#{endpos}"
   return endpos
  end
 end
 def getLastVisibleLine
   textchars=getTextChars()
   textheight=[1,self.contents.text_size("X").height].max
   lastVisible=@firstline+((self.height-32)/textheight)-1
   return lastVisible
 end
 def updateCursorPos(doRefresh)
  # Calculate new cursor position
  @helper.cursor=getPosFromLineAndColumn(
    @cursorLine,@cursorColumn)
  if doRefresh
   @frame=0
   self.refresh
  end
  if @cursorLine<@firstline
   @firstline=@cursorLine
  end
  lastVisible=getLastVisibleLine()
  if @cursorLine>lastVisible
   @firstline+=(@cursorLine-lastVisible)
  end
 end
 def moveCursor(lineOffset, columnOffset)
  # Move column offset first, then lines (since column offset
  # can affect line offset)
#  echoln ["beforemoving",@cursorLine,@cursorColumn]
  totalColumns=getColumnsInLine(@cursorLine) # check current line
  totalLines=getTotalLines()
  oldCursorLine=@cursorLine
  oldCursorColumn=@cursorColumn
  @cursorColumn+=columnOffset
  if @cursorColumn<0 && @cursorLine>0
   # Will happen if cursor is moved left from the beginning
   # of a line
   @cursorLine-=1
   @cursorColumn=getColumnsInLine(@cursorLine)
  elsif @cursorColumn>totalColumns && @cursorLine<totalLines-1
   # Will happen if cursor is moved right from the end
   # of a line
   @cursorLine+=1
   @cursorColumn=0
   updateColumns=true
  end
  # Ensure column bounds
  totalColumns=getColumnsInLine(@cursorLine)
  @cursorColumn=totalColumns if @cursorColumn>totalColumns
  @cursorColumn=0 if @cursorColumn<0 # totalColumns can be 0
  # Move line offset
  @cursorLine+=lineOffset
  @cursorLine=0 if @cursorLine<0
  @cursorLine=totalLines-1 if @cursorLine>=totalLines
  # Ensure column bounds again
  totalColumns=getColumnsInLine(@cursorLine)
  @cursorColumn=totalColumns if @cursorColumn>totalColumns
  @cursorColumn=0 if @cursorColumn<0 # totalColumns can be 0
  updateCursorPos(
     oldCursorLine!=@cursorLine ||
     oldCursorColumn!=@cursorColumn
  )
#  echoln ["aftermoving",@cursorLine,@cursorColumn]
 end
 def update
   @frame+=1
   @frame%=20
   self.refresh if ((@frame%10)==0)
   # Moving cursor
   if Input.repeat?(Input::LEFT)
    moveCursor(0,-1)
    return
   elsif Input.repeat?(Input::UP)
    moveCursor(-1,0)
    return
   elsif Input.repeat?(Input::DOWN)
    moveCursor(1,0)
    return
   elsif Input.repeat?(Input::RIGHT)
    moveCursor(0,1)
    return
   elsif Input2.pressex?(0x11) && Input.triggerex?(0x24) # Ctrl + Home
    # Move cursor to beginning
    @cursorLine=0
    @cursorColumn=0
    updateCursorPos(true)
    return
   elsif Input2.pressex?(0x11) && Input.triggerex?(0x23) # Ctrl + End
    # Move cursor to end
    @cursorLine=getTotalLines()-1
    @cursorColumn=getColumnsInLine(@cursorLine)
    updateCursorPos(true)
    return
   elsif Input2.repeatex?(13)
    self.insert("\n")
    return
   elsif Input2.repeatex?(8) || Input2.repeatex?(0x2E)
    # Backspace
    self.delete
    return
   end
   # Letter keys
   for i in 65..90
    if Input2.repeatex?(i)
     shift=(Input.press?(Input::SHIFT)) ? 0x41 : 0x61
     insert((shift+(i-65)).chr)
     return
    end
   end
   # Number keys
   shifted=")!@\#$%^&*("
   unshifted="0123456789"
   for i in 48..57
    if Input2.repeatex?(i)
     insert((Input.press?(Input::SHIFT)) ? shifted[i-48].chr : unshifted[i-48].chr)
     return
    end
   end
   keys=[
    [32," "," "],
    [106,"*","*"],
    [107,"+","+"],
    [109,"-","-"],
    [111,"/","/"],
    [186,";",":"],
    [187,"=","+"],
    [189,"-","_"],
    [191,"/","?"],
    [219,"[","{"],
    [190,".",">"],
    [188,",","<"],
    [220,"\\","|"],
    [190,".",""],
    [188,",",""],
    [221,"]","}"],
    [222,"'","\""]
   ]
   for i in keys
    if Input2.repeatex?(i[0])
     insert((Input.press?(Input::SHIFT)) ? i[2] : i[1])
     return
    end
   end
 end
 def refresh
  if !self.contents || self.contents.disposed? ||
     self.contents.width!=self.width-32 ||
     self.contents.height!=self.height-32
   # Re-create bitmap if necessary
   self.contents.dispose if self.contents
   self.contents=Bitmap.new([1,self.width-32].max,[1,self.height-32].max)
   @textchars=nil
  end
   bitmap=self.contents
   bitmap.clear
   x=0
   y=0
   getTextChars
   x+=4
   width=self.width-32
   height=self.height-32
   cursorcolor=Color.new(0,0,0)
   textchars=getTextChars()
   scanlength=@helper.length
   startY=getLineY(@firstline)
   lastheight=32
   for i in 0...textchars.length
    thisline=textchars[i][5]
    thispos=textchars[i][6]
    thiscolumn=textchars[i][7]
    thislength=textchars[i][8]
    textY=textchars[i][2]-startY
    # Don't draw lines before the first or zero-length segments
    next if thisline<@firstline || thislength==0
    # Don't draw lines beyond the window's height
    break if textY >= height
    c=textchars[i][0]
    # Don't draw spaces
    next if c==" "
    textwidth=textchars[i][3]+4 # add 4 to prevent draw_text from stretching text
    textheight=textchars[i][4]
    lastheight=textheight
    # Draw text
#    bitmap.font.color=@shadowColor
#    pbDrawShadow(bitmap,textchars[i][1],textY, textwidth, textheight, c)
    bitmap.font.color=@baseColor
    bitmap.draw_text(textchars[i][1],textY, textwidth, textheight, c)
   end
   # Draw cursor
   if ((@frame/10)&1) == 0
    textheight=bitmap.text_size("X").height
    cursorY=(textheight*@cursorLine)-startY
    cursorX=0
    for i in 0...textchars.length
     thisline=textchars[i][5]
     thispos=textchars[i][6]
     thiscolumn=textchars[i][7]
     thislength=textchars[i][8]
     if thisline==@cursorLine &&
        @cursorColumn>=thiscolumn && @cursorColumn<=thiscolumn+thislength
      cursorY=textchars[i][2]-startY
      cursorX=textchars[i][1]
      textheight=textchars[i][4]
      posToCursor=@cursorColumn-thiscolumn
      if posToCursor>=0
       partialString=textchars[i][0].scan(/./m)[0,posToCursor].join("")
       cursorX+=bitmap.text_size(partialString).width
      end
      break
     end
    end
    cursorY+=4
    cursorHeight=[4,textheight-4,bitmap.text_size("X").height-4].max
    bitmap.fill_rect(cursorX,cursorY,2,cursorHeight,cursorcolor)
   end
 end
end

class Game_System
  attr_accessor :journalText
  attr_accessor :journalMaxSize
  def journalText
    @journalText="" if !@journalText
    return @journalText
  end
  def journalMaxSize
    @journalMaxSize=200 if !@journalMaxSize
    return @journalMaxSize
  end
end

class Scene_Journal
  def main
    sprite=Sprite.new
    ##########
    ##  Set name of background image here
    ##########
    sprite.bitmap=RPG::Cache.picture("ScrollBackground.png")
    window=Window_MultilineTextEntry.new("",32,32,640-64,480-64)
    window.maxlength=$game_system.journalMaxSize
    window.z=1
    window.visible=true
    window.text=$game_system.journalText
    ##########
    ##  Set text color here
    ##########
    window.baseColor=Color.new(40,20,0)
    window.opacity=0
    Graphics.transition(15)
    loop do
      Graphics.update
      Input.update
      window.update
      if Input2.triggerex?(0x1B)
         $scene=Scene_Map.new
         $game_system.journalText=window.text
      end
      if $scene != self
        break
      end
    end
    Graphics.freeze
    sprite.dispose
    sprite.bitmap.dispose
    window.dispose
  end
end
 

poccil

Sponsor

You must use the module Input which is given on the script.  It is incorrect to rename the "Input" module given there.

You could replace all instances of "Input" in the script with "Input2", and perhaps elsewhere in the script, but this can be messier than it's worth.

This was rather unexpected, as you did not tell us about a pre-existing "Input" module and I tested the script on a new project.
 
Well, I changed the other input module's instances of Input to Input2, but I still cannot type with this script. The script, is the exact way you left it but as a .png image, instead of .jpg, and it is above my custom scripts, to stop it from overwriting my battle system's custom movement, Enter, and ESC key changes, in all of my game. I do not know what is wrong, could you please help me stop this problem?
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top