From c5b1e08383761a492fa1a66bfd3867efc5a1aaab Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Mon, 28 Sep 2020 21:07:54 +0100 Subject: [PATCH] Tidying and rearranging --- Data/Scripts/001_Settings.rb | 2 +- Data/Scripts/001_Technical/004_Win32API.rb | 2 +- .../006_Game processing/003_Event_Handlers.rb | 4 +- ...3_SpriteWindow.rb => 002_MessageConfig.rb} | 0 .../{002_Window.rb => 003_Window.rb} | 0 .../004_SpriteWindow.rb | 992 +++++++++++++++ .../005_SpriteWindow_sprites.rb | 1084 ----------------- ...indow_text.rb => 005_SpriteWindow_text.rb} | 995 --------------- .../006_SpriteWindow_pictures.rb | 121 ++ .../007_SpriteWrapper.rb | 359 ++++++ .../008_AnimatedBitmap.rb | 363 ++++++ .../009_Objects and windows/009_Planes.rb | 232 ++++ .../{006_DrawText.rb => 010_DrawText.rb} | 0 .../{007_Messages.rb => 011_Messages.rb} | 0 .../{008_TextEntry.rb => 012_TextEntry.rb} | 0 .../{009_PictureEx.rb => 013_PictureEx.rb} | 0 ..._Interpolators.rb => 014_Interpolators.rb} | 0 ..._PBTypes_Extra.rb => 004_PBTypes_Extra.rb} | 0 ...08_PBExperience.rb => 005_PBExperience.rb} | 0 .../{009_PBStats.rb => 006_PBStats.rb} | 2 + .../{004_PBStatuses.rb => 007_PBStatuses.rb} | 0 .../{006_PBNatures.rb => 008_PBNatures.rb} | 0 ..._PBGenderRates.rb => 009_PBGenderRates.rb} | 0 Data/Scripts/012_Battle/004_PBTargets.rb | 8 +- .../Scripts/013_Overworld/002_PField_Field.rb | 818 ++++++------- .../013_Overworld/003_PField_Visuals.rb | 449 +++---- .../009_PField_RoamingPokemon.rb | 2 +- .../015_Items/002_PItem_ItemEffects.rb | 6 +- Data/Scripts/017_UI/009_PScreen_RegionMap.rb | 8 +- .../005_PSystem_Utilities.rb | 2 +- Data/Scripts/021_Debug/002_Debug_Actions.rb | 13 +- Data/Scripts/021_Debug/005_Editor_SaveData.rb | 2 +- .../012_Editor_BattleAnimationEditor.rb | 4 +- Data/Scripts/999_Main/999_Main.rb | 18 +- 34 files changed, 2742 insertions(+), 2744 deletions(-) rename Data/Scripts/009_Objects and windows/{003_SpriteWindow.rb => 002_MessageConfig.rb} (100%) rename Data/Scripts/009_Objects and windows/{002_Window.rb => 003_Window.rb} (100%) create mode 100644 Data/Scripts/009_Objects and windows/004_SpriteWindow.rb delete mode 100644 Data/Scripts/009_Objects and windows/005_SpriteWindow_sprites.rb rename Data/Scripts/009_Objects and windows/{004_SpriteWindow_text.rb => 005_SpriteWindow_text.rb} (55%) create mode 100644 Data/Scripts/009_Objects and windows/006_SpriteWindow_pictures.rb create mode 100644 Data/Scripts/009_Objects and windows/007_SpriteWrapper.rb create mode 100644 Data/Scripts/009_Objects and windows/008_AnimatedBitmap.rb create mode 100644 Data/Scripts/009_Objects and windows/009_Planes.rb rename Data/Scripts/009_Objects and windows/{006_DrawText.rb => 010_DrawText.rb} (100%) rename Data/Scripts/009_Objects and windows/{007_Messages.rb => 011_Messages.rb} (100%) rename Data/Scripts/009_Objects and windows/{008_TextEntry.rb => 012_TextEntry.rb} (100%) rename Data/Scripts/009_Objects and windows/{009_PictureEx.rb => 013_PictureEx.rb} (100%) rename Data/Scripts/009_Objects and windows/{010_Interpolators.rb => 014_Interpolators.rb} (100%) rename Data/Scripts/011_Data/{005_PBTypes_Extra.rb => 004_PBTypes_Extra.rb} (100%) rename Data/Scripts/011_Data/{008_PBExperience.rb => 005_PBExperience.rb} (100%) rename Data/Scripts/011_Data/{009_PBStats.rb => 006_PBStats.rb} (99%) rename Data/Scripts/011_Data/{004_PBStatuses.rb => 007_PBStatuses.rb} (100%) rename Data/Scripts/011_Data/{006_PBNatures.rb => 008_PBNatures.rb} (100%) rename Data/Scripts/011_Data/{007_PBGenderRates.rb => 009_PBGenderRates.rb} (100%) diff --git a/Data/Scripts/001_Settings.rb b/Data/Scripts/001_Settings.rb index fe813737a..ddb373467 100644 --- a/Data/Scripts/001_Settings.rb +++ b/Data/Scripts/001_Settings.rb @@ -1,6 +1,6 @@ #==============================================================================# # Pokémon Essentials # -# Version 18 # +# Version 18.1 # #==============================================================================# #=============================================================================== diff --git a/Data/Scripts/001_Technical/004_Win32API.rb b/Data/Scripts/001_Technical/004_Win32API.rb index 821ed8dba..6f6bd8b66 100644 --- a/Data/Scripts/001_Technical/004_Win32API.rb +++ b/Data/Scripts/001_Technical/004_Win32API.rb @@ -100,5 +100,5 @@ end # Well done for finding this place. # DO NOT EDIT THESE -ESSENTIALS_VERSION = "18.dev" +ESSENTIALS_VERSION = "18.1" ERROR_TEXT = "" diff --git a/Data/Scripts/006_Game processing/003_Event_Handlers.rb b/Data/Scripts/006_Game processing/003_Event_Handlers.rb index 3822b9451..0c098655b 100644 --- a/Data/Scripts/006_Game processing/003_Event_Handlers.rb +++ b/Data/Scripts/006_Game processing/003_Event_Handlers.rb @@ -39,8 +39,8 @@ class Event # The first argument is the sender of the event, the second argument contains # the event's parameters. If three or more arguments are given, this method # supports the following callbacks: - # proc{ |sender,params| } where params is an array of the other parameters, and - # proc{ |sender,arg0,arg1,...| } + # proc { |sender,params| } where params is an array of the other parameters, and + # proc { |sender,arg0,arg1,...| } def trigger(*arg) arglist = arg[1,arg.length] for callback in @callbacks diff --git a/Data/Scripts/009_Objects and windows/003_SpriteWindow.rb b/Data/Scripts/009_Objects and windows/002_MessageConfig.rb similarity index 100% rename from Data/Scripts/009_Objects and windows/003_SpriteWindow.rb rename to Data/Scripts/009_Objects and windows/002_MessageConfig.rb diff --git a/Data/Scripts/009_Objects and windows/002_Window.rb b/Data/Scripts/009_Objects and windows/003_Window.rb similarity index 100% rename from Data/Scripts/009_Objects and windows/002_Window.rb rename to Data/Scripts/009_Objects and windows/003_Window.rb diff --git a/Data/Scripts/009_Objects and windows/004_SpriteWindow.rb b/Data/Scripts/009_Objects and windows/004_SpriteWindow.rb new file mode 100644 index 000000000..e4b2bae4a --- /dev/null +++ b/Data/Scripts/009_Objects and windows/004_SpriteWindow.rb @@ -0,0 +1,992 @@ +#=============================================================================== +# +#=============================================================================== +class SpriteWindowCursorRect < Rect + def initialize(window) + @window=window + @x=0 + @y=0 + @width=0 + @height=0 + end + + attr_reader :x,:y,:width,:height + + def empty + needupdate=@x!=0 || @y!=0 || @width!=0 || @height!=0 + if needupdate + @x=0 + @y=0 + @width=0 + @height=0 + @window.width=@window.width + end + end + + def isEmpty? + return @x==0 && @y==0 && @width==0 && @height==0 + end + + def set(x,y,width,height) + needupdate=@x!=x || @y!=y || @width!=width || @height!=height + if needupdate + @x=x + @y=y + @width=width + @height=height + @window.width=@window.width + end + end + + def height=(value) + @height=value; @window.width=@window.width + end + + def width=(value) + @width=value; @window.width=@window.width + end + + def x=(value) + @x=value; @window.width=@window.width + end + + def y=(value) + @y=value; @window.width=@window.width + end +end + + + +#=============================================================================== +# SpriteWindow is a class based on Window which emulates Window's functionality. +# This class is necessary in order to change the viewport of windows (with +# viewport=) and to make windows fade in and out (with tone=). +#=============================================================================== +class SpriteWindow < Window + attr_reader :tone + attr_reader :color + attr_reader :viewport + attr_reader :contents + attr_reader :ox + attr_reader :oy + attr_reader :x + attr_reader :y + attr_reader :z + attr_reader :zoom_x + attr_reader :zoom_y + attr_reader :offset_x + attr_reader :offset_y + attr_reader :width + attr_reader :active + attr_reader :pause + attr_reader :height + attr_reader :opacity + attr_reader :back_opacity + attr_reader :contents_opacity + attr_reader :visible + attr_reader :cursor_rect + attr_reader :contents_blend_type + attr_reader :blend_type + attr_reader :openness + + def windowskin + @_windowskin + end + + # Flags used to preserve compatibility + # with RGSS/RGSS2's version of Window + module CompatBits + CorrectZ = 1 + ExpandBack = 2 + ShowScrollArrows = 4 + StretchSides = 8 + ShowPause = 16 + ShowCursor = 32 + end + + attr_reader :compat + + def compat=(value) + @compat=value + privRefresh(true) + end + + def initialize(viewport=nil) + @sprites={} + @spritekeys=[ + "back", + "corner0","side0","scroll0", + "corner1","side1","scroll1", + "corner2","side2","scroll2", + "corner3","side3","scroll3", + "cursor","contents","pause" + ] + @viewport=viewport + @sidebitmaps=[nil,nil,nil,nil] + @cursorbitmap=nil + @bgbitmap=nil + for i in @spritekeys + @sprites[i]=Sprite.new(@viewport) + end + @disposed=false + @tone=Tone.new(0,0,0) + @color=Color.new(0,0,0,0) + @blankcontents=Bitmap.new(1,1) # RGSS2 requires this + @contents=@blankcontents + @_windowskin=nil + @rpgvx=false + @compat=CompatBits::ExpandBack|CompatBits::StretchSides + @x=0 + @y=0 + @width=0 + @height=0 + @offset_x=0 + @offset_y=0 + @zoom_x=1.0 + @zoom_y=1.0 + @ox=0 + @oy=0 + @z=0 + @stretch=true + @visible=true + @active=true + @openness=255 + @opacity=255 + @back_opacity=255 + @blend_type=0 + @contents_blend_type=0 + @contents_opacity=255 + @cursor_rect=SpriteWindowCursorRect.new(self) + @cursorblink=0 + @cursoropacity=255 + @pause=false + @pauseframe=0 + @flash=0 + @pauseopacity=0 + @skinformat=0 + @skinrect=Rect.new(0,0,0,0) + @trim=[16,16,16,16] + privRefresh(true) + end + + def dispose + if !self.disposed? + for i in @sprites + i[1].dispose if i[1] + @sprites[i[0]]=nil + end + for i in 0...@sidebitmaps.length + @sidebitmaps[i].dispose if @sidebitmaps[i] + @sidebitmaps[i]=nil + end + @blankcontents.dispose + @cursorbitmap.dispose if @cursorbitmap + @backbitmap.dispose if @backbitmap + @sprites.clear + @sidebitmaps.clear + @_windowskin=nil + @disposed=true + end + end + + def stretch=(value) + @stretch=value + privRefresh(true) + end + + def visible=(value) + @visible=value + privRefresh + end + + def viewport=(value) + @viewport=value + for i in @spritekeys + @sprites[i].dispose if @sprites[i] + end + for i in @spritekeys + if @sprites[i].is_a?(Sprite) + @sprites[i]=Sprite.new(@viewport) + else + @sprites[i]=nil + end + end + privRefresh(true) + end + + def z=(value) + @z=value + privRefresh + end + + def disposed? + return @disposed + end + + def contents=(value) + if @contents!=value + @contents=value + privRefresh if @visible + end + end + + def ox=(value) + if @ox!=value + @ox=value + privRefresh if @visible + end + end + + def oy=(value) + if @oy!=value + @oy=value + privRefresh if @visible + end + end + + def active=(value) + @active=value + privRefresh(true) + end + + def cursor_rect=(value) + if !value + @cursor_rect.empty + else + @cursor_rect.set(value.x,value.y,value.width,value.height) + end + end + + def openness=(value) + @openness=value + @openness=0 if @openness<0 + @openness=255 if @openness>255 + privRefresh + end + + def width=(value) + @width=value + privRefresh(true) + end + + def height=(value) + @height=value + privRefresh(true) + end + + def pause=(value) + @pause=value + @pauseopacity=0 if !value + privRefresh if @visible + end + + def x=(value) + @x=value + privRefresh if @visible + end + + def y=(value) + @y=value + privRefresh if @visible + end + + def zoom_x=(value) + @zoom_x=value + privRefresh if @visible + end + + def zoom_y=(value) + @zoom_y=value + privRefresh if @visible + end + + def offset_x=(value) + @x=value + privRefresh if @visible + end + + def offset_y=(value) + @y=value + privRefresh if @visible + end + + def opacity=(value) + @opacity=value + @opacity=0 if @opacity<0 + @opacity=255 if @opacity>255 + privRefresh if @visible + end + + def back_opacity=(value) + @back_opacity=value + @back_opacity=0 if @back_opacity<0 + @back_opacity=255 if @back_opacity>255 + privRefresh if @visible + end + + def contents_opacity=(value) + @contents_opacity=value + @contents_opacity=0 if @contents_opacity<0 + @contents_opacity=255 if @contents_opacity>255 + privRefresh if @visible + end + + def tone=(value) + @tone=value + privRefresh if @visible + end + + def color=(value) + @color=value + privRefresh if @visible + end + + def blend_type=(value) + @blend_type=value + privRefresh if @visible + end + + def flash(color,duration) + return if disposed? + @flash=duration+1 + for i in @sprites + i[1].flash(color,duration) + end + end + + def update + return if disposed? + mustchange=false + if @active + if @cursorblink==0 + @cursoropacity-=8 + @cursorblink=1 if @cursoropacity<=128 + else + @cursoropacity+=8 + @cursorblink=0 if @cursoropacity>=255 + end + privRefreshCursor + else + @cursoropacity=128 + privRefreshCursor + end + if @pause + oldpauseframe=@pauseframe + oldpauseopacity=@pauseopacity + @pauseframe=(Graphics.frame_count / 8) % 4 + @pauseopacity=[@pauseopacity+64,255].min + mustchange=@pauseframe!=oldpauseframe || @pauseopacity!=oldpauseopacity + end + privRefresh if mustchange + if @flash>0 + for i in @sprites.values + i.update + end + @flash-=1 + end + end + + ############# + attr_reader :skinformat + attr_reader :skinrect + + def loadSkinFile(_file) + if (self.windowskin.width==80 || self.windowskin.width==96) && + self.windowskin.height==48 + # Body = X, Y, width, height of body rectangle within windowskin + @skinrect.set(32,16,16,16) + # Trim = X, Y, width, height of trim rectangle within windowskin + @trim=[32,16,16,16] + elsif self.windowskin.width==80 && self.windowskin.height==80 + @skinrect.set(32,32,16,16) + @trim=[32,16,16,48] + end + end + + def windowskin=(value) + oldSkinWidth=(@_windowskin && !@_windowskin.disposed?) ? @_windowskin.width : -1 + oldSkinHeight=(@_windowskin && !@_windowskin.disposed?) ? @_windowskin.height : -1 + @_windowskin=value + if @skinformat==1 + @rpgvx=false + if @_windowskin && !@_windowskin.disposed? + if @_windowskin.width!=oldSkinWidth || @_windowskin.height!=oldSkinHeight + # Update skinrect and trim if windowskin's dimensions have changed + @skinrect.set((@_windowskin.width-16)/2,(@_windowskin.height-16)/2,16,16) + @trim=[@skinrect.x,@skinrect.y,@skinrect.x,@skinrect.y] + end + else + @skinrect.set(16,16,16,16) + @trim=[16,16,16,16] + end + else + if value && value.is_a?(Bitmap) && !value.disposed? && value.width==128 + @rpgvx=true + else + @rpgvx=false + end + @trim=[16,16,16,16] + end + privRefresh(true) + end + + def skinrect=(value) + @skinrect=value + privRefresh + end + + def skinformat=(value) + if @skinformat!=value + @skinformat=value + privRefresh(true) + end + end + + def borderX + return 32 if !@trim || skinformat==0 + if @_windowskin && !@_windowskin.disposed? + return @trim[0]+(@_windowskin.width-@trim[2]-@trim[0]) + end + return 32 + end + + def borderY + return 32 if !@trim || skinformat==0 + if @_windowskin && !@_windowskin.disposed? + return @trim[1]+(@_windowskin.height-@trim[3]-@trim[1]) + end + return 32 + end + + def leftEdge; self.startX; end + def topEdge; self.startY; end + def rightEdge; self.borderX-self.leftEdge; end + def bottomEdge; self.borderY-self.topEdge; end + + def startX + return !@trim || skinformat==0 ? 16 : @trim[0] + end + + def startY + return !@trim || skinformat==0 ? 16 : @trim[1] + end + + def endX + return !@trim || skinformat==0 ? 16 : @trim[2] + end + + def endY + return !@trim || skinformat==0 ? 16 : @trim[3] + end + + def startX=(value) + @trim[0]=value + privRefresh + end + + def startY=(value) + @trim[1]=value + privRefresh + end + + def endX=(value) + @trim[2]=value + privRefresh + end + + def endY=(value) + @trim[3]=value + privRefresh + end + + ############# + private + + def ensureBitmap(bitmap,dwidth,dheight) + if !bitmap||bitmap.disposed?||bitmap.width0 && @skinformat==0 && !@rpgvx + # Compatibility Mode: Cursor, pause, and contents have higher Z + @sprites["cursor"].z=@z+1 + @sprites["contents"].z=@z+2 + @sprites["pause"].z=@z+2 + end + if @skinformat==0 + startX=16 + startY=16 + endX=16 + endY=16 + trimStartX=16 + trimStartY=16 + trimWidth=32 + trimHeight=32 + if @rpgvx + trimX=64 + trimY=0 + backRect=Rect.new(0,0,64,64) + blindsRect=Rect.new(0,64,64,64) + else + trimX=128 + trimY=0 + backRect=Rect.new(0,0,128,128) + blindsRect=nil + end + if @_windowskin && !@_windowskin.disposed? + @sprites["corner0"].src_rect.set(trimX,trimY+0,16,16); + @sprites["corner1"].src_rect.set(trimX+48,trimY+0,16,16); + @sprites["corner2"].src_rect.set(trimX,trimY+48,16,16); + @sprites["corner3"].src_rect.set(trimX+48,trimY+48,16,16); + @sprites["scroll0"].src_rect.set(trimX+24, trimY+16, 16, 8) # up + @sprites["scroll3"].src_rect.set(trimX+24, trimY+40, 16, 8) # down + @sprites["scroll1"].src_rect.set(trimX+16, trimY+24, 8, 16) # left + @sprites["scroll2"].src_rect.set(trimX+40, trimY+24, 8, 16) # right + cursorX=trimX + cursorY=trimY+64 + sideRects=[ + Rect.new(trimX+16,trimY+0,32,16), + Rect.new(trimX,trimY+16,16,32), + Rect.new(trimX+48,trimY+16,16,32), + Rect.new(trimX+16,trimY+48,32,16) + ] + pauseRects=[ + trimX+32,trimY+64, + trimX+48,trimY+64, + trimX+32,trimY+80, + trimX+48,trimY+80, + ] + pauseWidth=16 + pauseHeight=16 + @sprites["pause"].src_rect.set( + pauseRects[@pauseframe*2], + pauseRects[@pauseframe*2+1], + pauseWidth,pauseHeight + ) + end + else + trimStartX=@trim[0] + trimStartY=@trim[1] + trimWidth=@trim[0]+(@skinrect.width-@trim[2]+@trim[0]) + trimHeight=@trim[1]+(@skinrect.height-@trim[3]+@trim[1]) + if @_windowskin && !@_windowskin.disposed? + # width of left end of window + startX=@skinrect.x + # width of top end of window + startY=@skinrect.y + cx=@skinrect.x+@skinrect.width # right side of BODY rect + cy=@skinrect.y+@skinrect.height # bottom side of BODY rect + # width of right end of window + endX=(!@_windowskin || @_windowskin.disposed?) ? @skinrect.x : @_windowskin.width-cx + # height of bottom end of window + endY=(!@_windowskin || @_windowskin.disposed?) ? @skinrect.y : @_windowskin.height-cy + @sprites["corner0"].src_rect.set(0,0,startX,startY); + @sprites["corner1"].src_rect.set(cx,0,endX,startY); + @sprites["corner2"].src_rect.set(0,cy,startX,endY); + @sprites["corner3"].src_rect.set(cx,cy,endX,endY); + backRect=Rect.new(@skinrect.x,@skinrect.y, + @skinrect.width,@skinrect.height); + blindsRect=nil + sideRects=[ + Rect.new(startX,0,@skinrect.width,startY), # side0 (top) + Rect.new(0,startY,startX,@skinrect.height), # side1 (left) + Rect.new(cx,startY,endX,@skinrect.height), # side2 (right) + Rect.new(startX,cy,@skinrect.width,endY) # side3 (bottom) + ] + end + end + if @width>trimWidth && @height>trimHeight + @sprites["contents"].src_rect.set(@ox,@oy,@width-trimWidth,@height-trimHeight) + else + @sprites["contents"].src_rect.set(0,0,0,0) + end + @sprites["contents"].x=@x+trimStartX + @sprites["contents"].y=@y+trimStartY + if (@compat & CompatBits::ShowScrollArrows)>0 && @skinformat==0 + # Compatibility mode: Make scroll arrows visible + if @skinformat==0 && @_windowskin && !@_windowskin.disposed? && + @contents && !@contents.disposed? + @sprites["scroll0"].visible = @visible && hascontents && @oy > 0 + @sprites["scroll1"].visible = @visible && hascontents && @ox > 0 + @sprites["scroll2"].visible = @visible && (@contents.width - @ox) > @width-trimWidth + @sprites["scroll3"].visible = @visible && (@contents.height - @oy) > @height-trimHeight + end + end + if @_windowskin && !@_windowskin.disposed? + borderX=startX+endX + borderY=startY+endY + @sprites["corner0"].x=@x + @sprites["corner0"].y=@y + @sprites["corner1"].x=@x+@width-endX + @sprites["corner1"].y=@y + @sprites["corner2"].x=@x + @sprites["corner2"].y=@y+@height-endY + @sprites["corner3"].x=@x+@width-endX + @sprites["corner3"].y=@y+@height-endY + @sprites["side0"].x=@x+startX + @sprites["side0"].y=@y + @sprites["side1"].x=@x + @sprites["side1"].y=@y+startY + @sprites["side2"].x=@x+@width-endX + @sprites["side2"].y=@y+startY + @sprites["side3"].x=@x+startX + @sprites["side3"].y=@y+@height-endY + @sprites["scroll0"].x = @x+@width / 2 - 8 + @sprites["scroll0"].y = @y+8 + @sprites["scroll1"].x = @x+8 + @sprites["scroll1"].y = @y+@height / 2 - 8 + @sprites["scroll2"].x = @x+@width - 16 + @sprites["scroll2"].y = @y+@height / 2 - 8 + @sprites["scroll3"].x = @x+@width / 2 - 8 + @sprites["scroll3"].y = @y+@height - 16 + @sprites["cursor"].x=@x+startX+@cursor_rect.x + @sprites["cursor"].y=@y+startY+@cursor_rect.y + if (@compat & CompatBits::ExpandBack)>0 && @skinformat==0 + # Compatibility mode: Expand background + @sprites["back"].x=@x+2 + @sprites["back"].y=@y+2 + else + @sprites["back"].x=@x+startX + @sprites["back"].y=@y+startY + end + end + if changeBitmap && @_windowskin && !@_windowskin.disposed? + if @skinformat==0 + @sprites["cursor"].x=@x+startX+@cursor_rect.x + @sprites["cursor"].y=@y+startY+@cursor_rect.y + width=@cursor_rect.width + height=@cursor_rect.height + if width > 0 && height > 0 + cursorrects=[ + # sides + Rect.new(cursorX+2, cursorY+0, 28, 2), + Rect.new(cursorX+0, cursorY+2, 2, 28), + Rect.new(cursorX+30, cursorY+2, 2, 28), + Rect.new(cursorX+2, cursorY+30, 28, 2), + # corners + Rect.new(cursorX+0, cursorY+0, 2, 2), + Rect.new(cursorX+30, cursorY+0, 2, 2), + Rect.new(cursorX+0, cursorY+30, 2, 2), + Rect.new(cursorX+30, cursorY+30, 2, 2), + # back + Rect.new(cursorX+2, cursorY+2, 28, 28) + ] + margin=2 + fullmargin=4 + @cursorbitmap = ensureBitmap(@cursorbitmap, width, height) + @cursorbitmap.clear + @sprites["cursor"].bitmap=@cursorbitmap + @sprites["cursor"].src_rect.set(0,0,width,height) + rect = Rect.new(margin,margin,width - fullmargin, height - fullmargin) + @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[8]) + @cursorbitmap.blt(0, 0, @_windowskin, cursorrects[4])# top left + @cursorbitmap.blt(width-margin, 0, @_windowskin, cursorrects[5]) # top right + @cursorbitmap.blt(0, height-margin, @_windowskin, cursorrects[6]) # bottom right + @cursorbitmap.blt(width-margin, height-margin, @_windowskin, cursorrects[7]) # bottom left + rect = Rect.new(margin, 0,width - fullmargin, margin) + @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[0]) + rect = Rect.new(0, margin,margin, height - fullmargin) + @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[1]) + rect = Rect.new(width - margin, margin, margin, height - fullmargin) + @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[2]) + rect = Rect.new(margin, height-margin, width - fullmargin, margin) + @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[3]) + else + @sprites["cursor"].visible=false + @sprites["cursor"].src_rect.set(0,0,0,0) + end + end + for i in 0..3 + case i + when 0 + dwidth = @width-startX-endX + dheight = startY + when 1 + dwidth = startX + dheight = @height-startY-endY + when 2 + dwidth = endX + dheight = @height-startY-endY + when 3 + dwidth = @width-startX-endX + dheight = endY + end + @sidebitmaps[i]=ensureBitmap(@sidebitmaps[i],dwidth,dheight) + @sprites["side#{i}"].bitmap=@sidebitmaps[i] + @sprites["side#{i}"].src_rect.set(0,0,dwidth,dheight) + @sidebitmaps[i].clear + if sideRects[i].width>0 && sideRects[i].height>0 + if (@compat & CompatBits::StretchSides)>0 && @skinformat==0 + # Compatibility mode: Stretch sides + @sidebitmaps[i].stretch_blt(@sprites["side#{i}"].src_rect, + @_windowskin,sideRects[i]) + else + tileBitmap(@sidebitmaps[i],@sprites["side#{i}"].src_rect, + @_windowskin,sideRects[i]) + end + end + end + if (@compat & CompatBits::ExpandBack)>0 && @skinformat==0 + # Compatibility mode: Expand background + backwidth=@width-4 + backheight=@height-4 + else + backwidth=@width-borderX + backheight=@height-borderY + end + if backwidth>0 && backheight>0 + @backbitmap=ensureBitmap(@backbitmap,backwidth,backheight) + @sprites["back"].bitmap=@backbitmap + @sprites["back"].src_rect.set(0,0,backwidth,backheight) + @backbitmap.clear + if @stretch + @backbitmap.stretch_blt(@sprites["back"].src_rect,@_windowskin,backRect) + else + tileBitmap(@backbitmap,@sprites["back"].src_rect,@_windowskin,backRect) + end + if blindsRect + tileBitmap(@backbitmap,@sprites["back"].src_rect,@_windowskin,blindsRect) + end + else + @sprites["back"].visible=false + @sprites["back"].src_rect.set(0,0,0,0) + end + end + if @openness!=255 + opn=@openness/255.0 + for k in @spritekeys + sprite=@sprites[k] + ratio=(@height<=0) ? 0 : (sprite.y-@y)*1.0/@height + sprite.zoom_y=opn + sprite.zoom_x=1.0 + sprite.oy=0 + sprite.y=(@y+(@height/2.0)+(@height*ratio*opn)-(@height/2*opn)).floor + end + else + for k in @spritekeys + sprite=@sprites[k] + sprite.zoom_x=1.0 + sprite.zoom_y=1.0 + end + end + i=0 + # Ensure Z order + for k in @spritekeys + sprite=@sprites[k] + y=sprite.y + sprite.y=i + sprite.oy=(sprite.zoom_y<=0) ? 0 : (i-y)/sprite.zoom_y + sprite.zoom_x*=@zoom_x + sprite.zoom_y*=@zoom_y + sprite.x*=@zoom_x + sprite.y*=@zoom_y + sprite.x+=(@offset_x/sprite.zoom_x) + sprite.y+=(@offset_y/sprite.zoom_y) + end + end +end + + + +#=============================================================================== +# +#=============================================================================== +class SpriteWindow_Base < SpriteWindow + TEXTPADDING=4 # In pixels + + def initialize(x, y, width, height) + super() + self.x = x + self.y = y + self.width = width + self.height = height + self.z = 100 + @curframe=MessageConfig.pbGetSystemFrame() + @curfont=MessageConfig.pbGetSystemFontName() + @sysframe=AnimatedBitmap.new(@curframe) + @customskin=nil + __setWindowskin(@sysframe.bitmap) + __resolveSystemFrame() + pbSetSystemFont(self.contents) if self.contents + end + + def __setWindowskin(skin) + if skin && (skin.width==192 && skin.height==128) || # RPGXP Windowskin + (skin.width==128 && skin.height==128) # RPGVX Windowskin + self.skinformat=0 + else + self.skinformat=1 + end + self.windowskin=skin + end + + def __resolveSystemFrame + if self.skinformat==1 + if !@resolvedFrame + @resolvedFrame=MessageConfig.pbGetSystemFrame() + @resolvedFrame.sub!(/\.[^\.\/\\]+$/,"") + end + self.loadSkinFile("#{@resolvedFrame}.txt") if @resolvedFrame!="" + end + end + + def setSkin(skin) # Filename of windowskin to apply. Supports XP, VX, and animated skins. + @customskin.dispose if @customskin + @customskin=nil + resolvedName=pbResolveBitmap(skin) + return if !resolvedName || resolvedName=="" + @customskin=AnimatedBitmap.new(resolvedName) + __setWindowskin(@customskin.bitmap) + if self.skinformat==1 + skinbase=resolvedName.sub(/\.[^\.\/\\]+$/,"") + self.loadSkinFile("#{skinbase}.txt") + end + end + + def setSystemFrame + @customskin.dispose if @customskin + @customskin=nil + __setWindowskin(@sysframe.bitmap) + __resolveSystemFrame() + end + + def update + super + if self.windowskin + if @customskin + if @customskin.totalFrames>1 + @customskin.update + __setWindowskin(@customskin.bitmap) + end + elsif @sysframe + if @sysframe.totalFrames>1 + @sysframe.update + __setWindowskin(@sysframe.bitmap) + end + end + end + if @curframe!=MessageConfig.pbGetSystemFrame() + @curframe=MessageConfig.pbGetSystemFrame() + if @sysframe && !@customskin + @sysframe.dispose if @sysframe + @sysframe=AnimatedBitmap.new(@curframe) + @resolvedFrame=nil + __setWindowskin(@sysframe.bitmap) + __resolveSystemFrame() + end + begin + refresh + rescue NoMethodError + end + end + if @curfont!=MessageConfig.pbGetSystemFontName() + @curfont=MessageConfig.pbGetSystemFontName() + if self.contents && !self.contents.disposed? + pbSetSystemFont(self.contents) + end + begin + refresh + rescue NoMethodError + end + end + end + + def dispose + self.contents.dispose if self.contents + @sysframe.dispose + @customskin.dispose if @customskin + super + end +end diff --git a/Data/Scripts/009_Objects and windows/005_SpriteWindow_sprites.rb b/Data/Scripts/009_Objects and windows/005_SpriteWindow_sprites.rb deleted file mode 100644 index dbffba4cd..000000000 --- a/Data/Scripts/009_Objects and windows/005_SpriteWindow_sprites.rb +++ /dev/null @@ -1,1084 +0,0 @@ -module GifLibrary - @@loadlib = Win32API.new("Kernel32.dll","LoadLibrary",'p','') - if safeExists?("gif.dll") - PngDll = @@loadlib.call("gif.dll") - GifToPngFiles = Win32API.new("gif.dll","GifToPngFiles",'pp','l') - GifToPngFilesInMemory = Win32API.new("gif.dll","GifToPngFilesInMemory",'plp','l') - CopyDataString = Win32API.new("gif.dll","CopyDataString",'lpl','l') - FreeDataString = Win32API.new("gif.dll","FreeDataString",'l','') - else - PngDll=nil - end - - def self.getDataFromResult(result) - datasize=CopyDataString.call(result,"",0) - ret=nil - if datasize!=0 - data="0"*datasize - CopyDataString.call(result,data,datasize) - ret=data.unpack("V*") - end - FreeDataString.call(result) - return ret - end -end - - - -class AnimatedBitmap - def initialize(file,hue=0) - if file==nil - raise "Filename is nil (missing graphic)\r\n\r\n"+ - "If you see this error in the Continue/New Game screen, you may be loading another game's save file. "+ - "Check your project's title (\"Game > Change Title...\" in RMXP).\r\n" - end - if file.split(/[\\\/]/)[-1][/^\[\d+(?:,\d+)?]/] # Starts with 1 or more digits in square brackets - @bitmap = PngAnimatedBitmap.new(file,hue) - else - @bitmap = GifBitmap.new(file,hue) - end - end - - def [](index); @bitmap[index]; end - def width; @bitmap.bitmap.width; end - def height; @bitmap.bitmap.height; end - def length; @bitmap.length; end - def each; @bitmap.each { |item| yield item }; end - def bitmap; @bitmap.bitmap; end - def currentIndex; @bitmap.currentIndex; end - def frameDelay; @bitmap.frameDelay; end - def totalFrames; @bitmap.totalFrames; end - def disposed?; @bitmap.disposed?; end - def update; @bitmap.update; end - def dispose; @bitmap.dispose; end - def deanimate; @bitmap.deanimate; end - def copy; @bitmap.copy; end -end - - - -class PngAnimatedBitmap - # Creates an animated bitmap from a PNG file. - def initialize(file,hue=0) - @frames=[] - @currentFrame=0 - @framecount=0 - panorama=BitmapCache.load_bitmap(file,hue) - if file.split(/[\\\/]/)[-1][/^\[(\d+)(?:,(\d+))?]/] # Starts with 1 or more digits in brackets - # File has a frame count - numFrames = $1.to_i - delay = $2.to_i - delay = 10 if delay == 0 - raise "Invalid frame count in #{file}" if numFrames<=0 - raise "Invalid frame delay in #{file}" if delay<=0 - if panorama.width % numFrames != 0 - raise "Bitmap's width (#{panorama.width}) is not divisible by frame count: #{file}" - end - @frameDelay = delay - subWidth=panorama.width/numFrames - for i in 0...numFrames - subBitmap=BitmapWrapper.new(subWidth,panorama.height) - subBitmap.blt(0,0,panorama,Rect.new(subWidth*i,0,subWidth,panorama.height)) - @frames.push(subBitmap) - end - panorama.dispose - else - @frames=[panorama] - end - end - - def [](index) - return @frames[index] - end - - def width; self.bitmap.width; end - - def height; self.bitmap.height; end - - def deanimate - for i in 1...@frames.length - @frames[i].dispose - end - @frames=[@frames[0]] - @currentFrame=0 - return @frames[0] - end - - def bitmap - @frames[@currentFrame] - end - - def currentIndex - @currentFrame - end - - def frameDelay(_index) - return @frameDelay - end - - def length - @frames.length - end - - def each - @frames.each { |item| yield item} - end - - def totalFrames - @frameDelay*@frames.length - end - - def disposed? - @disposed - end - - def update - return if disposed? - if @frames.length>1 - @framecount+=1 - if @framecount>=@frameDelay - @framecount=0 - @currentFrame+=1 - @currentFrame%=@frames.length - end - end - end - - def dispose - if !@disposed - for i in @frames - i.dispose - end - end - @disposed=true - end - - attr_accessor :frames # internal - - def copy - x=self.clone - x.frames=x.frames.clone - for i in 0...x.frames.length - x.frames[i]=x.frames[i].copy - end - return x - end -end - - - -#internal class -class GifBitmap - # Creates a bitmap from a GIF file with the specified - # optional viewport. Can also load non-animated bitmaps. - def initialize(file,hue=0) - @gifbitmaps=[] - @gifdelays=[] - @totalframes=0 - @framecount=0 - @currentIndex=0 - @disposed=false - bitmap=nil - filestring=nil - filestrName=nil - file="" if !file - file=canonicalize(file) - begin - bitmap=BitmapCache.load_bitmap(file,hue) - rescue - bitmap=nil - end - if !bitmap || (bitmap.width==32 && bitmap.height==32) - if !file || file.length<1 || file[file.length-1]!=0x2F - if (filestring=pbGetFileChar(file)) - filestrName=file - elsif (filestring=pbGetFileChar(file+".gif")) - filestrName=file+".gif" - elsif (filestring=pbGetFileChar(file+".png")) - filestrName=file+".png" - elsif (filestring=pbGetFileChar(file+".jpg")) - filestrName=file+".jpg" - elsif (filestring=pbGetFileChar(file+".bmp")) - filestrName=file+".bmp" - end - end - end - if bitmap && filestring && filestring[0]==0x47 && - bitmap.width==32 && bitmap.height==32 - #File.open("debug.txt","ab") { |f| f.puts("rejecting bitmap") } - bitmap.dispose - bitmap=nil - end - if bitmap - #File.open("debug.txt","ab") { |f| f.puts("reusing bitmap") } - # Have a regular non-animated bitmap - @totalframes=1 - @framecount=0 - @gifbitmaps=[bitmap] - @gifdelays=[1] - else - tmpBase=File.basename(file)+"_tmp_" - filestring=pbGetFileString(filestrName) if filestring - Dir.chdir(ENV["TEMP"]) { # navigate to temp folder since game might be on a CD-ROM - if filestring && filestring[0]==0x47 && GifLibrary::PngDll - result=GifLibrary::GifToPngFilesInMemory.call(filestring, - filestring.length,tmpBase) - else - result=0 - end - if result>0 - @gifdelays=GifLibrary.getDataFromResult(result) - @totalframes=@gifdelays.pop - for i in 0...@gifdelays.length - @gifdelays[i]=[@gifdelays[i],1].max - bmfile=sprintf("%s%d.png",tmpBase,i) - if safeExists?(bmfile) - gifbitmap=BitmapWrapper.new(bmfile) - @gifbitmaps.push(gifbitmap) - bmfile.hue_change(hue) if hue!=0 - if hue==0 && @gifdelays.length==1 - BitmapCache.setKey(file,gifbitmap) - end - File.delete(bmfile) - else - @gifbitmaps.push(BitmapWrapper.new(32,32)) - end - end - end - } - if @gifbitmaps.length==0 - @gifbitmaps=[BitmapWrapper.new(32,32)] - @gifdelays=[1] - end - if @gifbitmaps.length==1 - BitmapCache.setKey(file,@gifbitmaps[0]) - end - end - end - - def [](index) - return @gifbitmaps[index] - end - - def deanimate - for i in 1...@gifbitmaps.length - @gifbitmaps[i].dispose - end - @gifbitmaps=[@gifbitmaps[0]] - @currentIndex=0 - return @gifbitmaps[0] - end - - def bitmap - @gifbitmaps[@currentIndex] - end - - def currentIndex - @currentIndex - end - - def frameDelay(index) - return @gifdelay[index]/2 # Due to frame count being incremented by 2 - end - - def length - @gifbitmaps.length - end - - def each - @gifbitmaps.each { |item| yield item } - end - - def totalFrames - @totalframes/2 # Due to frame count being incremented by 2 - end - - def disposed? - @disposed - end - - def width - @gifbitmaps.length==0 ? 0 : @gifbitmaps[0].width - end - - def height - @gifbitmaps.length==0 ? 0 : @gifbitmaps[0].height - end - - # This function must be called in order to animate the GIF image. - def update - return if disposed? - if @gifbitmaps.length>0 - @framecount+=2 - @framecount=@totalframes<=0 ? 0 : @framecount%@totalframes - frametoshow=0 - for i in 0...@gifdelays.length - frametoshow=i if @gifdelays[i]<=@framecount - end - @currentIndex=frametoshow - end - end - - def dispose - if !@disposed - for i in @gifbitmaps - i.dispose - end - end - @disposed=true - end - - attr_accessor :gifbitmaps # internal - attr_accessor :gifdelays # internal - - def copy - x=self.clone - x.gifbitmaps=x.gifbitmaps.clone - x.gifdelays=x.gifdelays.clone - for i in 0...x.gifbitmaps.length - x.gifbitmaps[i]=x.gifbitmaps[i].copy - end - return x - end -end - - - -def pbGetTileBitmap(filename, tile_id, hue) - return BitmapCache.tileEx(filename, tile_id, hue) { |f| - AnimatedBitmap.new("Graphics/Tilesets/"+filename).deanimate - } -end - -def pbGetTileset(name,hue=0) - return AnimatedBitmap.new("Graphics/Tilesets/"+name,hue).deanimate -end - -def pbGetAutotile(name,hue=0) - return AnimatedBitmap.new("Graphics/Autotiles/"+name,hue).deanimate -end - -def pbGetAnimation(name,hue=0) - return AnimatedBitmap.new("Graphics/Animations/"+name,hue).deanimate -end - - - -#=============================================================================== -# SpriteWrapper is a class based on Sprite which wraps Sprite's properties. -#=============================================================================== -class SpriteWrapper < Sprite - def initialize(viewport=nil) - @sprite = Sprite.new(viewport) - end - - def dispose; @sprite.dispose; end - def disposed?; return @sprite.disposed?; end - def viewport; return @sprite.viewport; end - def flash(color,duration); return @sprite.flash(color,duration); end - def update; return @sprite.update; end - def x; @sprite.x; end - def x=(value); @sprite.x = value; end - def y; @sprite.y; end - def y=(value); @sprite.y = value; end - def bitmap; @sprite.bitmap; end - def bitmap=(value); @sprite.bitmap = value; end - def src_rect; @sprite.src_rect; end - def src_rect=(value); @sprite.src_rect = value; end - def visible; @sprite.visible; end - def visible=(value); @sprite.visible = value; end - def z; @sprite.z; end - def z=(value); @sprite.z = value; end - def ox; @sprite.ox; end - def ox=(value); @sprite.ox = value; end - def oy; @sprite.oy; end - def oy=(value); @sprite.oy = value; end - def zoom_x; @sprite.zoom_x; end - def zoom_x=(value); @sprite.zoom_x = value; end - def zoom_y; @sprite.zoom_y; end - def zoom_y=(value); @sprite.zoom_y = value; end - def angle; @sprite.angle; end - def angle=(value); @sprite.angle = value; end - def mirror; @sprite.mirror; end - def mirror=(value); @sprite.mirror = value; end - def bush_depth; @sprite.bush_depth; end - def bush_depth=(value); @sprite.bush_depth = value; end - def opacity; @sprite.opacity; end - def opacity=(value); @sprite.opacity = value; end - def blend_type; @sprite.blend_type; end - def blend_type=(value); @sprite.blend_type = value; end - def color; @sprite.color; end - def color=(value); @sprite.color = value; end - def tone; @sprite.tone; end - def tone=(value); @sprite.tone = value; end - - def viewport=(value) - return if self.viewport==value - bitmap = @sprite.bitmap - src_rect = @sprite.src_rect - visible = @sprite.visible - x = @sprite.x - y = @sprite.y - z = @sprite.z - ox = @sprite.ox - oy = @sprite.oy - zoom_x = @sprite.zoom_x - zoom_y = @sprite.zoom_y - angle = @sprite.angle - mirror = @sprite.mirror - bush_depth = @sprite.bush_depth - opacity = @sprite.opacity - blend_type = @sprite.blend_type - color = @sprite.color - tone = @sprite.tone - @sprite.dispose - @sprite = Sprite.new(value) - @sprite.bitmap = bitmap - @sprite.src_rect = src_rect - @sprite.visible = visible - @sprite.x = x - @sprite.y = y - @sprite.z = z - @sprite.ox = ox - @sprite.oy = oy - @sprite.zoom_x = zoom_x - @sprite.zoom_y = zoom_y - @sprite.angle = angle - @sprite.mirror = mirror - @sprite.bush_depth = bush_depth - @sprite.opacity = opacity - @sprite.blend_type = blend_type - @sprite.color = color - @sprite.tone = tone - end -end - - - -#=============================================================================== -# Sprite class that maintains a bitmap of its own. -# This bitmap can't be changed to a different one. -#=============================================================================== -class BitmapSprite < SpriteWrapper - def initialize(width,height,viewport=nil) - super(viewport) - self.bitmap=Bitmap.new(width,height) - @initialized=true - end - - def bitmap=(value) - super(value) if !@initialized - end - - def dispose - self.bitmap.dispose if !self.disposed? - super - end -end - - - -#=============================================================================== -# -#=============================================================================== -class AnimatedSprite < SpriteWrapper - attr_reader :frame - attr_reader :framewidth - attr_reader :frameheight - attr_reader :framecount - attr_reader :animname - - def initializeLong(animname,framecount,framewidth,frameheight,frameskip) - @animname=pbBitmapName(animname) - @realframes=0 - @frameskip=[1,frameskip].max - @frameskip *= Graphics.frame_rate/20 - raise _INTL("Frame width is 0") if framewidth==0 - raise _INTL("Frame height is 0") if frameheight==0 - begin - @animbitmap=AnimatedBitmap.new(animname).deanimate - rescue - @animbitmap=Bitmap.new(framewidth,frameheight) - end - if @animbitmap.width%framewidth!=0 - raise _INTL("Bitmap's width ({1}) is not a multiple of frame width ({2}) [Bitmap={3}]", - @animbitmap.width,framewidth,animname) - end - if @animbitmap.height%frameheight!=0 - raise _INTL("Bitmap's height ({1}) is not a multiple of frame height ({2}) [Bitmap={3}]", - @animbitmap.height,frameheight,animname) - end - @framecount=framecount - @framewidth=framewidth - @frameheight=frameheight - @framesperrow=@animbitmap.width/@framewidth - @playing=false - self.bitmap=@animbitmap - self.src_rect.width=@framewidth - self.src_rect.height=@frameheight - self.frame=0 - end - - # Shorter version of AnimationSprite. All frames are placed on a single row - # of the bitmap, so that the width and height need not be defined beforehand - def initializeShort(animname,framecount,frameskip) - @animname=pbBitmapName(animname) - @realframes=0 - @frameskip=[1,frameskip].max - @frameskip *= Graphics.frame_rate/20 - begin - @animbitmap=AnimatedBitmap.new(animname).deanimate - rescue - @animbitmap=Bitmap.new(framecount*4,32) - end - if @animbitmap.width%framecount!=0 - raise _INTL("Bitmap's width ({1}) is not a multiple of frame count ({2}) [Bitmap={3}]", - @animbitmap.width,framewidth,animname) - end - @framecount=framecount - @framewidth=@animbitmap.width/@framecount - @frameheight=@animbitmap.height - @framesperrow=framecount - @playing=false - self.bitmap=@animbitmap - self.src_rect.width=@framewidth - self.src_rect.height=@frameheight - self.frame=0 - end - - def initialize(*args) - if args.length==1 - super(args[0][3]) - initializeShort(args[0][0],args[0][1],args[0][2]) - else - super(args[5]) - initializeLong(args[0],args[1],args[2],args[3],args[4]) - end - end - - def self.create(animname,framecount,frameskip,viewport=nil) - return self.new([animname,framecount,frameskip,viewport]) - end - - def dispose - return if disposed? - @animbitmap.dispose - @animbitmap=nil - super - end - - def playing? - return @playing - end - - def frame=(value) - @frame=value - @realframes=0 - self.src_rect.x=@frame%@framesperrow*@framewidth - self.src_rect.y=@frame/@framesperrow*@frameheight - end - - def start - @playing=true - @realframes=0 - end - - alias play start - - def stop - @playing=false - end - - def update - super - if @playing - @realframes+=1 - if @realframes==@frameskip - @realframes=0 - self.frame+=1 - self.frame%=self.framecount - end - end - end -end - - - -#=============================================================================== -# Displays an icon bitmap in a sprite. Supports animated images. -#=============================================================================== -class IconSprite < SpriteWrapper - attr_reader :name - - def initialize(*args) - if args.length==0 - super(nil) - self.bitmap=nil - elsif args.length==1 - super(args[0]) - self.bitmap=nil - elsif args.length==2 - super(nil) - self.x=args[0] - self.y=args[1] - else - super(args[2]) - self.x=args[0] - self.y=args[1] - end - @name="" - @_iconbitmap=nil - end - - def dispose - clearBitmaps() - super - end - - # Sets the icon's filename. Alias for setBitmap. - def name=(value) - setBitmap(value) - end - - # Sets the icon's filename. - def setBitmap(file,hue=0) - oldrc=self.src_rect - clearBitmaps() - @name=file - return if file==nil - if file!="" - @_iconbitmap=AnimatedBitmap.new(file,hue) - # for compatibility - self.bitmap=@_iconbitmap ? @_iconbitmap.bitmap : nil - self.src_rect=oldrc - else - @_iconbitmap=nil - end - end - - def clearBitmaps - @_iconbitmap.dispose if @_iconbitmap - @_iconbitmap=nil - self.bitmap=nil if !self.disposed? - end - - def update - super - return if !@_iconbitmap - @_iconbitmap.update - if self.bitmap!=@_iconbitmap.bitmap - oldrc=self.src_rect - self.bitmap=@_iconbitmap.bitmap - self.src_rect=oldrc - end - end -end - - - -#=============================================================================== -# Old GifSprite class, retained for compatibility -#=============================================================================== -class GifSprite < IconSprite - def initialize(path) - super(0,0) - setBitmap(path) - end -end - - - -#=============================================================================== -# SpriteWrapper that stores multiple bitmaps, and displays only one at once. -#=============================================================================== -class ChangelingSprite < SpriteWrapper - def initialize(x=0,y=0,viewport=nil) - super(viewport) - self.x = x - self.y = y - @bitmaps = {} - @currentBitmap = nil - end - - def addBitmap(key,path) - @bitmaps[key].dispose if @bitmaps[key] - @bitmaps[key] = AnimatedBitmap.new(path) - end - - def changeBitmap(key) - @currentBitmap = @bitmaps[key] - self.bitmap = (@currentBitmap) ? @currentBitmap.bitmap : nil - end - - def dispose - return if disposed? - for bm in @bitmaps.values; bm.dispose; end - @bitmaps.clear - super - end - - def update - return if disposed? - for bm in @bitmaps.values; bm.update; end - self.bitmap = (@currentBitmap) ? @currentBitmap.bitmap : nil - end -end - - - -#=============================================================================== -# Displays an icon bitmap in a window. Supports animated images. -#=============================================================================== -class IconWindow < SpriteWindow_Base - attr_reader :name - - def initialize(x,y,width,height,viewport=nil) - super(x,y,width,height) - self.viewport=viewport - self.contents=nil - @name="" - @_iconbitmap=nil - end - - def dispose - clearBitmaps() - super - end - - def update - super - if @_iconbitmap - @_iconbitmap.update - self.contents=@_iconbitmap.bitmap - end - end - - def clearBitmaps - @_iconbitmap.dispose if @_iconbitmap - @_iconbitmap=nil - self.contents=nil if !self.disposed? - end - - # Sets the icon's filename. Alias for setBitmap. - def name=(value) - setBitmap(value) - end - - # Sets the icon's filename. - def setBitmap(file,hue=0) - clearBitmaps() - @name=file - return if file==nil - if file!="" - @_iconbitmap=AnimatedBitmap.new(file,hue) - # for compatibility - self.contents=@_iconbitmap ? @_iconbitmap.bitmap : nil - else - @_iconbitmap=nil - end - end -end - - - -#=============================================================================== -# Displays an icon bitmap in a window. Supports animated images. -# Accepts bitmaps and paths to bitmap files in its constructor. -#=============================================================================== -class PictureWindow < SpriteWindow_Base - def initialize(pathOrBitmap) - super(0,0,32,32) - self.viewport=viewport - self.contents=nil - @_iconbitmap=nil - setBitmap(pathOrBitmap) - end - - def dispose - clearBitmaps() - super - end - - def update - super - if @_iconbitmap - if @_iconbitmap.is_a?(Bitmap) - self.contents=@_iconbitmap - else - @_iconbitmap.update - self.contents=@_iconbitmap.bitmap - end - end - end - - def clearBitmaps - @_iconbitmap.dispose if @_iconbitmap - @_iconbitmap=nil - self.contents=nil if !self.disposed? - end - - # Sets the icon's bitmap or filename. (hue parameter - # is ignored unless pathOrBitmap is a filename) - def setBitmap(pathOrBitmap,hue=0) - clearBitmaps() - if pathOrBitmap!=nil && pathOrBitmap!="" - if pathOrBitmap.is_a?(Bitmap) - @_iconbitmap=pathOrBitmap - self.contents=@_iconbitmap - self.width=@_iconbitmap.width+self.borderX - self.height=@_iconbitmap.height+self.borderY - elsif pathOrBitmap.is_a?(AnimatedBitmap) - @_iconbitmap=pathOrBitmap - self.contents=@_iconbitmap.bitmap - self.width=@_iconbitmap.bitmap.width+self.borderX - self.height=@_iconbitmap.bitmap.height+self.borderY - else - @_iconbitmap=AnimatedBitmap.new(pathOrBitmap,hue) - self.contents=@_iconbitmap ? @_iconbitmap.bitmap : nil - self.width=@_iconbitmap ? @_iconbitmap.bitmap.width+self.borderX : - 32+self.borderX - self.height=@_iconbitmap ? @_iconbitmap.bitmap.height+self.borderY : - 32+self.borderY - end - else - @_iconbitmap=nil - self.width=32+self.borderX - self.height=32+self.borderY - end - end -end - - - -#=============================================================================== -# -#=============================================================================== -class Plane - def update; end - def refresh; end -end - - - -#=============================================================================== -# This class works around a limitation that planes are always -# 640 by 480 pixels in size regardless of the window's size. -#=============================================================================== -class LargePlane < Plane - attr_accessor :borderX - attr_accessor :borderY - - def initialize(viewport=nil) - @__sprite=Sprite.new(viewport) - @__disposed=false - @__ox=0 - @__oy=0 - @__bitmap=nil - @__visible=true - @__sprite.visible=false - @borderX=0 - @borderY=0 - end - - def disposed? - return @__disposed - end - - def dispose - if !@__disposed - @__sprite.bitmap.dispose if @__sprite.bitmap - @__sprite.dispose - @__sprite=nil - @__bitmap=nil - @__disposed=true - end - super - end - - def ox; @__ox; end - def oy; @__oy; end - - def ox=(value); - return if @__ox==value - @__ox = value - refresh - end - - def oy=(value); - return if @__oy==value - @__oy = value - refresh - end - - def bitmap - return @__bitmap - end - - def bitmap=(value) - if value==nil - if @__bitmap!=nil - @__bitmap=nil - @__sprite.visible=(@__visible && !@__bitmap.nil?) - end - elsif @__bitmap!=value && !value.disposed? - @__bitmap=value - refresh - elsif value.disposed? - if @__bitmap!=nil - @__bitmap=nil - @__sprite.visible=(@__visible && !@__bitmap.nil?) - end - end - end - - def viewport; @__sprite.viewport; end - def zoom_x; @__sprite.zoom_x; end - def zoom_y; @__sprite.zoom_y; end - def opacity; @__sprite.opacity; end - def blend_type; @__sprite.blend_type; end - def visible; @__visible; end - def z; @__sprite.z; end - def color; @__sprite.color; end - def tone; @__sprite.tone; end - - def zoom_x=(v); - return if @__sprite.zoom_x==v - @__sprite.zoom_x = v - refresh - end - - def zoom_y=(v); - return if @__sprite.zoom_y==v - @__sprite.zoom_y = v - refresh - end - - def opacity=(v); @__sprite.opacity=(v); end - def blend_type=(v); @__sprite.blend_type=(v); end - def visible=(v); @__visible=v; @__sprite.visible=(@__visible && !@__bitmap.nil?); end - def z=(v); @__sprite.z=(v); end - def color=(v); @__sprite.color=(v); end - def tone=(v); @__sprite.tone=(v); end - def update; ;end - - def refresh - @__sprite.visible = (@__visible && !@__bitmap.nil?) - if @__bitmap - if !@__bitmap.disposed? - @__ox += @__bitmap.width*@__sprite.zoom_x if @__ox<0 - @__oy += @__bitmap.height*@__sprite.zoom_y if @__oy<0 - @__ox -= @__bitmap.width*@__sprite.zoom_x if @__ox>@__bitmap.width - @__oy -= @__bitmap.height*@__sprite.zoom_y if @__oy>@__bitmap.height - dwidth = (Graphics.width/@__sprite.zoom_x+@borderX).to_i # +2 - dheight = (Graphics.height/@__sprite.zoom_y+@borderY).to_i # +2 - @__sprite.bitmap = ensureBitmap(@__sprite.bitmap,dwidth,dheight) - @__sprite.bitmap.clear - tileBitmap(@__sprite.bitmap,@__bitmap,@__bitmap.rect) - else - @__sprite.visible = false - end - end - end - - private - - def ensureBitmap(bitmap,dwidth,dheight) - if !bitmap || bitmap.disposed? || bitmap.width0; left -= srcbitmap.width; end - while top>0; top -= srcbitmap.height; end - y = top - while y255 - privRefresh - end - - def width=(value) - @width=value - privRefresh(true) - end - - def height=(value) - @height=value - privRefresh(true) - end - - def pause=(value) - @pause=value - @pauseopacity=0 if !value - privRefresh if @visible - end - - def x=(value) - @x=value - privRefresh if @visible - end - - def y=(value) - @y=value - privRefresh if @visible - end - - def zoom_x=(value) - @zoom_x=value - privRefresh if @visible - end - - def zoom_y=(value) - @zoom_y=value - privRefresh if @visible - end - - def offset_x=(value) - @x=value - privRefresh if @visible - end - - def offset_y=(value) - @y=value - privRefresh if @visible - end - - def opacity=(value) - @opacity=value - @opacity=0 if @opacity<0 - @opacity=255 if @opacity>255 - privRefresh if @visible - end - - def back_opacity=(value) - @back_opacity=value - @back_opacity=0 if @back_opacity<0 - @back_opacity=255 if @back_opacity>255 - privRefresh if @visible - end - - def contents_opacity=(value) - @contents_opacity=value - @contents_opacity=0 if @contents_opacity<0 - @contents_opacity=255 if @contents_opacity>255 - privRefresh if @visible - end - - def tone=(value) - @tone=value - privRefresh if @visible - end - - def color=(value) - @color=value - privRefresh if @visible - end - - def blend_type=(value) - @blend_type=value - privRefresh if @visible - end - - def flash(color,duration) - return if disposed? - @flash=duration+1 - for i in @sprites - i[1].flash(color,duration) - end - end - - def update - return if disposed? - mustchange=false - if @active - if @cursorblink==0 - @cursoropacity-=8 - @cursorblink=1 if @cursoropacity<=128 - else - @cursoropacity+=8 - @cursorblink=0 if @cursoropacity>=255 - end - privRefreshCursor - else - @cursoropacity=128 - privRefreshCursor - end - if @pause - oldpauseframe=@pauseframe - oldpauseopacity=@pauseopacity - @pauseframe=(Graphics.frame_count / 8) % 4 - @pauseopacity=[@pauseopacity+64,255].min - mustchange=@pauseframe!=oldpauseframe || @pauseopacity!=oldpauseopacity - end - privRefresh if mustchange - if @flash>0 - for i in @sprites.values - i.update - end - @flash-=1 - end - end - - ############# - attr_reader :skinformat - attr_reader :skinrect - - def loadSkinFile(_file) - if (self.windowskin.width==80 || self.windowskin.width==96) && - self.windowskin.height==48 - # Body = X, Y, width, height of body rectangle within windowskin - @skinrect.set(32,16,16,16) - # Trim = X, Y, width, height of trim rectangle within windowskin - @trim=[32,16,16,16] - elsif self.windowskin.width==80 && self.windowskin.height==80 - @skinrect.set(32,32,16,16) - @trim=[32,16,16,48] - end - end - - def windowskin=(value) - oldSkinWidth=(@_windowskin && !@_windowskin.disposed?) ? @_windowskin.width : -1 - oldSkinHeight=(@_windowskin && !@_windowskin.disposed?) ? @_windowskin.height : -1 - @_windowskin=value - if @skinformat==1 - @rpgvx=false - if @_windowskin && !@_windowskin.disposed? - if @_windowskin.width!=oldSkinWidth || @_windowskin.height!=oldSkinHeight - # Update skinrect and trim if windowskin's dimensions have changed - @skinrect.set((@_windowskin.width-16)/2,(@_windowskin.height-16)/2,16,16) - @trim=[@skinrect.x,@skinrect.y,@skinrect.x,@skinrect.y] - end - else - @skinrect.set(16,16,16,16) - @trim=[16,16,16,16] - end - else - if value && value.is_a?(Bitmap) && !value.disposed? && value.width==128 - @rpgvx=true - else - @rpgvx=false - end - @trim=[16,16,16,16] - end - privRefresh(true) - end - - def skinrect=(value) - @skinrect=value - privRefresh - end - - def skinformat=(value) - if @skinformat!=value - @skinformat=value - privRefresh(true) - end - end - - def borderX - return 32 if !@trim || skinformat==0 - if @_windowskin && !@_windowskin.disposed? - return @trim[0]+(@_windowskin.width-@trim[2]-@trim[0]) - end - return 32 - end - - def borderY - return 32 if !@trim || skinformat==0 - if @_windowskin && !@_windowskin.disposed? - return @trim[1]+(@_windowskin.height-@trim[3]-@trim[1]) - end - return 32 - end - - def leftEdge; self.startX; end - def topEdge; self.startY; end - def rightEdge; self.borderX-self.leftEdge; end - def bottomEdge; self.borderY-self.topEdge; end - - def startX - return !@trim || skinformat==0 ? 16 : @trim[0] - end - - def startY - return !@trim || skinformat==0 ? 16 : @trim[1] - end - - def endX - return !@trim || skinformat==0 ? 16 : @trim[2] - end - - def endY - return !@trim || skinformat==0 ? 16 : @trim[3] - end - - def startX=(value) - @trim[0]=value - privRefresh - end - - def startY=(value) - @trim[1]=value - privRefresh - end - - def endX=(value) - @trim[2]=value - privRefresh - end - - def endY=(value) - @trim[3]=value - privRefresh - end - - ############# - private - - def ensureBitmap(bitmap,dwidth,dheight) - if !bitmap||bitmap.disposed?||bitmap.width0 && @skinformat==0 && !@rpgvx - # Compatibility Mode: Cursor, pause, and contents have higher Z - @sprites["cursor"].z=@z+1 - @sprites["contents"].z=@z+2 - @sprites["pause"].z=@z+2 - end - if @skinformat==0 - startX=16 - startY=16 - endX=16 - endY=16 - trimStartX=16 - trimStartY=16 - trimWidth=32 - trimHeight=32 - if @rpgvx - trimX=64 - trimY=0 - backRect=Rect.new(0,0,64,64) - blindsRect=Rect.new(0,64,64,64) - else - trimX=128 - trimY=0 - backRect=Rect.new(0,0,128,128) - blindsRect=nil - end - if @_windowskin && !@_windowskin.disposed? - @sprites["corner0"].src_rect.set(trimX,trimY+0,16,16); - @sprites["corner1"].src_rect.set(trimX+48,trimY+0,16,16); - @sprites["corner2"].src_rect.set(trimX,trimY+48,16,16); - @sprites["corner3"].src_rect.set(trimX+48,trimY+48,16,16); - @sprites["scroll0"].src_rect.set(trimX+24, trimY+16, 16, 8) # up - @sprites["scroll3"].src_rect.set(trimX+24, trimY+40, 16, 8) # down - @sprites["scroll1"].src_rect.set(trimX+16, trimY+24, 8, 16) # left - @sprites["scroll2"].src_rect.set(trimX+40, trimY+24, 8, 16) # right - cursorX=trimX - cursorY=trimY+64 - sideRects=[ - Rect.new(trimX+16,trimY+0,32,16), - Rect.new(trimX,trimY+16,16,32), - Rect.new(trimX+48,trimY+16,16,32), - Rect.new(trimX+16,trimY+48,32,16) - ] - pauseRects=[ - trimX+32,trimY+64, - trimX+48,trimY+64, - trimX+32,trimY+80, - trimX+48,trimY+80, - ] - pauseWidth=16 - pauseHeight=16 - @sprites["pause"].src_rect.set( - pauseRects[@pauseframe*2], - pauseRects[@pauseframe*2+1], - pauseWidth,pauseHeight - ) - end - else - trimStartX=@trim[0] - trimStartY=@trim[1] - trimWidth=@trim[0]+(@skinrect.width-@trim[2]+@trim[0]) - trimHeight=@trim[1]+(@skinrect.height-@trim[3]+@trim[1]) - if @_windowskin && !@_windowskin.disposed? - # width of left end of window - startX=@skinrect.x - # width of top end of window - startY=@skinrect.y - cx=@skinrect.x+@skinrect.width # right side of BODY rect - cy=@skinrect.y+@skinrect.height # bottom side of BODY rect - # width of right end of window - endX=(!@_windowskin || @_windowskin.disposed?) ? @skinrect.x : @_windowskin.width-cx - # height of bottom end of window - endY=(!@_windowskin || @_windowskin.disposed?) ? @skinrect.y : @_windowskin.height-cy - @sprites["corner0"].src_rect.set(0,0,startX,startY); - @sprites["corner1"].src_rect.set(cx,0,endX,startY); - @sprites["corner2"].src_rect.set(0,cy,startX,endY); - @sprites["corner3"].src_rect.set(cx,cy,endX,endY); - backRect=Rect.new(@skinrect.x,@skinrect.y, - @skinrect.width,@skinrect.height); - blindsRect=nil - sideRects=[ - Rect.new(startX,0,@skinrect.width,startY), # side0 (top) - Rect.new(0,startY,startX,@skinrect.height), # side1 (left) - Rect.new(cx,startY,endX,@skinrect.height), # side2 (right) - Rect.new(startX,cy,@skinrect.width,endY) # side3 (bottom) - ] - end - end - if @width>trimWidth && @height>trimHeight - @sprites["contents"].src_rect.set(@ox,@oy,@width-trimWidth,@height-trimHeight) - else - @sprites["contents"].src_rect.set(0,0,0,0) - end - @sprites["contents"].x=@x+trimStartX - @sprites["contents"].y=@y+trimStartY - if (@compat & CompatBits::ShowScrollArrows)>0 && @skinformat==0 - # Compatibility mode: Make scroll arrows visible - if @skinformat==0 && @_windowskin && !@_windowskin.disposed? && - @contents && !@contents.disposed? - @sprites["scroll0"].visible = @visible && hascontents && @oy > 0 - @sprites["scroll1"].visible = @visible && hascontents && @ox > 0 - @sprites["scroll2"].visible = @visible && (@contents.width - @ox) > @width-trimWidth - @sprites["scroll3"].visible = @visible && (@contents.height - @oy) > @height-trimHeight - end - end - if @_windowskin && !@_windowskin.disposed? - borderX=startX+endX - borderY=startY+endY - @sprites["corner0"].x=@x - @sprites["corner0"].y=@y - @sprites["corner1"].x=@x+@width-endX - @sprites["corner1"].y=@y - @sprites["corner2"].x=@x - @sprites["corner2"].y=@y+@height-endY - @sprites["corner3"].x=@x+@width-endX - @sprites["corner3"].y=@y+@height-endY - @sprites["side0"].x=@x+startX - @sprites["side0"].y=@y - @sprites["side1"].x=@x - @sprites["side1"].y=@y+startY - @sprites["side2"].x=@x+@width-endX - @sprites["side2"].y=@y+startY - @sprites["side3"].x=@x+startX - @sprites["side3"].y=@y+@height-endY - @sprites["scroll0"].x = @x+@width / 2 - 8 - @sprites["scroll0"].y = @y+8 - @sprites["scroll1"].x = @x+8 - @sprites["scroll1"].y = @y+@height / 2 - 8 - @sprites["scroll2"].x = @x+@width - 16 - @sprites["scroll2"].y = @y+@height / 2 - 8 - @sprites["scroll3"].x = @x+@width / 2 - 8 - @sprites["scroll3"].y = @y+@height - 16 - @sprites["cursor"].x=@x+startX+@cursor_rect.x - @sprites["cursor"].y=@y+startY+@cursor_rect.y - if (@compat & CompatBits::ExpandBack)>0 && @skinformat==0 - # Compatibility mode: Expand background - @sprites["back"].x=@x+2 - @sprites["back"].y=@y+2 - else - @sprites["back"].x=@x+startX - @sprites["back"].y=@y+startY - end - end - if changeBitmap && @_windowskin && !@_windowskin.disposed? - if @skinformat==0 - @sprites["cursor"].x=@x+startX+@cursor_rect.x - @sprites["cursor"].y=@y+startY+@cursor_rect.y - width=@cursor_rect.width - height=@cursor_rect.height - if width > 0 && height > 0 - cursorrects=[ - # sides - Rect.new(cursorX+2, cursorY+0, 28, 2), - Rect.new(cursorX+0, cursorY+2, 2, 28), - Rect.new(cursorX+30, cursorY+2, 2, 28), - Rect.new(cursorX+2, cursorY+30, 28, 2), - # corners - Rect.new(cursorX+0, cursorY+0, 2, 2), - Rect.new(cursorX+30, cursorY+0, 2, 2), - Rect.new(cursorX+0, cursorY+30, 2, 2), - Rect.new(cursorX+30, cursorY+30, 2, 2), - # back - Rect.new(cursorX+2, cursorY+2, 28, 28) - ] - margin=2 - fullmargin=4 - @cursorbitmap = ensureBitmap(@cursorbitmap, width, height) - @cursorbitmap.clear - @sprites["cursor"].bitmap=@cursorbitmap - @sprites["cursor"].src_rect.set(0,0,width,height) - rect = Rect.new(margin,margin,width - fullmargin, height - fullmargin) - @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[8]) - @cursorbitmap.blt(0, 0, @_windowskin, cursorrects[4])# top left - @cursorbitmap.blt(width-margin, 0, @_windowskin, cursorrects[5]) # top right - @cursorbitmap.blt(0, height-margin, @_windowskin, cursorrects[6]) # bottom right - @cursorbitmap.blt(width-margin, height-margin, @_windowskin, cursorrects[7]) # bottom left - rect = Rect.new(margin, 0,width - fullmargin, margin) - @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[0]) - rect = Rect.new(0, margin,margin, height - fullmargin) - @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[1]) - rect = Rect.new(width - margin, margin, margin, height - fullmargin) - @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[2]) - rect = Rect.new(margin, height-margin, width - fullmargin, margin) - @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[3]) - else - @sprites["cursor"].visible=false - @sprites["cursor"].src_rect.set(0,0,0,0) - end - end - for i in 0..3 - case i - when 0 - dwidth = @width-startX-endX - dheight = startY - when 1 - dwidth = startX - dheight = @height-startY-endY - when 2 - dwidth = endX - dheight = @height-startY-endY - when 3 - dwidth = @width-startX-endX - dheight = endY - end - @sidebitmaps[i]=ensureBitmap(@sidebitmaps[i],dwidth,dheight) - @sprites["side#{i}"].bitmap=@sidebitmaps[i] - @sprites["side#{i}"].src_rect.set(0,0,dwidth,dheight) - @sidebitmaps[i].clear - if sideRects[i].width>0 && sideRects[i].height>0 - if (@compat & CompatBits::StretchSides)>0 && @skinformat==0 - # Compatibility mode: Stretch sides - @sidebitmaps[i].stretch_blt(@sprites["side#{i}"].src_rect, - @_windowskin,sideRects[i]) - else - tileBitmap(@sidebitmaps[i],@sprites["side#{i}"].src_rect, - @_windowskin,sideRects[i]) - end - end - end - if (@compat & CompatBits::ExpandBack)>0 && @skinformat==0 - # Compatibility mode: Expand background - backwidth=@width-4 - backheight=@height-4 - else - backwidth=@width-borderX - backheight=@height-borderY - end - if backwidth>0 && backheight>0 - @backbitmap=ensureBitmap(@backbitmap,backwidth,backheight) - @sprites["back"].bitmap=@backbitmap - @sprites["back"].src_rect.set(0,0,backwidth,backheight) - @backbitmap.clear - if @stretch - @backbitmap.stretch_blt(@sprites["back"].src_rect,@_windowskin,backRect) - else - tileBitmap(@backbitmap,@sprites["back"].src_rect,@_windowskin,backRect) - end - if blindsRect - tileBitmap(@backbitmap,@sprites["back"].src_rect,@_windowskin,blindsRect) - end - else - @sprites["back"].visible=false - @sprites["back"].src_rect.set(0,0,0,0) - end - end - if @openness!=255 - opn=@openness/255.0 - for k in @spritekeys - sprite=@sprites[k] - ratio=(@height<=0) ? 0 : (sprite.y-@y)*1.0/@height - sprite.zoom_y=opn - sprite.zoom_x=1.0 - sprite.oy=0 - sprite.y=(@y+(@height/2.0)+(@height*ratio*opn)-(@height/2*opn)).floor - end - else - for k in @spritekeys - sprite=@sprites[k] - sprite.zoom_x=1.0 - sprite.zoom_y=1.0 - end - end - i=0 - # Ensure Z order - for k in @spritekeys - sprite=@sprites[k] - y=sprite.y - sprite.y=i - sprite.oy=(sprite.zoom_y<=0) ? 0 : (i-y)/sprite.zoom_y - sprite.zoom_x*=@zoom_x - sprite.zoom_y*=@zoom_y - sprite.x*=@zoom_x - sprite.y*=@zoom_y - sprite.x+=(@offset_x/sprite.zoom_x) - sprite.y+=(@offset_y/sprite.zoom_y) - end - end -end - - - -#=============================================================================== -# -#=============================================================================== -class SpriteWindow_Base < SpriteWindow - TEXTPADDING=4 # In pixels - - def initialize(x, y, width, height) - super() - self.x = x - self.y = y - self.width = width - self.height = height - self.z = 100 - @curframe=MessageConfig.pbGetSystemFrame() - @curfont=MessageConfig.pbGetSystemFontName() - @sysframe=AnimatedBitmap.new(@curframe) - @customskin=nil - __setWindowskin(@sysframe.bitmap) - __resolveSystemFrame() - pbSetSystemFont(self.contents) if self.contents - end - - def __setWindowskin(skin) - if skin && (skin.width==192 && skin.height==128) || # RPGXP Windowskin - (skin.width==128 && skin.height==128) # RPGVX Windowskin - self.skinformat=0 - else - self.skinformat=1 - end - self.windowskin=skin - end - - def __resolveSystemFrame - if self.skinformat==1 - if !@resolvedFrame - @resolvedFrame=MessageConfig.pbGetSystemFrame() - @resolvedFrame.sub!(/\.[^\.\/\\]+$/,"") - end - self.loadSkinFile("#{@resolvedFrame}.txt") if @resolvedFrame!="" - end - end - - def setSkin(skin) # Filename of windowskin to apply. Supports XP, VX, and animated skins. - @customskin.dispose if @customskin - @customskin=nil - resolvedName=pbResolveBitmap(skin) - return if !resolvedName || resolvedName=="" - @customskin=AnimatedBitmap.new(resolvedName) - __setWindowskin(@customskin.bitmap) - if self.skinformat==1 - skinbase=resolvedName.sub(/\.[^\.\/\\]+$/,"") - self.loadSkinFile("#{skinbase}.txt") - end - end - - def setSystemFrame - @customskin.dispose if @customskin - @customskin=nil - __setWindowskin(@sysframe.bitmap) - __resolveSystemFrame() - end - - def update - super - if self.windowskin - if @customskin - if @customskin.totalFrames>1 - @customskin.update - __setWindowskin(@customskin.bitmap) - end - elsif @sysframe - if @sysframe.totalFrames>1 - @sysframe.update - __setWindowskin(@sysframe.bitmap) - end - end - end - if @curframe!=MessageConfig.pbGetSystemFrame() - @curframe=MessageConfig.pbGetSystemFrame() - if @sysframe && !@customskin - @sysframe.dispose if @sysframe - @sysframe=AnimatedBitmap.new(@curframe) - @resolvedFrame=nil - __setWindowskin(@sysframe.bitmap) - __resolveSystemFrame() - end - begin - refresh - rescue NoMethodError - end - end - if @curfont!=MessageConfig.pbGetSystemFontName() - @curfont=MessageConfig.pbGetSystemFontName() - if self.contents && !self.contents.disposed? - pbSetSystemFont(self.contents) - end - begin - refresh - rescue NoMethodError - end - end - end - - def dispose - self.contents.dispose if self.contents - @sysframe.dispose - @customskin.dispose if @customskin - super - end -end - - - #=============================================================================== # #=============================================================================== diff --git a/Data/Scripts/009_Objects and windows/006_SpriteWindow_pictures.rb b/Data/Scripts/009_Objects and windows/006_SpriteWindow_pictures.rb new file mode 100644 index 000000000..33a367d0e --- /dev/null +++ b/Data/Scripts/009_Objects and windows/006_SpriteWindow_pictures.rb @@ -0,0 +1,121 @@ +#=============================================================================== +# Displays an icon bitmap in a window. Supports animated images. +#=============================================================================== +class IconWindow < SpriteWindow_Base + attr_reader :name + + def initialize(x,y,width,height,viewport=nil) + super(x,y,width,height) + self.viewport=viewport + self.contents=nil + @name="" + @_iconbitmap=nil + end + + def dispose + clearBitmaps() + super + end + + def update + super + if @_iconbitmap + @_iconbitmap.update + self.contents=@_iconbitmap.bitmap + end + end + + def clearBitmaps + @_iconbitmap.dispose if @_iconbitmap + @_iconbitmap=nil + self.contents=nil if !self.disposed? + end + + # Sets the icon's filename. Alias for setBitmap. + def name=(value) + setBitmap(value) + end + + # Sets the icon's filename. + def setBitmap(file,hue=0) + clearBitmaps() + @name=file + return if file==nil + if file!="" + @_iconbitmap=AnimatedBitmap.new(file,hue) + # for compatibility + self.contents=@_iconbitmap ? @_iconbitmap.bitmap : nil + else + @_iconbitmap=nil + end + end +end + + + +#=============================================================================== +# Displays an icon bitmap in a window. Supports animated images. +# Accepts bitmaps and paths to bitmap files in its constructor. +#=============================================================================== +class PictureWindow < SpriteWindow_Base + def initialize(pathOrBitmap) + super(0,0,32,32) + self.viewport=viewport + self.contents=nil + @_iconbitmap=nil + setBitmap(pathOrBitmap) + end + + def dispose + clearBitmaps() + super + end + + def update + super + if @_iconbitmap + if @_iconbitmap.is_a?(Bitmap) + self.contents=@_iconbitmap + else + @_iconbitmap.update + self.contents=@_iconbitmap.bitmap + end + end + end + + def clearBitmaps + @_iconbitmap.dispose if @_iconbitmap + @_iconbitmap=nil + self.contents=nil if !self.disposed? + end + + # Sets the icon's bitmap or filename. (hue parameter + # is ignored unless pathOrBitmap is a filename) + def setBitmap(pathOrBitmap,hue=0) + clearBitmaps() + if pathOrBitmap!=nil && pathOrBitmap!="" + if pathOrBitmap.is_a?(Bitmap) + @_iconbitmap=pathOrBitmap + self.contents=@_iconbitmap + self.width=@_iconbitmap.width+self.borderX + self.height=@_iconbitmap.height+self.borderY + elsif pathOrBitmap.is_a?(AnimatedBitmap) + @_iconbitmap=pathOrBitmap + self.contents=@_iconbitmap.bitmap + self.width=@_iconbitmap.bitmap.width+self.borderX + self.height=@_iconbitmap.bitmap.height+self.borderY + else + @_iconbitmap=AnimatedBitmap.new(pathOrBitmap,hue) + self.contents=@_iconbitmap ? @_iconbitmap.bitmap : nil + self.width=@_iconbitmap ? @_iconbitmap.bitmap.width+self.borderX : + 32+self.borderX + self.height=@_iconbitmap ? @_iconbitmap.bitmap.height+self.borderY : + 32+self.borderY + end + else + @_iconbitmap=nil + self.width=32+self.borderX + self.height=32+self.borderY + end + end +end diff --git a/Data/Scripts/009_Objects and windows/007_SpriteWrapper.rb b/Data/Scripts/009_Objects and windows/007_SpriteWrapper.rb new file mode 100644 index 000000000..84ab380e2 --- /dev/null +++ b/Data/Scripts/009_Objects and windows/007_SpriteWrapper.rb @@ -0,0 +1,359 @@ +#=============================================================================== +# SpriteWrapper is a class based on Sprite which wraps Sprite's properties. +#=============================================================================== +class SpriteWrapper < Sprite + def initialize(viewport=nil) + @sprite = Sprite.new(viewport) + end + + def dispose; @sprite.dispose; end + def disposed?; return @sprite.disposed?; end + def viewport; return @sprite.viewport; end + def flash(color,duration); return @sprite.flash(color,duration); end + def update; return @sprite.update; end + def x; @sprite.x; end + def x=(value); @sprite.x = value; end + def y; @sprite.y; end + def y=(value); @sprite.y = value; end + def bitmap; @sprite.bitmap; end + def bitmap=(value); @sprite.bitmap = value; end + def src_rect; @sprite.src_rect; end + def src_rect=(value); @sprite.src_rect = value; end + def visible; @sprite.visible; end + def visible=(value); @sprite.visible = value; end + def z; @sprite.z; end + def z=(value); @sprite.z = value; end + def ox; @sprite.ox; end + def ox=(value); @sprite.ox = value; end + def oy; @sprite.oy; end + def oy=(value); @sprite.oy = value; end + def zoom_x; @sprite.zoom_x; end + def zoom_x=(value); @sprite.zoom_x = value; end + def zoom_y; @sprite.zoom_y; end + def zoom_y=(value); @sprite.zoom_y = value; end + def angle; @sprite.angle; end + def angle=(value); @sprite.angle = value; end + def mirror; @sprite.mirror; end + def mirror=(value); @sprite.mirror = value; end + def bush_depth; @sprite.bush_depth; end + def bush_depth=(value); @sprite.bush_depth = value; end + def opacity; @sprite.opacity; end + def opacity=(value); @sprite.opacity = value; end + def blend_type; @sprite.blend_type; end + def blend_type=(value); @sprite.blend_type = value; end + def color; @sprite.color; end + def color=(value); @sprite.color = value; end + def tone; @sprite.tone; end + def tone=(value); @sprite.tone = value; end + + def viewport=(value) + return if self.viewport==value + bitmap = @sprite.bitmap + src_rect = @sprite.src_rect + visible = @sprite.visible + x = @sprite.x + y = @sprite.y + z = @sprite.z + ox = @sprite.ox + oy = @sprite.oy + zoom_x = @sprite.zoom_x + zoom_y = @sprite.zoom_y + angle = @sprite.angle + mirror = @sprite.mirror + bush_depth = @sprite.bush_depth + opacity = @sprite.opacity + blend_type = @sprite.blend_type + color = @sprite.color + tone = @sprite.tone + @sprite.dispose + @sprite = Sprite.new(value) + @sprite.bitmap = bitmap + @sprite.src_rect = src_rect + @sprite.visible = visible + @sprite.x = x + @sprite.y = y + @sprite.z = z + @sprite.ox = ox + @sprite.oy = oy + @sprite.zoom_x = zoom_x + @sprite.zoom_y = zoom_y + @sprite.angle = angle + @sprite.mirror = mirror + @sprite.bush_depth = bush_depth + @sprite.opacity = opacity + @sprite.blend_type = blend_type + @sprite.color = color + @sprite.tone = tone + end +end + + + +#=============================================================================== +# Sprite class that maintains a bitmap of its own. +# This bitmap can't be changed to a different one. +#=============================================================================== +class BitmapSprite < SpriteWrapper + def initialize(width,height,viewport=nil) + super(viewport) + self.bitmap=Bitmap.new(width,height) + @initialized=true + end + + def bitmap=(value) + super(value) if !@initialized + end + + def dispose + self.bitmap.dispose if !self.disposed? + super + end +end + + + +#=============================================================================== +# +#=============================================================================== +class AnimatedSprite < SpriteWrapper + attr_reader :frame + attr_reader :framewidth + attr_reader :frameheight + attr_reader :framecount + attr_reader :animname + + def initializeLong(animname,framecount,framewidth,frameheight,frameskip) + @animname=pbBitmapName(animname) + @realframes=0 + @frameskip=[1,frameskip].max + @frameskip *= Graphics.frame_rate/20 + raise _INTL("Frame width is 0") if framewidth==0 + raise _INTL("Frame height is 0") if frameheight==0 + begin + @animbitmap=AnimatedBitmap.new(animname).deanimate + rescue + @animbitmap=Bitmap.new(framewidth,frameheight) + end + if @animbitmap.width%framewidth!=0 + raise _INTL("Bitmap's width ({1}) is not a multiple of frame width ({2}) [Bitmap={3}]", + @animbitmap.width,framewidth,animname) + end + if @animbitmap.height%frameheight!=0 + raise _INTL("Bitmap's height ({1}) is not a multiple of frame height ({2}) [Bitmap={3}]", + @animbitmap.height,frameheight,animname) + end + @framecount=framecount + @framewidth=framewidth + @frameheight=frameheight + @framesperrow=@animbitmap.width/@framewidth + @playing=false + self.bitmap=@animbitmap + self.src_rect.width=@framewidth + self.src_rect.height=@frameheight + self.frame=0 + end + + # Shorter version of AnimationSprite. All frames are placed on a single row + # of the bitmap, so that the width and height need not be defined beforehand + def initializeShort(animname,framecount,frameskip) + @animname=pbBitmapName(animname) + @realframes=0 + @frameskip=[1,frameskip].max + @frameskip *= Graphics.frame_rate/20 + begin + @animbitmap=AnimatedBitmap.new(animname).deanimate + rescue + @animbitmap=Bitmap.new(framecount*4,32) + end + if @animbitmap.width%framecount!=0 + raise _INTL("Bitmap's width ({1}) is not a multiple of frame count ({2}) [Bitmap={3}]", + @animbitmap.width,framewidth,animname) + end + @framecount=framecount + @framewidth=@animbitmap.width/@framecount + @frameheight=@animbitmap.height + @framesperrow=framecount + @playing=false + self.bitmap=@animbitmap + self.src_rect.width=@framewidth + self.src_rect.height=@frameheight + self.frame=0 + end + + def initialize(*args) + if args.length==1 + super(args[0][3]) + initializeShort(args[0][0],args[0][1],args[0][2]) + else + super(args[5]) + initializeLong(args[0],args[1],args[2],args[3],args[4]) + end + end + + def self.create(animname,framecount,frameskip,viewport=nil) + return self.new([animname,framecount,frameskip,viewport]) + end + + def dispose + return if disposed? + @animbitmap.dispose + @animbitmap=nil + super + end + + def playing? + return @playing + end + + def frame=(value) + @frame=value + @realframes=0 + self.src_rect.x=@frame%@framesperrow*@framewidth + self.src_rect.y=@frame/@framesperrow*@frameheight + end + + def start + @playing=true + @realframes=0 + end + + alias play start + + def stop + @playing=false + end + + def update + super + if @playing + @realframes+=1 + if @realframes==@frameskip + @realframes=0 + self.frame+=1 + self.frame%=self.framecount + end + end + end +end + + + +#=============================================================================== +# Displays an icon bitmap in a sprite. Supports animated images. +#=============================================================================== +class IconSprite < SpriteWrapper + attr_reader :name + + def initialize(*args) + if args.length==0 + super(nil) + self.bitmap=nil + elsif args.length==1 + super(args[0]) + self.bitmap=nil + elsif args.length==2 + super(nil) + self.x=args[0] + self.y=args[1] + else + super(args[2]) + self.x=args[0] + self.y=args[1] + end + @name="" + @_iconbitmap=nil + end + + def dispose + clearBitmaps() + super + end + + # Sets the icon's filename. Alias for setBitmap. + def name=(value) + setBitmap(value) + end + + # Sets the icon's filename. + def setBitmap(file,hue=0) + oldrc=self.src_rect + clearBitmaps() + @name=file + return if file==nil + if file!="" + @_iconbitmap=AnimatedBitmap.new(file,hue) + # for compatibility + self.bitmap=@_iconbitmap ? @_iconbitmap.bitmap : nil + self.src_rect=oldrc + else + @_iconbitmap=nil + end + end + + def clearBitmaps + @_iconbitmap.dispose if @_iconbitmap + @_iconbitmap=nil + self.bitmap=nil if !self.disposed? + end + + def update + super + return if !@_iconbitmap + @_iconbitmap.update + if self.bitmap!=@_iconbitmap.bitmap + oldrc=self.src_rect + self.bitmap=@_iconbitmap.bitmap + self.src_rect=oldrc + end + end +end + + + +#=============================================================================== +# Old GifSprite class, retained for compatibility +#=============================================================================== +class GifSprite < IconSprite + def initialize(path) + super(0,0) + setBitmap(path) + end +end + + + +#=============================================================================== +# SpriteWrapper that stores multiple bitmaps, and displays only one at once. +#=============================================================================== +class ChangelingSprite < SpriteWrapper + def initialize(x=0,y=0,viewport=nil) + super(viewport) + self.x = x + self.y = y + @bitmaps = {} + @currentBitmap = nil + end + + def addBitmap(key,path) + @bitmaps[key].dispose if @bitmaps[key] + @bitmaps[key] = AnimatedBitmap.new(path) + end + + def changeBitmap(key) + @currentBitmap = @bitmaps[key] + self.bitmap = (@currentBitmap) ? @currentBitmap.bitmap : nil + end + + def dispose + return if disposed? + for bm in @bitmaps.values; bm.dispose; end + @bitmaps.clear + super + end + + def update + return if disposed? + for bm in @bitmaps.values; bm.update; end + self.bitmap = (@currentBitmap) ? @currentBitmap.bitmap : nil + end +end diff --git a/Data/Scripts/009_Objects and windows/008_AnimatedBitmap.rb b/Data/Scripts/009_Objects and windows/008_AnimatedBitmap.rb new file mode 100644 index 000000000..3791a738f --- /dev/null +++ b/Data/Scripts/009_Objects and windows/008_AnimatedBitmap.rb @@ -0,0 +1,363 @@ +module GifLibrary + @@loadlib = Win32API.new("Kernel32.dll","LoadLibrary",'p','') + if safeExists?("gif.dll") + PngDll = @@loadlib.call("gif.dll") + GifToPngFiles = Win32API.new("gif.dll","GifToPngFiles",'pp','l') + GifToPngFilesInMemory = Win32API.new("gif.dll","GifToPngFilesInMemory",'plp','l') + CopyDataString = Win32API.new("gif.dll","CopyDataString",'lpl','l') + FreeDataString = Win32API.new("gif.dll","FreeDataString",'l','') + else + PngDll=nil + end + + def self.getDataFromResult(result) + datasize=CopyDataString.call(result,"",0) + ret=nil + if datasize!=0 + data="0"*datasize + CopyDataString.call(result,data,datasize) + ret=data.unpack("V*") + end + FreeDataString.call(result) + return ret + end +end + + + +class AnimatedBitmap + def initialize(file,hue=0) + if file==nil + raise "Filename is nil (missing graphic)\r\n\r\n"+ + "If you see this error in the Continue/New Game screen, you may be loading another game's save file. "+ + "Check your project's title (\"Game > Change Title...\" in RMXP).\r\n" + end + if file.split(/[\\\/]/)[-1][/^\[\d+(?:,\d+)?]/] # Starts with 1 or more digits in square brackets + @bitmap = PngAnimatedBitmap.new(file,hue) + else + @bitmap = GifBitmap.new(file,hue) + end + end + + def [](index); @bitmap[index]; end + def width; @bitmap.bitmap.width; end + def height; @bitmap.bitmap.height; end + def length; @bitmap.length; end + def each; @bitmap.each { |item| yield item }; end + def bitmap; @bitmap.bitmap; end + def currentIndex; @bitmap.currentIndex; end + def frameDelay; @bitmap.frameDelay; end + def totalFrames; @bitmap.totalFrames; end + def disposed?; @bitmap.disposed?; end + def update; @bitmap.update; end + def dispose; @bitmap.dispose; end + def deanimate; @bitmap.deanimate; end + def copy; @bitmap.copy; end +end + + + +class PngAnimatedBitmap + # Creates an animated bitmap from a PNG file. + def initialize(file,hue=0) + @frames=[] + @currentFrame=0 + @framecount=0 + panorama=BitmapCache.load_bitmap(file,hue) + if file.split(/[\\\/]/)[-1][/^\[(\d+)(?:,(\d+))?]/] # Starts with 1 or more digits in brackets + # File has a frame count + numFrames = $1.to_i + delay = $2.to_i + delay = 10 if delay == 0 + raise "Invalid frame count in #{file}" if numFrames<=0 + raise "Invalid frame delay in #{file}" if delay<=0 + if panorama.width % numFrames != 0 + raise "Bitmap's width (#{panorama.width}) is not divisible by frame count: #{file}" + end + @frameDelay = delay + subWidth=panorama.width/numFrames + for i in 0...numFrames + subBitmap=BitmapWrapper.new(subWidth,panorama.height) + subBitmap.blt(0,0,panorama,Rect.new(subWidth*i,0,subWidth,panorama.height)) + @frames.push(subBitmap) + end + panorama.dispose + else + @frames=[panorama] + end + end + + def [](index) + return @frames[index] + end + + def width; self.bitmap.width; end + + def height; self.bitmap.height; end + + def deanimate + for i in 1...@frames.length + @frames[i].dispose + end + @frames=[@frames[0]] + @currentFrame=0 + return @frames[0] + end + + def bitmap + @frames[@currentFrame] + end + + def currentIndex + @currentFrame + end + + def frameDelay(_index) + return @frameDelay + end + + def length + @frames.length + end + + def each + @frames.each { |item| yield item} + end + + def totalFrames + @frameDelay*@frames.length + end + + def disposed? + @disposed + end + + def update + return if disposed? + if @frames.length>1 + @framecount+=1 + if @framecount>=@frameDelay + @framecount=0 + @currentFrame+=1 + @currentFrame%=@frames.length + end + end + end + + def dispose + if !@disposed + for i in @frames + i.dispose + end + end + @disposed=true + end + + attr_accessor :frames # internal + + def copy + x=self.clone + x.frames=x.frames.clone + for i in 0...x.frames.length + x.frames[i]=x.frames[i].copy + end + return x + end +end + + + +#internal class +class GifBitmap + # Creates a bitmap from a GIF file with the specified + # optional viewport. Can also load non-animated bitmaps. + def initialize(file,hue=0) + @gifbitmaps=[] + @gifdelays=[] + @totalframes=0 + @framecount=0 + @currentIndex=0 + @disposed=false + bitmap=nil + filestring=nil + filestrName=nil + file="" if !file + file=canonicalize(file) + begin + bitmap=BitmapCache.load_bitmap(file,hue) + rescue + bitmap=nil + end + if !bitmap || (bitmap.width==32 && bitmap.height==32) + if !file || file.length<1 || file[file.length-1]!=0x2F + if (filestring=pbGetFileChar(file)) + filestrName=file + elsif (filestring=pbGetFileChar(file+".gif")) + filestrName=file+".gif" + elsif (filestring=pbGetFileChar(file+".png")) + filestrName=file+".png" + elsif (filestring=pbGetFileChar(file+".jpg")) + filestrName=file+".jpg" + elsif (filestring=pbGetFileChar(file+".bmp")) + filestrName=file+".bmp" + end + end + end + if bitmap && filestring && filestring[0]==0x47 && + bitmap.width==32 && bitmap.height==32 + #File.open("debug.txt","ab") { |f| f.puts("rejecting bitmap") } + bitmap.dispose + bitmap=nil + end + if bitmap + #File.open("debug.txt","ab") { |f| f.puts("reusing bitmap") } + # Have a regular non-animated bitmap + @totalframes=1 + @framecount=0 + @gifbitmaps=[bitmap] + @gifdelays=[1] + else + tmpBase=File.basename(file)+"_tmp_" + filestring=pbGetFileString(filestrName) if filestring + Dir.chdir(ENV["TEMP"]) { # navigate to temp folder since game might be on a CD-ROM + if filestring && filestring[0]==0x47 && GifLibrary::PngDll + result=GifLibrary::GifToPngFilesInMemory.call(filestring, + filestring.length,tmpBase) + else + result=0 + end + if result>0 + @gifdelays=GifLibrary.getDataFromResult(result) + @totalframes=@gifdelays.pop + for i in 0...@gifdelays.length + @gifdelays[i]=[@gifdelays[i],1].max + bmfile=sprintf("%s%d.png",tmpBase,i) + if safeExists?(bmfile) + gifbitmap=BitmapWrapper.new(bmfile) + @gifbitmaps.push(gifbitmap) + bmfile.hue_change(hue) if hue!=0 + if hue==0 && @gifdelays.length==1 + BitmapCache.setKey(file,gifbitmap) + end + File.delete(bmfile) + else + @gifbitmaps.push(BitmapWrapper.new(32,32)) + end + end + end + } + if @gifbitmaps.length==0 + @gifbitmaps=[BitmapWrapper.new(32,32)] + @gifdelays=[1] + end + if @gifbitmaps.length==1 + BitmapCache.setKey(file,@gifbitmaps[0]) + end + end + end + + def [](index) + return @gifbitmaps[index] + end + + def deanimate + for i in 1...@gifbitmaps.length + @gifbitmaps[i].dispose + end + @gifbitmaps=[@gifbitmaps[0]] + @currentIndex=0 + return @gifbitmaps[0] + end + + def bitmap + @gifbitmaps[@currentIndex] + end + + def currentIndex + @currentIndex + end + + def frameDelay(index) + return @gifdelay[index]/2 # Due to frame count being incremented by 2 + end + + def length + @gifbitmaps.length + end + + def each + @gifbitmaps.each { |item| yield item } + end + + def totalFrames + @totalframes/2 # Due to frame count being incremented by 2 + end + + def disposed? + @disposed + end + + def width + @gifbitmaps.length==0 ? 0 : @gifbitmaps[0].width + end + + def height + @gifbitmaps.length==0 ? 0 : @gifbitmaps[0].height + end + + # This function must be called in order to animate the GIF image. + def update + return if disposed? + if @gifbitmaps.length>0 + @framecount+=2 + @framecount=@totalframes<=0 ? 0 : @framecount%@totalframes + frametoshow=0 + for i in 0...@gifdelays.length + frametoshow=i if @gifdelays[i]<=@framecount + end + @currentIndex=frametoshow + end + end + + def dispose + if !@disposed + for i in @gifbitmaps + i.dispose + end + end + @disposed=true + end + + attr_accessor :gifbitmaps # internal + attr_accessor :gifdelays # internal + + def copy + x=self.clone + x.gifbitmaps=x.gifbitmaps.clone + x.gifdelays=x.gifdelays.clone + for i in 0...x.gifbitmaps.length + x.gifbitmaps[i]=x.gifbitmaps[i].copy + end + return x + end +end + + + +def pbGetTileBitmap(filename, tile_id, hue) + return BitmapCache.tileEx(filename, tile_id, hue) { |f| + AnimatedBitmap.new("Graphics/Tilesets/"+filename).deanimate + } +end + +def pbGetTileset(name,hue=0) + return AnimatedBitmap.new("Graphics/Tilesets/"+name,hue).deanimate +end + +def pbGetAutotile(name,hue=0) + return AnimatedBitmap.new("Graphics/Autotiles/"+name,hue).deanimate +end + +def pbGetAnimation(name,hue=0) + return AnimatedBitmap.new("Graphics/Animations/"+name,hue).deanimate +end diff --git a/Data/Scripts/009_Objects and windows/009_Planes.rb b/Data/Scripts/009_Objects and windows/009_Planes.rb new file mode 100644 index 000000000..4a15d3f89 --- /dev/null +++ b/Data/Scripts/009_Objects and windows/009_Planes.rb @@ -0,0 +1,232 @@ +#=============================================================================== +# +#=============================================================================== +class Plane + def update; end + def refresh; end +end + + + +#=============================================================================== +# This class works around a limitation that planes are always +# 640 by 480 pixels in size regardless of the window's size. +#=============================================================================== +class LargePlane < Plane + attr_accessor :borderX + attr_accessor :borderY + + def initialize(viewport=nil) + @__sprite=Sprite.new(viewport) + @__disposed=false + @__ox=0 + @__oy=0 + @__bitmap=nil + @__visible=true + @__sprite.visible=false + @borderX=0 + @borderY=0 + end + + def disposed? + return @__disposed + end + + def dispose + if !@__disposed + @__sprite.bitmap.dispose if @__sprite.bitmap + @__sprite.dispose + @__sprite=nil + @__bitmap=nil + @__disposed=true + end + super + end + + def ox; @__ox; end + def oy; @__oy; end + + def ox=(value); + return if @__ox==value + @__ox = value + refresh + end + + def oy=(value); + return if @__oy==value + @__oy = value + refresh + end + + def bitmap + return @__bitmap + end + + def bitmap=(value) + if value==nil + if @__bitmap!=nil + @__bitmap=nil + @__sprite.visible=(@__visible && !@__bitmap.nil?) + end + elsif @__bitmap!=value && !value.disposed? + @__bitmap=value + refresh + elsif value.disposed? + if @__bitmap!=nil + @__bitmap=nil + @__sprite.visible=(@__visible && !@__bitmap.nil?) + end + end + end + + def viewport; @__sprite.viewport; end + def zoom_x; @__sprite.zoom_x; end + def zoom_y; @__sprite.zoom_y; end + def opacity; @__sprite.opacity; end + def blend_type; @__sprite.blend_type; end + def visible; @__visible; end + def z; @__sprite.z; end + def color; @__sprite.color; end + def tone; @__sprite.tone; end + + def zoom_x=(v); + return if @__sprite.zoom_x==v + @__sprite.zoom_x = v + refresh + end + + def zoom_y=(v); + return if @__sprite.zoom_y==v + @__sprite.zoom_y = v + refresh + end + + def opacity=(v); @__sprite.opacity=(v); end + def blend_type=(v); @__sprite.blend_type=(v); end + def visible=(v); @__visible=v; @__sprite.visible=(@__visible && !@__bitmap.nil?); end + def z=(v); @__sprite.z=(v); end + def color=(v); @__sprite.color=(v); end + def tone=(v); @__sprite.tone=(v); end + def update; ;end + + def refresh + @__sprite.visible = (@__visible && !@__bitmap.nil?) + if @__bitmap + if !@__bitmap.disposed? + @__ox += @__bitmap.width*@__sprite.zoom_x if @__ox<0 + @__oy += @__bitmap.height*@__sprite.zoom_y if @__oy<0 + @__ox -= @__bitmap.width*@__sprite.zoom_x if @__ox>@__bitmap.width + @__oy -= @__bitmap.height*@__sprite.zoom_y if @__oy>@__bitmap.height + dwidth = (Graphics.width/@__sprite.zoom_x+@borderX).to_i # +2 + dheight = (Graphics.height/@__sprite.zoom_y+@borderY).to_i # +2 + @__sprite.bitmap = ensureBitmap(@__sprite.bitmap,dwidth,dheight) + @__sprite.bitmap.clear + tileBitmap(@__sprite.bitmap,@__bitmap,@__bitmap.rect) + else + @__sprite.visible = false + end + end + end + + private + + def ensureBitmap(bitmap,dwidth,dheight) + if !bitmap || bitmap.disposed? || bitmap.width0; left -= srcbitmap.width; end + while top>0; top -= srcbitmap.height; end + y = top + while y=128 @@ -371,7 +371,7 @@ def pbOnStepTaken(eventTriggered) end # Start wild encounters while turning on the spot -Events.onChangeDirection += proc{ +Events.onChangeDirection += proc { repel = ($PokemonGlobal.repel>0) pbBattleOnStepTaken(repel) if !$game_temp.in_menu } @@ -500,412 +500,6 @@ Events.onMapSceneChange += proc { |_sender,e| -#=============================================================================== -# Event movement -#=============================================================================== -module PBMoveRoute - Down = 1 - Left = 2 - Right = 3 - Up = 4 - LowerLeft = 5 - LowerRight = 6 - UpperLeft = 7 - UpperRight = 8 - Random = 9 - TowardPlayer = 10 - AwayFromPlayer = 11 - Forward = 12 - Backward = 13 - Jump = 14 # xoffset, yoffset - Wait = 15 # frames - TurnDown = 16 - TurnLeft = 17 - TurnRight = 18 - TurnUp = 19 - TurnRight90 = 20 - TurnLeft90 = 21 - Turn180 = 22 - TurnRightOrLeft90 = 23 - TurnRandom = 24 - TurnTowardPlayer = 25 - TurnAwayFromPlayer = 26 - SwitchOn = 27 # 1 param - SwitchOff = 28 # 1 param - ChangeSpeed = 29 # 1 param - ChangeFreq = 30 # 1 param - WalkAnimeOn = 31 - WalkAnimeOff = 32 - StepAnimeOn = 33 - StepAnimeOff = 34 - DirectionFixOn = 35 - DirectionFixOff = 36 - ThroughOn = 37 - ThroughOff = 38 - AlwaysOnTopOn = 39 - AlwaysOnTopOff = 40 - Graphic = 41 # Name, hue, direction, pattern - Opacity = 42 # 1 param - Blending = 43 # 1 param - PlaySE = 44 # 1 param - Script = 45 # 1 param - ScriptAsync = 101 # 1 param -end - - - -def pbMoveRoute(event,commands,waitComplete=false) - route = RPG::MoveRoute.new - route.repeat = false - route.skippable = true - route.list.clear - route.list.push(RPG::MoveCommand.new(PBMoveRoute::ThroughOn)) - i=0 - while i sy.abs - (sx > 0) ? event.turn_left : event.turn_right - else - (sy > 0) ? event.turn_up : event.turn_down - end -end - -def pbMoveTowardPlayer(event) - maxsize = [$game_map.width,$game_map.height].max - return if !pbEventCanReachPlayer?(event,$game_player,maxsize) - loop do - x = event.x - y = event.y - event.move_toward_player - break if event.x==x && event.y==y - while event.moving? - Graphics.update - Input.update - pbUpdateSceneMap - end - end - $PokemonMap.addMovedEvent(event.id) if $PokemonMap -end - -def pbJumpToward(dist=1,playSound=false,cancelSurf=false) - x = $game_player.x - y = $game_player.y - case $game_player.direction - when 2; $game_player.jump(0,dist) # down - when 4; $game_player.jump(-dist,0) # left - when 6; $game_player.jump(dist,0) # right - when 8; $game_player.jump(0,-dist) # up - end - if $game_player.x!=x || $game_player.y!=y - pbSEPlay("Player jump") if playSound - $PokemonEncounters.clearStepCount if cancelSurf - $PokemonTemp.endSurf = true if cancelSurf - while $game_player.jumping? - Graphics.update - Input.update - pbUpdateSceneMap - end - return true - end - return false -end - - - -#=============================================================================== -# Fishing -#=============================================================================== -def pbFishingBegin - $PokemonGlobal.fishing = true - if !pbCommonEvent(FISHING_BEGIN_COMMON_EVENT) - patternb = 2*$game_player.direction - 1 - meta = pbGetMetadata(0,MetadataPlayerA+$PokemonGlobal.playerID) - num = ($PokemonGlobal.surfing) ? 7 : 6 - if meta && meta[num] && meta[num]!="" - charset = pbGetPlayerCharset(meta,num) - 4.times do |pattern| - $game_player.setDefaultCharName(charset,patternb-pattern,true) - (Graphics.frame_rate/20).times do - Graphics.update - Input.update - pbUpdateSceneMap - end - end - end - end -end - -def pbFishingEnd - if !pbCommonEvent(FISHING_END_COMMON_EVENT) - patternb = 2*($game_player.direction - 2) - meta = pbGetMetadata(0,MetadataPlayerA+$PokemonGlobal.playerID) - num = ($PokemonGlobal.surfing) ? 7 : 6 - if meta && meta[num] && meta[num]!="" - charset = pbGetPlayerCharset(meta,num) - 4.times do |pattern| - $game_player.setDefaultCharName(charset,patternb+pattern,true) - (Graphics.frame_rate/20).times do - Graphics.update - Input.update - pbUpdateSceneMap - end - end - end - end - $PokemonGlobal.fishing = false -end - -def pbFishing(hasEncounter,rodType=1) - speedup = ($Trainer.firstPokemon && - (isConst?($Trainer.firstPokemon.ability,PBAbilities,:STICKYHOLD) || - isConst?($Trainer.firstPokemon.ability,PBAbilities,:SUCTIONCUPS))) - biteChance = 20+(25*rodType) # 45, 70, 95 - biteChance *= 1.5 if speedup # 67.5, 100, 100 - hookChance = 100 - oldpattern = $game_player.fullPattern - pbFishingBegin - msgWindow = pbCreateMessageWindow - ret = false - loop do - time = 5+rand(6) - time = [time,5+rand(6)].min if speedup - message = "" - time.times { message += ". " } - if pbWaitMessage(msgWindow,time) - pbFishingEnd - $game_player.setDefaultCharName(nil,oldpattern) - pbMessageDisplay(msgWindow,_INTL("Not even a nibble...")) - break - end - if hasEncounter && rand(100)0 - pbMessageDisplay(msgWindow,message,false) - periodTime.times do - Graphics.update - Input.update - pbUpdateSceneMap - if Input.trigger?(Input::C) || Input.trigger?(Input::B) - return true - end - end - end - return false -end - -# A Pokémon is biting, reflex test to reel it in -def pbWaitForInput(msgWindow,message,frames) - pbMessageDisplay(msgWindow,message,false) - numFrame = 0 - twitchFrame = 0 - twitchFrameTime = Graphics.frame_rate/10 # 0.1 seconds, 4 frames - loop do - Graphics.update - Input.update - pbUpdateSceneMap - # Twitch cycle: 1,0,1,0,0,0,0,0 - twitchFrame = (twitchFrame+1)%(twitchFrameTime*8) - case twitchFrame%twitchFrameTime - when 0, 2 - $game_player.pattern = 1 - else - $game_player.pattern = 0 - end - if Input.trigger?(Input::C) || Input.trigger?(Input::B) - $game_player.pattern = 0 - return true - end - break if !FISHING_AUTO_HOOK && numFrame>frames - numFrame += 1 - end - return false -end - - - -#=============================================================================== -# Bridges, cave escape points, and setting the heal point -#=============================================================================== -def pbBridgeOn(height=2) - $PokemonGlobal.bridge = height -end - -def pbBridgeOff - $PokemonGlobal.bridge = 0 -end - -def pbSetEscapePoint - $PokemonGlobal.escapePoint = [] if !$PokemonGlobal.escapePoint - xco = $game_player.x - yco = $game_player.y - case $game_player.direction - when 2; yco -= 1; dir = 8 # Down - when 4; xco += 1; dir = 6 # Left - when 6; xco -= 1; dir = 4 # Right - when 8; yco += 1; dir = 2 # Up - end - $PokemonGlobal.escapePoint = [$game_map.map_id,xco,yco,dir] -end - -def pbEraseEscapePoint - $PokemonGlobal.escapePoint = [] -end - -def pbSetPokemonCenter - $PokemonGlobal.pokecenterMapId = $game_map.map_id - $PokemonGlobal.pokecenterX = $game_player.x - $PokemonGlobal.pokecenterY = $game_player.y - $PokemonGlobal.pokecenterDirection = $game_player.direction -end - - - -#=============================================================================== -# Partner trainer -#=============================================================================== -def pbRegisterPartner(trainerid,trainername,partyid=0) - trainerid = getID(PBTrainers,trainerid) - pbCancelVehicles - trainer = pbLoadTrainer(trainerid,trainername,partyid) - Events.onTrainerPartyLoad.trigger(nil,trainer) - trainerobject = PokeBattle_Trainer.new(_INTL(trainer[0].name),trainerid) - trainerobject.setForeignID($Trainer) - for i in trainer[2] - i.trainerID = trainerobject.id - i.ot = trainerobject.name - i.calcStats - end - $PokemonGlobal.partner = [trainerid,trainerobject.name,trainerobject.id,trainer[2]] -end - -def pbDeregisterPartner - $PokemonGlobal.partner = nil -end - - - #=============================================================================== # Event locations, terrain tags #=============================================================================== @@ -1321,6 +915,412 @@ end +#=============================================================================== +# Event movement +#=============================================================================== +module PBMoveRoute + Down = 1 + Left = 2 + Right = 3 + Up = 4 + LowerLeft = 5 + LowerRight = 6 + UpperLeft = 7 + UpperRight = 8 + Random = 9 + TowardPlayer = 10 + AwayFromPlayer = 11 + Forward = 12 + Backward = 13 + Jump = 14 # xoffset, yoffset + Wait = 15 # frames + TurnDown = 16 + TurnLeft = 17 + TurnRight = 18 + TurnUp = 19 + TurnRight90 = 20 + TurnLeft90 = 21 + Turn180 = 22 + TurnRightOrLeft90 = 23 + TurnRandom = 24 + TurnTowardPlayer = 25 + TurnAwayFromPlayer = 26 + SwitchOn = 27 # 1 param + SwitchOff = 28 # 1 param + ChangeSpeed = 29 # 1 param + ChangeFreq = 30 # 1 param + WalkAnimeOn = 31 + WalkAnimeOff = 32 + StepAnimeOn = 33 + StepAnimeOff = 34 + DirectionFixOn = 35 + DirectionFixOff = 36 + ThroughOn = 37 + ThroughOff = 38 + AlwaysOnTopOn = 39 + AlwaysOnTopOff = 40 + Graphic = 41 # Name, hue, direction, pattern + Opacity = 42 # 1 param + Blending = 43 # 1 param + PlaySE = 44 # 1 param + Script = 45 # 1 param + ScriptAsync = 101 # 1 param +end + + + +def pbMoveRoute(event,commands,waitComplete=false) + route = RPG::MoveRoute.new + route.repeat = false + route.skippable = true + route.list.clear + route.list.push(RPG::MoveCommand.new(PBMoveRoute::ThroughOn)) + i=0 + while i sy.abs + (sx > 0) ? event.turn_left : event.turn_right + else + (sy > 0) ? event.turn_up : event.turn_down + end +end + +def pbMoveTowardPlayer(event) + maxsize = [$game_map.width,$game_map.height].max + return if !pbEventCanReachPlayer?(event,$game_player,maxsize) + loop do + x = event.x + y = event.y + event.move_toward_player + break if event.x==x && event.y==y + while event.moving? + Graphics.update + Input.update + pbUpdateSceneMap + end + end + $PokemonMap.addMovedEvent(event.id) if $PokemonMap +end + +def pbJumpToward(dist=1,playSound=false,cancelSurf=false) + x = $game_player.x + y = $game_player.y + case $game_player.direction + when 2; $game_player.jump(0,dist) # down + when 4; $game_player.jump(-dist,0) # left + when 6; $game_player.jump(dist,0) # right + when 8; $game_player.jump(0,-dist) # up + end + if $game_player.x!=x || $game_player.y!=y + pbSEPlay("Player jump") if playSound + $PokemonEncounters.clearStepCount if cancelSurf + $PokemonTemp.endSurf = true if cancelSurf + while $game_player.jumping? + Graphics.update + Input.update + pbUpdateSceneMap + end + return true + end + return false +end + + + +#=============================================================================== +# Fishing +#=============================================================================== +def pbFishingBegin + $PokemonGlobal.fishing = true + if !pbCommonEvent(FISHING_BEGIN_COMMON_EVENT) + patternb = 2*$game_player.direction - 1 + meta = pbGetMetadata(0,MetadataPlayerA+$PokemonGlobal.playerID) + num = ($PokemonGlobal.surfing) ? 7 : 6 + if meta && meta[num] && meta[num]!="" + charset = pbGetPlayerCharset(meta,num) + 4.times do |pattern| + $game_player.setDefaultCharName(charset,patternb-pattern,true) + (Graphics.frame_rate/20).times do + Graphics.update + Input.update + pbUpdateSceneMap + end + end + end + end +end + +def pbFishingEnd + if !pbCommonEvent(FISHING_END_COMMON_EVENT) + patternb = 2*($game_player.direction - 2) + meta = pbGetMetadata(0,MetadataPlayerA+$PokemonGlobal.playerID) + num = ($PokemonGlobal.surfing) ? 7 : 6 + if meta && meta[num] && meta[num]!="" + charset = pbGetPlayerCharset(meta,num) + 4.times do |pattern| + $game_player.setDefaultCharName(charset,patternb+pattern,true) + (Graphics.frame_rate/20).times do + Graphics.update + Input.update + pbUpdateSceneMap + end + end + end + end + $PokemonGlobal.fishing = false +end + +def pbFishing(hasEncounter,rodType=1) + speedup = ($Trainer.firstPokemon && + (isConst?($Trainer.firstPokemon.ability,PBAbilities,:STICKYHOLD) || + isConst?($Trainer.firstPokemon.ability,PBAbilities,:SUCTIONCUPS))) + biteChance = 20+(25*rodType) # 45, 70, 95 + biteChance *= 1.5 if speedup # 67.5, 100, 100 + hookChance = 100 + oldpattern = $game_player.fullPattern + pbFishingBegin + msgWindow = pbCreateMessageWindow + ret = false + loop do + time = 5+rand(6) + time = [time,5+rand(6)].min if speedup + message = "" + time.times { message += ". " } + if pbWaitMessage(msgWindow,time) + pbFishingEnd + $game_player.setDefaultCharName(nil,oldpattern) + pbMessageDisplay(msgWindow,_INTL("Not even a nibble...")) + break + end + if hasEncounter && rand(100)0 + pbMessageDisplay(msgWindow,message,false) + periodTime.times do + Graphics.update + Input.update + pbUpdateSceneMap + if Input.trigger?(Input::C) || Input.trigger?(Input::B) + return true + end + end + end + return false +end + +# A Pokémon is biting, reflex test to reel it in +def pbWaitForInput(msgWindow,message,frames) + pbMessageDisplay(msgWindow,message,false) + numFrame = 0 + twitchFrame = 0 + twitchFrameTime = Graphics.frame_rate/10 # 0.1 seconds, 4 frames + loop do + Graphics.update + Input.update + pbUpdateSceneMap + # Twitch cycle: 1,0,1,0,0,0,0,0 + twitchFrame = (twitchFrame+1)%(twitchFrameTime*8) + case twitchFrame%twitchFrameTime + when 0, 2 + $game_player.pattern = 1 + else + $game_player.pattern = 0 + end + if Input.trigger?(Input::C) || Input.trigger?(Input::B) + $game_player.pattern = 0 + return true + end + break if !FISHING_AUTO_HOOK && numFrame>frames + numFrame += 1 + end + return false +end + + + +#=============================================================================== +# Bridges, cave escape points, and setting the heal point +#=============================================================================== +def pbBridgeOn(height=2) + $PokemonGlobal.bridge = height +end + +def pbBridgeOff + $PokemonGlobal.bridge = 0 +end + +def pbSetEscapePoint + $PokemonGlobal.escapePoint = [] if !$PokemonGlobal.escapePoint + xco = $game_player.x + yco = $game_player.y + case $game_player.direction + when 2; yco -= 1; dir = 8 # Down + when 4; xco += 1; dir = 6 # Left + when 6; xco -= 1; dir = 4 # Right + when 8; yco += 1; dir = 2 # Up + end + $PokemonGlobal.escapePoint = [$game_map.map_id,xco,yco,dir] +end + +def pbEraseEscapePoint + $PokemonGlobal.escapePoint = [] +end + +def pbSetPokemonCenter + $PokemonGlobal.pokecenterMapId = $game_map.map_id + $PokemonGlobal.pokecenterX = $game_player.x + $PokemonGlobal.pokecenterY = $game_player.y + $PokemonGlobal.pokecenterDirection = $game_player.direction +end + + + +#=============================================================================== +# Partner trainer +#=============================================================================== +def pbRegisterPartner(trainerid,trainername,partyid=0) + trainerid = getID(PBTrainers,trainerid) + pbCancelVehicles + trainer = pbLoadTrainer(trainerid,trainername,partyid) + Events.onTrainerPartyLoad.trigger(nil,trainer) + trainerobject = PokeBattle_Trainer.new(_INTL(trainer[0].name),trainerid) + trainerobject.setForeignID($Trainer) + for i in trainer[2] + i.trainerID = trainerobject.id + i.ot = trainerobject.name + i.calcStats + end + $PokemonGlobal.partner = [trainerid,trainerobject.name,trainerobject.id,trainer[2]] +end + +def pbDeregisterPartner + $PokemonGlobal.partner = nil +end + + + #=============================================================================== # Picking up an item found on the ground #=============================================================================== diff --git a/Data/Scripts/013_Overworld/003_PField_Visuals.rb b/Data/Scripts/013_Overworld/003_PField_Visuals.rb index 26e75e442..0a6d6000f 100644 --- a/Data/Scripts/013_Overworld/003_PField_Visuals.rb +++ b/Data/Scripts/013_Overworld/003_PField_Visuals.rb @@ -1,227 +1,3 @@ -#=============================================================================== -# Location signpost -#=============================================================================== -class LocationWindow - def initialize(name) - @window = Window_AdvancedTextPokemon.new(name) - @window.resizeToFit(name,Graphics.width) - @window.x = 0 - @window.y = -@window.height - @window.viewport = Viewport.new(0,0,Graphics.width,Graphics.height) - @window.viewport.z = 99999 - @currentmap = $game_map.map_id - @frames = 0 - end - - def disposed? - @window.disposed? - end - - def dispose - @window.dispose - end - - def update - return if @window.disposed? - @window.update - if $game_temp.message_window_showing || @currentmap!=$game_map.map_id - @window.dispose - return - end - if @frames>80 - @window.y -= 4 - @window.dispose if @window.y+@window.height<0 - else - @window.y += 4 if @window.y<0 - @frames += 1 - end - end -end - - - -#=============================================================================== -# Visibility circle in dark maps -#=============================================================================== -class DarknessSprite < SpriteWrapper - attr_reader :radius - - def initialize(viewport=nil) - super(viewport) - @darkness = BitmapWrapper.new(Graphics.width,Graphics.height) - @radius = radiusMin - self.bitmap = @darkness - self.z = 99998 - refresh - end - - def dispose - @darkness.dispose - super - end - - def radiusMin; return 64; end # Before using Flash - def radiusMax; return 176; end # After using Flash - - def radius=(value) - @radius = value - refresh - end - - def refresh - @darkness.fill_rect(0,0,Graphics.width,Graphics.height,Color.new(0,0,0,255)) - cx = Graphics.width/2 - cy = Graphics.height/2 - cradius = @radius - numfades = 5 - for i in 1..numfades - for j in cx-cradius..cx+cradius - diff2 = (cradius * cradius) - ((j - cx) * (j - cx)) - diff = Math.sqrt(diff2) - @darkness.fill_rect(j,cy-diff,1,diff*2,Color.new(0,0,0,255.0*(numfades-i)/numfades)) - end - cradius = (cradius*0.9).floor - end - end -end - - - -#=============================================================================== -# Lights -#=============================================================================== -class LightEffect - def initialize(event,viewport=nil,map=nil,filename=nil) - @light = IconSprite.new(0,0,viewport) - if filename!=nil && filename!="" && pbResolveBitmap("Graphics/Pictures/"+filename) - @light.setBitmap("Graphics/Pictures/"+filename) - else - @light.setBitmap("Graphics/Pictures/LE") - end - @light.z = 1000 - @event = event - @map = (map) ? map : $game_map - @disposed = false - end - - def disposed? - return @disposed - end - - def dispose - @light.dispose - @map = nil - @event = nil - @disposed = true - end - - def update - @light.update - end -end - - - -class LightEffect_Lamp < LightEffect - def initialize(event,viewport=nil,map=nil) - lamp = AnimatedBitmap.new("Graphics/Pictures/LE") - @light = Sprite.new(viewport) - @light.bitmap = Bitmap.new(128,64) - src_rect = Rect.new(0, 0, 64, 64) - @light.bitmap.blt(0, 0, lamp.bitmap, src_rect) - @light.bitmap.blt(20, 0, lamp.bitmap, src_rect) - @light.visible = true - @light.z = 1000 - lamp.dispose - @map = (map) ? map : $game_map - @event = event - end -end - - - -class LightEffect_Basic < LightEffect - def update - return if !@light || !@event - super - @light.opacity = 100 - @light.ox = 32 - @light.oy = 48 - if (Object.const_defined?(:ScreenPosHelper) rescue false) - @light.x = ScreenPosHelper.pbScreenX(@event) - @light.y = ScreenPosHelper.pbScreenY(@event) - @light.zoom_x = ScreenPosHelper.pbScreenZoomX(@event) - else - @light.x = @event.screen_x - @light.y = @event.screen_y - @light.zoom_x = 1.0 - end - @light.zoom_y = @light.zoom_x - @light.tone = $game_screen.tone - end -end - - - -class LightEffect_DayNight < LightEffect - def update - return if !@light || !@event - super - shade = PBDayNight.getShade - if shade>=144 # If light enough, call it fully day - shade = 255 - elsif shade<=64 # If dark enough, call it fully night - shade = 0 - else - shade = 255-(255*(144-shade)/(144-64)) - end - @light.opacity = 255-shade - if @light.opacity>0 - @light.ox = 32 - @light.oy = 48 - if (Object.const_defined?(:ScreenPosHelper) rescue false) - @light.x = ScreenPosHelper.pbScreenX(@event) - @light.y = ScreenPosHelper.pbScreenY(@event) - @light.zoom_x = ScreenPosHelper.pbScreenZoomX(@event) - @light.zoom_y = ScreenPosHelper.pbScreenZoomY(@event) - else - @light.x = @event.screen_x - @light.y = @event.screen_y - @light.zoom_x = 1.0 - @light.zoom_y = 1.0 - end - @light.tone.set($game_screen.tone.red, - $game_screen.tone.green, - $game_screen.tone.blue, - $game_screen.tone.gray) - end - end -end - - - -Events.onSpritesetCreate += proc { |_sender,e| - spriteset = e[0] # Spriteset being created - viewport = e[1] # Viewport used for tilemap and characters - map = spriteset.map # Map associated with the spriteset (not necessarily the current map) - for i in map.events.keys - if map.events[i].name[/^outdoorlight\((\w+)\)$/i] - filename = $~[1].to_s - spriteset.addUserSprite(LightEffect_DayNight.new(map.events[i],viewport,map,filename)) - elsif map.events[i].name.downcase=="outdoorlight" - spriteset.addUserSprite(LightEffect_DayNight.new(map.events[i],viewport,map)) - elsif map.events[i].name[/^light\((\w+)\)$/i] - filename = $~[1].to_s - spriteset.addUserSprite(LightEffect_Basic.new(map.events[i],viewport,map,filename)) - elsif map.events[i].name.downcase=="light" - spriteset.addUserSprite(LightEffect_Basic.new(map.events[i],viewport,map)) - end - end - spriteset.addUserSprite(Particle_Engine.new(viewport,map)) -} - - - #=============================================================================== # Battle start animation #=============================================================================== @@ -540,6 +316,231 @@ def pbBattleAnimationOverride(viewport,battletype=0,foe=nil) end + +#=============================================================================== +# Location signpost +#=============================================================================== +class LocationWindow + def initialize(name) + @window = Window_AdvancedTextPokemon.new(name) + @window.resizeToFit(name,Graphics.width) + @window.x = 0 + @window.y = -@window.height + @window.viewport = Viewport.new(0,0,Graphics.width,Graphics.height) + @window.viewport.z = 99999 + @currentmap = $game_map.map_id + @frames = 0 + end + + def disposed? + @window.disposed? + end + + def dispose + @window.dispose + end + + def update + return if @window.disposed? + @window.update + if $game_temp.message_window_showing || @currentmap!=$game_map.map_id + @window.dispose + return + end + if @frames>80 + @window.y -= 4 + @window.dispose if @window.y+@window.height<0 + else + @window.y += 4 if @window.y<0 + @frames += 1 + end + end +end + + + +#=============================================================================== +# Visibility circle in dark maps +#=============================================================================== +class DarknessSprite < SpriteWrapper + attr_reader :radius + + def initialize(viewport=nil) + super(viewport) + @darkness = BitmapWrapper.new(Graphics.width,Graphics.height) + @radius = radiusMin + self.bitmap = @darkness + self.z = 99998 + refresh + end + + def dispose + @darkness.dispose + super + end + + def radiusMin; return 64; end # Before using Flash + def radiusMax; return 176; end # After using Flash + + def radius=(value) + @radius = value + refresh + end + + def refresh + @darkness.fill_rect(0,0,Graphics.width,Graphics.height,Color.new(0,0,0,255)) + cx = Graphics.width/2 + cy = Graphics.height/2 + cradius = @radius + numfades = 5 + for i in 1..numfades + for j in cx-cradius..cx+cradius + diff2 = (cradius * cradius) - ((j - cx) * (j - cx)) + diff = Math.sqrt(diff2) + @darkness.fill_rect(j,cy-diff,1,diff*2,Color.new(0,0,0,255.0*(numfades-i)/numfades)) + end + cradius = (cradius*0.9).floor + end + end +end + + + +#=============================================================================== +# Lights +#=============================================================================== +class LightEffect + def initialize(event,viewport=nil,map=nil,filename=nil) + @light = IconSprite.new(0,0,viewport) + if filename!=nil && filename!="" && pbResolveBitmap("Graphics/Pictures/"+filename) + @light.setBitmap("Graphics/Pictures/"+filename) + else + @light.setBitmap("Graphics/Pictures/LE") + end + @light.z = 1000 + @event = event + @map = (map) ? map : $game_map + @disposed = false + end + + def disposed? + return @disposed + end + + def dispose + @light.dispose + @map = nil + @event = nil + @disposed = true + end + + def update + @light.update + end +end + + + +class LightEffect_Lamp < LightEffect + def initialize(event,viewport=nil,map=nil) + lamp = AnimatedBitmap.new("Graphics/Pictures/LE") + @light = Sprite.new(viewport) + @light.bitmap = Bitmap.new(128,64) + src_rect = Rect.new(0, 0, 64, 64) + @light.bitmap.blt(0, 0, lamp.bitmap, src_rect) + @light.bitmap.blt(20, 0, lamp.bitmap, src_rect) + @light.visible = true + @light.z = 1000 + lamp.dispose + @map = (map) ? map : $game_map + @event = event + end +end + + + +class LightEffect_Basic < LightEffect + def update + return if !@light || !@event + super + @light.opacity = 100 + @light.ox = 32 + @light.oy = 48 + if (Object.const_defined?(:ScreenPosHelper) rescue false) + @light.x = ScreenPosHelper.pbScreenX(@event) + @light.y = ScreenPosHelper.pbScreenY(@event) + @light.zoom_x = ScreenPosHelper.pbScreenZoomX(@event) + else + @light.x = @event.screen_x + @light.y = @event.screen_y + @light.zoom_x = 1.0 + end + @light.zoom_y = @light.zoom_x + @light.tone = $game_screen.tone + end +end + + + +class LightEffect_DayNight < LightEffect + def update + return if !@light || !@event + super + shade = PBDayNight.getShade + if shade>=144 # If light enough, call it fully day + shade = 255 + elsif shade<=64 # If dark enough, call it fully night + shade = 0 + else + shade = 255-(255*(144-shade)/(144-64)) + end + @light.opacity = 255-shade + if @light.opacity>0 + @light.ox = 32 + @light.oy = 48 + if (Object.const_defined?(:ScreenPosHelper) rescue false) + @light.x = ScreenPosHelper.pbScreenX(@event) + @light.y = ScreenPosHelper.pbScreenY(@event) + @light.zoom_x = ScreenPosHelper.pbScreenZoomX(@event) + @light.zoom_y = ScreenPosHelper.pbScreenZoomY(@event) + else + @light.x = @event.screen_x + @light.y = @event.screen_y + @light.zoom_x = 1.0 + @light.zoom_y = 1.0 + end + @light.tone.set($game_screen.tone.red, + $game_screen.tone.green, + $game_screen.tone.blue, + $game_screen.tone.gray) + end + end +end + + + +Events.onSpritesetCreate += proc { |_sender,e| + spriteset = e[0] # Spriteset being created + viewport = e[1] # Viewport used for tilemap and characters + map = spriteset.map # Map associated with the spriteset (not necessarily the current map) + for i in map.events.keys + if map.events[i].name[/^outdoorlight\((\w+)\)$/i] + filename = $~[1].to_s + spriteset.addUserSprite(LightEffect_DayNight.new(map.events[i],viewport,map,filename)) + elsif map.events[i].name.downcase=="outdoorlight" + spriteset.addUserSprite(LightEffect_DayNight.new(map.events[i],viewport,map)) + elsif map.events[i].name[/^light\((\w+)\)$/i] + filename = $~[1].to_s + spriteset.addUserSprite(LightEffect_Basic.new(map.events[i],viewport,map,filename)) + elsif map.events[i].name.downcase=="light" + spriteset.addUserSprite(LightEffect_Basic.new(map.events[i],viewport,map)) + end + end + spriteset.addUserSprite(Particle_Engine.new(viewport,map)) +} + + + #=============================================================================== # Entering/exiting cave animations #=============================================================================== diff --git a/Data/Scripts/013_Overworld/009_PField_RoamingPokemon.rb b/Data/Scripts/013_Overworld/009_PField_RoamingPokemon.rb index 8750f930d..72099b882 100644 --- a/Data/Scripts/013_Overworld/009_PField_RoamingPokemon.rb +++ b/Data/Scripts/013_Overworld/009_PField_RoamingPokemon.rb @@ -241,6 +241,6 @@ def pbRoamingPokemonBattle(species, level) return (decision!=2 && decision!=5) end -EncounterModifier.registerEncounterEnd(proc{ +EncounterModifier.registerEncounterEnd(proc { $PokemonTemp.roamerIndex = nil }) diff --git a/Data/Scripts/015_Items/002_PItem_ItemEffects.rb b/Data/Scripts/015_Items/002_PItem_ItemEffects.rb index b40202189..214071145 100644 --- a/Data/Scripts/015_Items/002_PItem_ItemEffects.rb +++ b/Data/Scripts/015_Items/002_PItem_ItemEffects.rb @@ -112,9 +112,9 @@ ItemHandlers::UseInField.add(:MAXREPEL,proc { |item| next pbRepel(item,250) }) -Events.onStepTaken += proc{ - if !PBTerrain.isIce?($game_player.terrain_tag) # Shouldn't count down if on ice - if $PokemonGlobal.repel>0 +Events.onStepTaken += proc { + if $PokemonGlobal.repel>0 + if !PBTerrain.isIce?($game_player.terrain_tag) # Shouldn't count down if on ice $PokemonGlobal.repel -= 1 if $PokemonGlobal.repel<=0 if $PokemonBag.pbHasItem?(:REPEL) || diff --git a/Data/Scripts/017_UI/009_PScreen_RegionMap.rb b/Data/Scripts/017_UI/009_PScreen_RegionMap.rb index 621947e03..b535c6970 100644 --- a/Data/Scripts/017_UI/009_PScreen_RegionMap.rb +++ b/Data/Scripts/017_UI/009_PScreen_RegionMap.rb @@ -165,9 +165,15 @@ class PokemonRegionMap_Scene def pbSaveMapData File.open("PBS/townmap.txt","wb") { |f| + f.write(0xEF.chr) + f.write(0xBB.chr) + f.write(0xBF.chr) + f.write("\# "+_INTL("See the documentation on the wiki to learn how to edit this file.")) + f.write("\r\n") for i in 0...@mapdata.length map = @mapdata[i] - return if !map + next if !map + f.write("\#-------------------------------\r\n") f.write(sprintf("[%d]\r\n",i)) f.write(sprintf("Name=%s\r\nFilename=%s\r\n",csvQuote(map[0]),csvQuote(map[1]))) for loc in map[2] diff --git a/Data/Scripts/020_System and utilities/005_PSystem_Utilities.rb b/Data/Scripts/020_System and utilities/005_PSystem_Utilities.rb index 73598486b..30ab59ff8 100644 --- a/Data/Scripts/020_System and utilities/005_PSystem_Utilities.rb +++ b/Data/Scripts/020_System and utilities/005_PSystem_Utilities.rb @@ -286,7 +286,7 @@ end #=============================================================================== -# JavaScript-related utilities +# Json-related utilities #=============================================================================== # Returns true if the given string represents a valid object in JavaScript # Object Notation, and false otherwise. diff --git a/Data/Scripts/021_Debug/002_Debug_Actions.rb b/Data/Scripts/021_Debug/002_Debug_Actions.rb index d42b9bb53..7d0495221 100644 --- a/Data/Scripts/021_Debug/002_Debug_Actions.rb +++ b/Data/Scripts/021_Debug/002_Debug_Actions.rb @@ -82,9 +82,16 @@ class SpriteWindow_DebugVariables < Window_DrawableCommand name = $data_system.switches[index+1] codeswitch = (name[/^s\:/]) val = (codeswitch) ? (eval($~.post_match) rescue nil) : $game_switches[index+1] - if val==nil; status = "[-]"; colors = 0; codeswitch = true - elsif val; status = "[ON]"; colors = 2 - else; status = "[OFF]"; colors = 1 + if val==nil + status = "[-]" + colors = 0 + codeswitch = true + elsif val + status = "[ON]" + colors = 2 + else + status = "[OFF]" + colors = 1 end else name = $data_system.variables[index+1] diff --git a/Data/Scripts/021_Debug/005_Editor_SaveData.rb b/Data/Scripts/021_Debug/005_Editor_SaveData.rb index 9fe7fe749..d162b4944 100644 --- a/Data/Scripts/021_Debug/005_Editor_SaveData.rb +++ b/Data/Scripts/021_Debug/005_Editor_SaveData.rb @@ -550,7 +550,7 @@ def pbSaveTownMap f.write("\r\n") for i in 0...mapdata.length map = mapdata[i] - return if !map + next if !map f.write("\#-------------------------------\r\n") f.write(sprintf("[%d]\r\n",i)) rname = pbGetMessage(MessageTypes::RegionNames,i) diff --git a/Data/Scripts/021_Debug/012_Editor_BattleAnimationEditor.rb b/Data/Scripts/021_Debug/012_Editor_BattleAnimationEditor.rb index 84d43cb98..5294a6aed 100644 --- a/Data/Scripts/021_Debug/012_Editor_BattleAnimationEditor.rb +++ b/Data/Scripts/021_Debug/012_Editor_BattleAnimationEditor.rb @@ -3093,8 +3093,8 @@ class PointPath return ret end step=1.0/frames - t=0.0; - for i in 0..frames+1 + t=0.0 + (frames+2).times do point=pointOnPath(t) if roundValues ret.addPoint(point[0].round,point[1].round) diff --git a/Data/Scripts/999_Main/999_Main.rb b/Data/Scripts/999_Main/999_Main.rb index 34c5d0b9a..f3ed485d1 100644 --- a/Data/Scripts/999_Main/999_Main.rb +++ b/Data/Scripts/999_Main/999_Main.rb @@ -1,7 +1,5 @@ pbCompiler - - class Scene_DebugIntro def main Graphics.transition(0) @@ -12,8 +10,6 @@ class Scene_DebugIntro end end - - def pbCallTitle return Scene_DebugIntro.new if $DEBUG # First parameter is an array of images in the Titles @@ -34,9 +30,9 @@ end def mainFunctionDebug begin - getCurrentProcess = Win32API.new("kernel32.dll","GetCurrentProcess","","l") - setPriorityClass = Win32API.new("kernel32.dll","SetPriorityClass",%w(l i),"") - setPriorityClass.call(getCurrentProcess.call(),32768) # "Above normal" priority class + getCurrentProcess = Win32API.new("kernel32.dll", "GetCurrentProcess", "", "l") + setPriorityClass = Win32API.new("kernel32.dll", "SetPriorityClass", %w(l i), "") + setPriorityClass.call(getCurrentProcess.call(), 32768) # "Above normal" priority class $data_animations = pbLoadRxData("Data/Animations") $data_tilesets = pbLoadRxData("Data/Tilesets") $data_common_events = pbLoadRxData("Data/CommonEvents") @@ -46,9 +42,7 @@ def mainFunctionDebug Graphics.update Graphics.freeze $scene = pbCallTitle - while $scene!=nil - $scene.main - end + $scene.main until $scene.nil? Graphics.transition(20) rescue Hangup pbPrintException($!) if !$DEBUG @@ -59,11 +53,11 @@ end loop do retval = mainFunction - if retval==0 # failed + if retval == 0 # failed loop do Graphics.update end - elsif retval==1 # ended successfully + elsif retval == 1 # ended successfully break end end