#======================================================================= # This module is a little fix that works around PC hardware limitations. # Since Essentials isn't working with software rendering anymore, it now # has to deal with the limits of the GPU. For the most part this is no # big deal, but people do have some really big tilesets. # # The fix is simple enough: If your tileset is too big, a new # bitmap will be constructed with all the excess pixels sent to the # image's right side. This basically means that you now have a limit # far higher than you should ever actually need. # # Hardware limit -> max tileset length: # 1024px -> 4096px # 2048px -> 16384px (enough to get the normal limit) # 4096px -> 65536px (enough to load pretty much any tileset) # 8192px -> 262144px # 16384px -> 1048576px (what most people have at this point) # ~Roza/Zoroark #======================================================================= module TileWrap TILESET_WIDTH = 0x100 # Looks useless, but covers weird numbers given to mkxp.json or a funky driver MAX_TEX_SIZE = (Bitmap.max_size / 1024) * 1024 MAX_TEX_SIZE_BOOSTED = MAX_TEX_SIZE**2/TILESET_WIDTH def self.clamp(val, min, max) val = max if val > max val = min if val < min return val end def self.wrapTileset(originalbmp) width = originalbmp.width height = originalbmp.height if width == TILESET_WIDTH && originalbmp.mega? columns = (height / MAX_TEX_SIZE.to_f).ceil if columns * TILESET_WIDTH > MAX_TEX_SIZE raise "Tilemap is too long!\n\nSIZE: #{originalbmp.height}px\nHARDWARE LIMIT: #{MAX_TEX_SIZE}px\nBOOSTED LIMIT: #{MAX_TEX_SIZE_BOOSTED}px" end bmp = Bitmap.new(TILESET_WIDTH*columns, MAX_TEX_SIZE) remainder = height % MAX_TEX_SIZE columns.times{|col| srcrect = Rect.new(0, col * MAX_TEX_SIZE, width, (col + 1 == columns) ? remainder : MAX_TEX_SIZE) bmp.blt(col*TILESET_WIDTH, 0, originalbmp, srcrect) } return bmp end return originalbmp end def self.getWrappedRect(src_rect) ret = Rect.new(0,0,0,0) col = (src_rect.y / MAX_TEX_SIZE.to_f).floor ret.x = col * TILESET_WIDTH + clamp(src_rect.x,0,TILESET_WIDTH) ret.y = src_rect.y % MAX_TEX_SIZE ret.width = clamp(src_rect.width, 0, TILESET_WIDTH - src_rect.x) ret.height = clamp(src_rect.height, 0, MAX_TEX_SIZE) return ret end def self.blitWrappedPixels(destX, destY, dest, src, srcrect) if (srcrect.y + srcrect.width < MAX_TEX_SIZE) # Save the processing power dest.blt(destX, destY, src, srcrect) return end merge = (srcrect.y % MAX_TEX_SIZE) > ((srcrect.y + srcrect.height) % MAX_TEX_SIZE) srcrect_mod = getWrappedRect(srcrect) if !merge dest.blt(destX, destY, src, srcrect_mod) else #FIXME won't work on heights longer than two columns, but nobody should need # more than 32k pixels high at once anyway side = {:a => MAX_TEX_SIZE - srcrect_mod.y, :b => srcrect_mod.height - (MAX_TEX_SIZE - srcrect_mod.y)} dest.blt(destX, destY, src, Rect.new(srcrect_mod.x, srcrect_mod.y, srcrect_mod.width, side[:a])) dest.blt(destX, destY + side[:a], src, Rect.new(srcrect_mod.x + TILESET_WIDTH, 0, srcrect_mod.width, side[:b])) end end def self.stretchBlitWrappedPixels(destrect, dest, src, srcrect) if (srcrect.y + srcrect.width < MAX_TEX_SIZE) # Save the processing power dest.stretch_blt(destrect, src, srcrect) return end # Does a regular blit to a non-megasurface, then stretch_blts that to # the destination. Yes it is slow tmp = Bitmap.new(srcrect.width, srcrect.height) blitWrappedPixels(0,0,tmp,src,srcrect) dest.stretch_blt(destrect, tmp, Rect.new(0,0,srcrect.width,srcrect.height)) end end #=============================================================================== # #=============================================================================== class CustomTilemapAutotiles attr_accessor :changed def initialize @changed = true @tiles = [nil,nil,nil,nil,nil,nil,nil] end def [](i) return @tiles[i] end def []=(i,value) @tiles[i] = value @changed = true end end class CustomTilemapSprite < Sprite end #=============================================================================== # #=============================================================================== class CustomTilemap attr_reader :tileset attr_reader :autotiles attr_reader :map_data attr_reader :flash_data attr_reader :priorities attr_reader :terrain_tags attr_reader :visible attr_reader :viewport attr_reader :graphicsWidth attr_reader :graphicsHeight attr_reader :ox attr_reader :oy attr_accessor :tone attr_accessor :color Autotiles = [ [ [27, 28, 33, 34], [ 5, 28, 33, 34], [27, 6, 33, 34], [ 5, 6, 33, 34], [27, 28, 33, 12], [ 5, 28, 33, 12], [27, 6, 33, 12], [ 5, 6, 33, 12] ], [ [27, 28, 11, 34], [ 5, 28, 11, 34], [27, 6, 11, 34], [ 5, 6, 11, 34], [27, 28, 11, 12], [ 5, 28, 11, 12], [27, 6, 11, 12], [ 5, 6, 11, 12] ], [ [25, 26, 31, 32], [25, 6, 31, 32], [25, 26, 31, 12], [25, 6, 31, 12], [15, 16, 21, 22], [15, 16, 21, 12], [15, 16, 11, 22], [15, 16, 11, 12] ], [ [29, 30, 35, 36], [29, 30, 11, 36], [ 5, 30, 35, 36], [ 5, 30, 11, 36], [39, 40, 45, 46], [ 5, 40, 45, 46], [39, 6, 45, 46], [ 5, 6, 45, 46] ], [ [25, 30, 31, 36], [15, 16, 45, 46], [13, 14, 19, 20], [13, 14, 19, 12], [17, 18, 23, 24], [17, 18, 11, 24], [41, 42, 47, 48], [ 5, 42, 47, 48] ], [ [37, 38, 43, 44], [37, 6, 43, 44], [13, 18, 19, 24], [13, 14, 43, 44], [37, 42, 43, 48], [17, 18, 47, 48], [13, 18, 43, 48], [ 1, 2, 7, 8] ] ] Animated_Autotiles_Frames = 5*Graphics.frame_rate/20 # Frequency of updating animated autotiles FlashOpacity = [100,90,80,70,80,90] def initialize(viewport) @tileset = nil # Refers to Map Tileset Name @autotiles = CustomTilemapAutotiles.new @map_data = nil # Refers to 3D Array Of Tile Settings @flash_data = nil # Refers to 3D Array of Tile Flashdata @priorities = nil # Refers to Tileset Priorities @terrain_tags = nil # Refers to Tileset Terrain Tags @visible = true # Refers to Tileset Visibleness @ox = 0 # Bitmap Offsets @oy = 0 # Bitmap Offsets @plane = false @haveGraphicsWH = (Graphics.width!=nil rescue false) if @haveGraphicsWH @graphicsWidth = Graphics.width @graphicsHeight = Graphics.height else @graphicsWidth = 640 @graphicsHeight = 480 end @tileWidth = Game_Map::TILE_WIDTH rescue 32 @tileHeight = Game_Map::TILE_HEIGHT rescue 32 @tileSrcWidth = 32 @tileSrcHeight = 32 @diffsizes = (@tileWidth!=@tileSrcWidth) || (@tileHeight!=@tileSrcHeight) @tone = Tone.new(0,0,0,0) @oldtone = Tone.new(0,0,0,0) @color = Color.new(0,0,0,0) @oldcolor = Color.new(0,0,0,0) @selfviewport = Viewport.new(0,0,graphicsWidth,graphicsHeight) @viewport = (viewport) ? viewport : @selfviewport @tiles = [] @autotileInfo = [] @regularTileInfo = [] @oldOx = 0 @oldOy = 0 @oldViewportOx = 0 @oldViewportOy = 0 @layer0 = CustomTilemapSprite.new(viewport) @layer0.visible = true @nowshown = false @layer0.bitmap = Bitmap.new([graphicsWidth+320,1].max,[graphicsHeight+320,1].max) @layer0.z = 0 @layer0.ox = 0 @layer0.oy = 0 @oxLayer0 = 0 @oyLayer0 = 0 @flash = nil @oxFlash = 0 @oyFlash = 0 @priotiles = {} @priotilesfast = [] @prioautotiles = {} @autosprites = [] @framecount = [0,0,0,0,0,0,0,0] # For autotiles @tilesetChanged = true @flashChanged = false @firsttime = true @disposed = false @usedsprites = false @layer0clip = true @firsttimeflash = true @fullyrefreshed = false @fullyrefreshedautos = false @shouldWrap = false end def dispose return if disposed? @help.dispose if @help @help = nil i = 0; len = @autotileInfo.length while i=xsize xEnd = (@ox+@viewport.rect.width)/@tileWidth + 1 xEnd = 0 if xEnd<0 xEnd = xsize-1 if xEnd>=xsize return false if xStart>=xEnd ysize = @map_data.ysize yStart = @oy/@tileHeight - 1 yStart = 0 if yStart<0 yStart = ysize-1 if yStart>=ysize yEnd = (@oy+@viewport.rect.height)/@tileHeight + 1 yEnd = 0 if yEnd<0 yEnd = ysize-1 if yEnd>=ysize return false if yStart>=yEnd return true end def autotileNumFrames(id) autotile = @autotiles[id/48-1] return 0 if !autotile || autotile.disposed? frames = 1 if autotile.height==@tileHeight frames = autotile.width/@tileWidth else frames = autotile.width/(3*@tileWidth) end return frames end def autotileFrame(id) autotile = @autotiles[id/48-1] return -1 if !autotile || autotile.disposed? frames = 1 if autotile.height==@tileHeight frames = autotile.width/@tileWidth else frames = autotile.width/(3*@tileWidth) end return (Graphics.frame_count/Animated_Autotiles_Frames)%frames end def repaintAutotiles for i in 0...@autotileInfo.length next if !@autotileInfo[i] frame = autotileFrame(i) @autotileInfo[i].clear bltAutotile(@autotileInfo[i],0,0,i,frame) end end def bltAutotile(bitmap,x,y,id,frame) return if frame<0 autotile = @autotiles[id/48-1] return if !autotile || autotile.disposed? if autotile.height==@tileSrcHeight anim = frame*@tileSrcWidth src_rect = Rect.new(anim,0,@tileSrcWidth,@tileSrcHeight) if @diffsizes bitmap.stretch_blt(Rect.new(x,y,@tileWidth,@tileHeight),autotile,src_rect) else bitmap.blt(x,y,autotile,src_rect) end else anim = frame*3*@tileSrcWidth id %= 48 tiles = Autotiles[id>>3][id&7] src = Rect.new(0,0,0,0) halfTileWidth = @tileWidth>>1 halfTileHeight = @tileHeight>>1 halfTileSrcWidth = @tileSrcWidth>>1 halfTileSrcHeight = @tileSrcHeight>>1 for i in 0...4 tile_position = tiles[i] - 1 src.set( (tile_position % 6)*halfTileSrcWidth + anim, (tile_position / 6)*halfTileSrcHeight, halfTileSrcWidth, halfTileSrcHeight) if @diffsizes bitmap.stretch_blt( Rect.new(i%2*halfTileWidth+x,i/2*halfTileHeight+y,halfTileWidth,halfTileHeight), autotile,src) else bitmap.blt(i%2*halfTileWidth+x,i/2*halfTileHeight+y, autotile, src) end end end end def getAutotile(sprite,id) frames = @framecount[id/48-1] if frames<=1 anim = 0 else anim = (Graphics.frame_count/Animated_Autotiles_Frames)%frames end return if anim<0 bitmap = @autotileInfo[id] if !bitmap bitmap = Bitmap.new(@tileWidth,@tileHeight) bltAutotile(bitmap,0,0,id,anim) @autotileInfo[id] = bitmap end sprite.bitmap = bitmap if sprite.bitmap!=bitmap end def getRegularTile(sprite,id) if @diffsizes bitmap = @regularTileInfo[id] if !bitmap bitmap = Bitmap.new(@tileWidth,@tileHeight) rect = Rect.new(((id - 384)&7)*@tileSrcWidth,((id - 384)>>3)*@tileSrcHeight, @tileSrcWidth,@tileSrcHeight) TileWrap::stretchBlitWrappedPixels(Rect.new(0,0,@tileWidth,@tileHeight), bitmap, @tileset, rect) @regularTileInfo[id] = bitmap end sprite.bitmap = bitmap if sprite.bitmap!=bitmap else sprite.bitmap = @tileset if sprite.bitmap!=@tileset rect = Rect.new(((id - 384)&7)*@tileSrcWidth,((id - 384)>>3)*@tileSrcHeight, @tileSrcWidth,@tileSrcHeight) rect = TileWrap::getWrappedRect(rect) if @shouldWrap sprite.src_rect = rect end end def addTile(tiles,count,xpos,ypos,id) terrain = @terrain_tags[id] priority = @priorities[id] if id >= 384 # Tileset tile if count>=tiles.length sprite = CustomTilemapSprite.new(@viewport) tiles.push(sprite,0) else sprite = tiles[count] tiles[count+1] = 0 end sprite.visible = @visible sprite.x = xpos sprite.y = ypos sprite.tone = @tone sprite.color = @color getRegularTile(sprite,id) else # Autotile if count>=tiles.length sprite = CustomTilemapSprite.new(@viewport) tiles.push(sprite,1) else sprite = tiles[count] tiles[count+1] = 1 end sprite.visible = @visible sprite.x = xpos sprite.y = ypos sprite.tone = @tone sprite.color = @color getAutotile(sprite,id) end terrain_tag_data = GameData::TerrainTag.try_get(terrain) if terrain_tag_data.shows_reflections spriteZ = -100 elsif $PokemonGlobal.bridge > 0 && terrain_tag_data.bridge spriteZ = 1 else spriteZ = (priority==0) ? 0 : ypos+priority*32+32 end sprite.z = spriteZ count += 2 return count end def refresh_flash if @flash_data && !@flash @flash = CustomTilemapSprite.new(viewport) @flash.visible = true @flash.z = 1 @flash.tone = tone @flash.color = color @flash.blend_type = 1 @flash.bitmap = Bitmap.new([graphicsWidth*2,1].max,[graphicsHeight*2,1].max) @firsttimeflash = true elsif !@flash_data && @flash @flash.bitmap.dispose if @flash.bitmap @flash.dispose @flash = nil @firsttimeflash = false end end def refreshFlashSprite return if !@flash || @flash_data.nil? ptX = @ox-@oxFlash ptY = @oy-@oyFlash if !@firsttimeflash && !@usedsprites && ptX>=0 && ptX+@viewport.rect.width<=@flash.bitmap.width && ptY>=0 && ptY+@viewport.rect.height<=@flash.bitmap.height @flash.ox = 0 @flash.oy = 0 @flash.src_rect.set(ptX.round,ptY.round, @viewport.rect.width,@viewport.rect.height) return end width = @flash.bitmap.width height = @flash.bitmap.height bitmap = @flash.bitmap ysize = @map_data.ysize xsize = @map_data.xsize @firsttimeflash = false @oxFlash = @ox-(width>>2) @oyFlash = @oy-(height>>2) @flash.ox = 0 @flash.oy = 0 @flash.src_rect.set(width>>2,height>>2, @viewport.rect.width,@viewport.rect.height) @flash.bitmap.clear @oxFlash = @oxFlash.floor @oyFlash = @oyFlash.floor xStart = @oxFlash/@tileWidth xStart = 0 if xStart<0 yStart = @oyFlash/@tileHeight yStart = 0 if yStart<0 xEnd = xStart+(width/@tileWidth)+1 yEnd = yStart+(height/@tileHeight)+1 xEnd = xsize if xEnd>=xsize yEnd = ysize if yEnd>=ysize if xStart>8)&15 g = (id>>4)&15 b = (id)&15 tmpcolor.set(r<<4,g<<4,b<<4) bitmap.fill_rect(xpos,ypos,@tileWidth,@tileHeight,tmpcolor) end end end end def refresh_tileset i = 0 len = @regularTileInfo.length while i < len if @regularTileInfo[i] @regularTileInfo[i].dispose @regularTileInfo[i] = nil end i += 1 end @regularTileInfo.clear @priotiles.clear ysize = @map_data.ysize xsize = @map_data.xsize zsize = @map_data.zsize if xsize > 100 || ysize > 100 @fullyrefreshed = false else for z in 0...zsize for y in 0...ysize for x in 0...xsize id = @map_data[x, y, z] next if id == 0 next if @priorities[id] == 0 && !GameData::TerrainTag.try_get(@terrain_tags[id]).shows_reflections @priotiles[[x, y]] = [] if !@priotiles[[x, y]] @priotiles[[x, y]].push([z, id]) end end end @fullyrefreshed = true end end def refresh_autotiles i = 0 len = @autotileInfo.length while i < len if @autotileInfo[i] @autotileInfo[i].dispose @autotileInfo[i] = nil end i += 1 end i = 0 len = @autosprites.length while i < len if @autosprites[i] @autosprites[i].dispose @autosprites[i] = nil end i += 2 end @autosprites.clear @autotileInfo.clear @prioautotiles.clear @priorect = nil @priorectautos = nil hasanimated = false for i in 0...7 numframes = autotileNumFrames(48 * (i + 1)) hasanimated = true if numframes >= 2 @framecount[i] = numframes end if hasanimated ysize = @map_data.ysize xsize = @map_data.xsize zsize = @map_data.zsize if xsize > 100 || ysize > 100 @fullyrefreshedautos = false else for y in 0...ysize for x in 0...xsize for z in 0...zsize id = @map_data[x, y, z] next if id == 0 || id >= 384 # Skip non-autotiles next if @priorities[id] != 0 || GameData::TerrainTag.try_get(@terrain_tags[id]).shows_reflections next if @framecount[id / 48 - 1] < 2 @prioautotiles[[x, y]] = true break end end end @fullyrefreshedautos = true end else @fullyrefreshedautos = true end end def refreshLayer0(autotiles = false) return true if autotiles && !shown? ptX = @ox - @oxLayer0 ptY = @oy - @oyLayer0 if !autotiles && !@firsttime && !@usedsprites && ptX >= 0 && ptX + @viewport.rect.width <= @layer0.bitmap.width && ptY >= 0 && ptY + @viewport.rect.height <= @layer0.bitmap.height if @layer0clip && @viewport.ox == 0 && @viewport.oy == 0 @layer0.ox = 0 @layer0.oy = 0 @layer0.src_rect.set(ptX.round, ptY.round, @viewport.rect.width, @viewport.rect.height) else @layer0.ox = ptX.round @layer0.oy = ptY.round @layer0.src_rect.set(0, 0, @layer0.bitmap.width, @layer0.bitmap.height) end return true end width = @layer0.bitmap.width height = @layer0.bitmap.height bitmap = @layer0.bitmap ysize = @map_data.ysize xsize = @map_data.xsize zsize = @map_data.zsize twidth = @tileWidth theight = @tileHeight mapdata = @map_data if autotiles return true if @fullyrefreshedautos && @prioautotiles.length == 0 xStart = @oxLayer0 / twidth xStart = 0 if xStart < 0 yStart = @oyLayer0 / theight yStart = 0 if yStart < 0 xEnd = xStart + (width / twidth) + 1 xEnd = xsize if xEnd > xsize yEnd = yStart + (height / theight) + 1 yEnd = ysize if yEnd > ysize return true if xStart >= xEnd || yStart >= yEnd trans = Color.new(0, 0, 0, 0) temprect = Rect.new(0, 0, 0, 0) tilerect = Rect.new(0, 0, twidth, theight) zrange = 0...zsize overallcount = 0 count = 0 if !@fullyrefreshedautos for y in yStart..yEnd for x in xStart..xEnd for z in zrange id = mapdata[x, y, z] next if !id || id < 48 || id >= 384 # Skip non-autotiles prioid = @priorities[id] next if prioid != 0 || GameData::TerrainTag.try_get(@terrain_tags[id]).shows_reflections fcount = @framecount[id / 48 - 1] next if !fcount || fcount < 2 overallcount += 1 xpos = (x * twidth) - @oxLayer0 ypos = (y * theight) - @oyLayer0 bitmap.fill_rect(xpos, ypos, twidth, theight, trans) if overallcount <= 2000 break end for z in zrange id = mapdata[x, y, z] next if !id || id < 48 prioid = @priorities[id] next if prioid != 0 || GameData::TerrainTag.try_get(@terrain_tags[id]).shows_reflections if overallcount > 2000 xpos = (x * twidth) - @oxLayer0 ypos = (y * theight) - @oyLayer0 count = addTile(@autosprites, count, xpos, ypos, id) elsif id >= 384 # Tileset tiles temprect.set(((id - 384) & 7) * @tileSrcWidth, ((id - 384) >> 3) * @tileSrcHeight, @tileSrcWidth, @tileSrcHeight) xpos = (x * twidth) - @oxLayer0 ypos = (y * theight) - @oyLayer0 if @diffsizes TileWrap::stretchBlitWrappedPixels(Rect.new(xpos, ypos, twidth, theight), bitmap, @tileset, temprect) else TileWrap::blitWrappedPixels(xpos,ypos, bitmap, @tileset, temprect) end else # Autotiles tilebitmap = @autotileInfo[id] if !tilebitmap anim = autotileFrame(id) next if anim < 0 tilebitmap = Bitmap.new(twidth, theight) bltAutotile(tilebitmap, 0, 0, id, anim) @autotileInfo[id] = tilebitmap end xpos = (x * twidth) - @oxLayer0 ypos = (y * theight) - @oyLayer0 bitmap.blt(xpos, ypos, tilebitmap, tilerect) end end end end Graphics.frame_reset else if !@priorect || !@priorectautos || @priorect[0] != xStart || @priorect[1] != yStart || @priorect[2] != xEnd || @priorect[3] != yEnd @priorect = [xStart, yStart, xEnd, yEnd] @priorectautos = [] for y in yStart..yEnd for x in xStart..xEnd @priorectautos.push([x, y]) if @prioautotiles[[x, y]] end end end for tile in @priorectautos x = tile[0] y = tile[1] overallcount += 1 xpos = (x * twidth) - @oxLayer0 ypos = (y * theight) - @oyLayer0 bitmap.fill_rect(xpos, ypos, twidth, theight, trans) z = 0 while z < zsize id = mapdata[x, y, z] z += 1 next if !id || id < 48 prioid = @priorities[id] next if prioid != 0 || GameData::TerrainTag.try_get(@terrain_tags[id]).shows_reflections if id >= 384 # Tileset tiles temprect.set(((id - 384) & 7) * @tileSrcWidth, ((id - 384) >> 3) * @tileSrcHeight, @tileSrcWidth, @tileSrcHeight) if @diffsizes TileWrap::stretchBlitWrappedPixels(Rect.new(xpos, ypos, twidth, theight), bitmap, @tileset, temprect) else TileWrap::blitWrappedPixels(xpos,ypos, bitmap, @tileset, temprect) end else # Autotiles tilebitmap = @autotileInfo[id] if !tilebitmap anim = autotileFrame(id) next if anim < 0 tilebitmap = Bitmap.new(twidth, theight) bltAutotile(tilebitmap, 0, 0, id, anim) @autotileInfo[id] = tilebitmap end bitmap.blt(xpos, ypos, tilebitmap, tilerect) end end end Graphics.frame_reset if overallcount > 500 end @usedsprites = false return true end return false if @usedsprites @firsttime = false @oxLayer0 = @ox - (width >> 2) @oyLayer0 = @oy - (height >> 2) if @layer0clip @layer0.ox = 0 @layer0.oy = 0 @layer0.src_rect.set(width >> 2, height >> 2, @viewport.rect.width, @viewport.rect.height) else @layer0.ox = (width >> 2) @layer0.oy = (height >> 2) end @layer0.bitmap.clear @oxLayer0 = @oxLayer0.round @oyLayer0 = @oyLayer0.round xStart = @oxLayer0 / twidth xStart = 0 if xStart < 0 yStart = @oyLayer0 / theight yStart = 0 if yStart < 0 xEnd = xStart + (width / twidth) + 1 xEnd = xsize if xEnd >= xsize yEnd = yStart + (height / theight) + 1 yEnd = ysize if yEnd >= ysize if xStart < xEnd && yStart < yEnd tmprect = Rect.new(0, 0, 0, 0) yrange = yStart...yEnd xrange = xStart...xEnd for z in 0...zsize for y in yrange ypos = (y * theight) - @oyLayer0 for x in xrange xpos = (x * twidth) - @oxLayer0 id = mapdata[x, y, z] next if id == 0 || @priorities[id] != 0 || GameData::TerrainTag.try_get(@terrain_tags[id]).shows_reflections if id >= 384 # Tileset tiles tmprect.set(((id - 384) & 7) * @tileSrcWidth, ((id - 384) >> 3) * @tileSrcHeight, @tileSrcWidth, @tileSrcHeight) if @diffsizes TileWrap::stretchBlitWrappedPixels(Rect.new(xpos, ypos, twidth, theight), bitmap, @tileset, tmprect) else TileWrap::blitWrappedPixels(xpos,ypos, bitmap, @tileset, tmprect) end else # Autotiles frames = @framecount[id / 48 - 1] if frames <= 1 frame = 0 else frame = (Graphics.frame_count / Animated_Autotiles_Frames) % frames end bltAutotile(bitmap, xpos, ypos, id, frame) end end end end Graphics.frame_reset end return true end def refresh(autotiles = false) @oldOx = @ox @oldOy = @oy usesprites = false if @layer0 @layer0.visible = @visible usesprites = !refreshLayer0(autotiles) return if autotiles && !usesprites else usesprites = true end refreshFlashSprite xsize = @map_data.xsize ysize = @map_data.ysize minX = (@ox / @tileWidth) - 1 minX = minX.clamp(0, xsize - 1) maxX = ((@ox + @viewport.rect.width) / @tileWidth) + 1 maxX = maxX.clamp(0, xsize - 1) minY = (@oy / @tileHeight) - 1 minY = minY.clamp(0, ysize - 1) maxY = ((@oy + @viewport.rect.height) / @tileHeight) + 1 maxY = maxY.clamp(0, ysize - 1) count = 0 if minX < maxX && minY < maxY @usedsprites = usesprites || @usedsprites @layer0.visible = false if usesprites && @layer0 if !@priotilesrect || !@priotilesfast || @priotilesrect[0] != minX || @priotilesrect[1] != minY || @priotilesrect[2] != maxX || @priotilesrect[3] != maxY @priotilesrect = [minX, minY, maxX, maxY] @priotilesfast = [] if @fullyrefreshed for y in minY..maxY for x in minX..maxX next if !@priotiles[[x, y]] @priotiles[[x, y]].each { |tile| @priotilesfast.push([x, y, tile[0], tile[1]]) } end end else for z in 0...@map_data.zsize for y in minY..maxY for x in minX..maxX id = @map_data[x, y, z] next if id == 0 next if @priorities[id] == 0 && !GameData::TerrainTag.try_get(@terrain_tags[id]).shows_reflections @priotilesfast.push([x, y, z, id]) end end end end end for prio in @priotilesfast xpos = (prio[0] * @tileWidth) - @ox ypos = (prio[1] * @tileHeight) - @oy count = addTile(@tiles, count, xpos, ypos, prio[3]) end end if count < @tiles.length bigchange = (count <= (@tiles.length * 2 / 3)) && @tiles.length > 40 j = count len = @tiles.length while j < len sprite = @tiles[j] @tiles[j + 1] = -1 if bigchange sprite.dispose @tiles[j] = nil @tiles[j + 1] = nil elsif !@tiles[j].disposed? sprite.visible = false if sprite.visible end j += 2 end @tiles.compact! if bigchange end end def update if @haveGraphicsWH @graphicsWidth = Graphics.width @graphicsHeight = Graphics.height end # Update tone if @oldtone != @tone @layer0.tone = @tone @flash.tone = @tone if @flash for sprite in @autosprites sprite.tone = @tone if sprite.is_a?(Sprite) end for sprite in @tiles sprite.tone = @tone if sprite.is_a?(Sprite) end @oldtone = @tone.clone end # Update color if @oldcolor != @color @layer0.color = @color @flash.color = @color if @flash for sprite in @autosprites sprite.color = @color if sprite.is_a?(Sprite) end for sprite in @tiles sprite.color = @color if sprite.is_a?(Sprite) end @oldcolor = @color.clone end # Refresh anything that has changed if @autotiles.changed refresh_autotiles repaintAutotiles end refresh_flash if @flashChanged refresh_tileset if @tilesetChanged @flash.opacity = FlashOpacity[(Graphics.frame_count / 2) % 6] if @flash mustrefresh = (@oldOx != @ox || @oldOy != @oy || @tilesetChanged || @autotiles.changed) if @viewport.ox != @oldViewportOx || @viewport.oy != @oldViewportOy mustrefresh = true @oldViewportOx = @viewport.ox @oldViewportOy = @viewport.oy end refresh if mustrefresh if (Graphics.frame_count % Animated_Autotiles_Frames) == 0 || @nowshown repaintAutotiles refresh(true) end @nowshown = false @autotiles.changed = false @tilesetChanged = false end end