Problem passability ☆ with character over 32x32

Started by Ally, February 02, 2017, 05:38:17 pm

Previous topic - Next topic

Ally

Hi, I have a problem that apparently no one can solve...
I use character larger than 32x32...
When using tileset with ☆, this happens:

http://imgur.com/C5gb52B

And this, my tileset setting:
http://imgur.com/8rkvJ3a

and terrain tag:
http://imgur.com/57LZcES

The terrain tag is 6 beacuse I use this script:
##-----------------------------------------------------------------------------
#  Large Sprite ☆ Display Fix v1.3
#  Created by Neon Black at request of seita
#  v1.4 - 12.18.14 - Added position tuning
#  v1.3 - 1.12.14  - Viewport/position issue fixes
#  v1.1 - 8.18.13  - Fixed an odd lag issue
#  v1.0 - 8.17.13  - Main script completed
#  For both commercial and non-commercial use as long as credit is given to
#  Neon Black and any additional authors.  Licensed under Creative Commons
#  CC BY 4.0 - http://creativecommons.org/licenses/by/4.0/
##-----------------------------------------------------------------------------

##------
## By default, this script only affects the player.  To allow it to affect
## an event page as well, add a comment with the tag <large sprite> to the page
## of the event you would like to have affected by this.

class Sprite_Character < Sprite_Base
  ##------
  ## The ID of the terrain used to display the large character above ☆ tiles.
  ## If the player is below this tile (y position), the sprite will appear
  ## above all tiles and events from that y position up.  If the player is on
  ## the same tile or above (y position) the event will appear BELOW ☆ tiles
  ## from that position up.
  ##------
  UpperTerrain = 6
 
  ##------
  ## This value is the pixel tuning used to check the location.  This is
  ## because characters tagged with a '!' in their name are drawn lower than
  ## normal characters and are considered to be lower than these.  This causes
  ## the script to think they are on the tile below where they really are and
  ## draw them above tiles they should appear under.
  ##------
  Tuning = -1
 
  alias :cp_011214_update_bitmap :update_bitmap
  def update_bitmap(*args)
    if graphic_changed? && @set_upper_area_sprite
      @force_no_gfx_change = true
    else
      @force_no_gfx_change = false
    end
    cp_011214_update_bitmap(*args)
  end

  ## Alias the update method to add in the new graphic check.
  alias :cp_073013_update_pos :update_position
  def update_position(*args)
    cp_073013_update_pos(*args)
    check_encompassed_area if sprite_is_onscreen?
  end

  ## Alias the dispose to dispose the upper sprite.
  alias :cp_073013_dispose :dispose
  def dispose(*args)
    @upper_area_sprite.dispose if @upper_area_sprite
    cp_073013_dispose(*args)
  end

#~   ## Alias the graphic changed method to allow the sprite to revent to what it
#~   ## was during the last frame.  This allows the check to work again.
#~   alias :cp_073013_graphic_changed? :graphic_changed?
#~   def graphic_changed?(*args)
#~     cp_073013_graphic_changed?(*args) || @set_upper_area_sprite
#~   end

  ## Check if the sprite is onscreen.  Reduces redundant drawing.
  def sprite_is_onscreen?
    return false if @character.is_a?(Game_Vehicle) || @character.is_a?(Game_Follower)
    return false unless @character.is_a?(Game_Player) || @character.large_sprite
    return false if @character.screen_z >= 200
    top_left, bot_right = get_edge_corner_dis
    return false if top_left[0] > Graphics.width
    return false if top_left[1] > Graphics.height
    return false if bot_right[0] < 0
    return false if bot_right[1] < 0
    return true
  end

  ## Get the top left and bottom right positions.
  def get_edge_corner_dis
    top_left = [self.x - self.ox, self.y - self.oy]
    bot_right = [top_left[0] + self.width, top_left[1] + self.height]
    return [top_left, bot_right]
  end

  ## Long method that checks each position and draws the upper sprite.
  def check_encompassed_area
    if @set_upper_area_sprite && !@force_no_gfx_change
      old_src = self.src_rect.clone
      self.bitmap = @old_bitmap
      self.src_rect = old_src
    end
    @set_upper_area_sprite = false
    top_left, bot_right = get_edge_corner_dis
    last_x, last_y, copy_region = nil, nil, 0
    map_xd, map_yd = $game_map.display_x * 32, $game_map.display_y * 32
    total_height = (self.height + @character.jump_height).round
    self.width.times do |x|
      xp = map_xd.to_i + top_left[0] + x
      unless xp / 32 == last_x
        last_x = xp / 32
        last_y, copy_region = nil, 0
        total_height.times do |y|
          yp = map_yd.to_i + bot_right[1] + @character.jump_height - y + Tuning
          next if yp.to_i / 32 == last_y
          last_y = yp.to_i / 32
          if last_y == (@character.screen_y + @character.jump_height + Tuning +
                        map_yd).to_i / 32
            break if $game_map.terrain_tag(last_x, last_y) == UpperTerrain
            next
          end
          next if $game_map.terrain_tag(last_x, last_y) != UpperTerrain
          copy_region = [self.height, total_height - y + 1].min
          set_upper_sprite
          break
        end
      end
      next if copy_region == 0
      rect = Rect.new(src_rect.x + x, src_rect.y, 1, copy_region)
      @upper_area_sprite.bitmap.blt(x, 0, self.bitmap, rect)
      self.bitmap.clear_rect(rect)
    end
    if !@set_upper_area_sprite && @upper_area_sprite
      @upper_area_sprite.visible = false
    end
  end

  ## Creates the upper sprite that's a copy of the current sprite.
  def set_upper_sprite
    return if @set_upper_area_sprite
    @upper_area_sprite ||= Sprite.new
    @upper_area_sprite.bitmap = Bitmap.new(self.width, self.height)
    props = ["x", "y", "ox", "oy", "zoom_x", "zoom_y", "angle", "mirror",
             "bush_depth", "opacity", "blend_type", "color", "tone", "visible",
             "viewport"]
    props.each do |meth|
      @upper_area_sprite.method("#{meth}=").call(self.method(meth).call)
    end
    @upper_area_sprite.z = 200
    @set_upper_area_sprite = true
    @old_bitmap, old_src_rect = self.bitmap, self.src_rect.clone
    self.bitmap = Bitmap.new(@old_bitmap.width, @old_bitmap.height)
    self.bitmap.blt(0, 0, @old_bitmap, @old_bitmap.rect)
    self.src_rect = old_src_rect
  end
end

class Game_Event < Game_Character
  attr_reader :large_sprite

  alias :cp_081713_setup_page_settings :setup_page_settings
  def setup_page_settings(*args)
    cp_081713_setup_page_settings(*args)
    get_large_sprite_conditions
  end

  def get_large_sprite_conditions
    @large_sprite = false
    return if @list.nil? || @list.empty?
    @list.each do |line|
      next unless line.code == 108 || line.code == 408
      case line.parameters[0]
      when /<large sprite>/i
        @large_sprite = true
      end
    end
  end
end


But the problem is not solved...
I also tried to use this script:
=begin
#==============================================================================
# OZ OverTiles
#==============================================================================
Solves the problem when using character overworld sprites bigger than 32x32.

CHANGELOG
1.00 Initial release.
1.01 Performance increase, fixed an issue with the process_data method.
1.02 Fixed a bug with looping maps.

=end

class Game_CharacterBase
  def simple_screen_y
    ($game_map.adjust_y(@real_y) * 32) + 32
    #((@real_y - $game_map.display_y) * 32) + 32
  end
  def screen_z
    simple_screen_y.to_i + (@priority_type * 100)+100
  end
end

#==============================================================================
# ** Spriteset_Map
#------------------------------------------------------------------------------
#  This class brings together map screen sprites, tilemaps, etc. It's used
# within the Scene_Map class.
#==============================================================================

class Spriteset_Map
  #--------------------------------------------------------------------------
  # * Create Tilemap
  #--------------------------------------------------------------------------
  alias ozot_create_tilemap create_tilemap
  def create_tilemap
    ozot_create_tilemap
    process_mapdata
    @spr_over = Spriteset_OverMap.new(@over_data,@tilemap.bitmaps,@viewport1)
  end
#~   #--------------------------------------------------------------------------
#~   # * Create Airship Shadow Sprite (you can try and mess up with this, I don't want to :V
#~   #--------------------------------------------------------------------------
#~   def create_shadow
#~     @shadow_sprite = Sprite.new(@viewport1)
#~     @shadow_sprite.bitmap = Cache.system("Shadow")
#~     @shadow_sprite.ox = @shadow_sprite.bitmap.width / 2
#~     @shadow_sprite.oy = @shadow_sprite.bitmap.height
#~     @shadow_sprite.z = 180
#~   end
  #--------------------------------------------------------------------------
  # * Free
  #--------------------------------------------------------------------------
  alias ozot_dispose dispose
  def dispose
    ozot_dispose
    @spr_over.dispose
  end
  #--------------------------------------------------------------------------
  # * Update Tilemap
  #--------------------------------------------------------------------------
  alias ozot_update_tilemap update_tilemap
  def update_tilemap
    ozot_update_tilemap
    refresh_sprover if refresh_sprover?
    #@spr_over.refresh
    @spr_over.update
  end
 
  def refresh_sprover?
    return @gm_bck != $game_map.data
  end
  def refresh_sprover
    process_mapdata
    @spr_over.map_data = @over_data
    @spr_over.bitmaps = @tilemap.bitmaps
    @spr_over.refresh
  end
 
  def process_mapdata
    @gm_bck = $game_map.data
    @over_data = $game_map.data.dup
    @over_data.xsize.times{|x|
      @over_data.ysize.times{|y|
        flag = $game_map.tileset.flags[$game_map.data[x, y, 2]]
        # [?]: No effect on passage
        if (flag & 0x10 == 0) && ($game_map.data[x, y, 2] != 0)
          @over_data[x, y, 2] = 0
        #elsif (flag & 0x10 != 0) && ($game_map.data[x, y, 2] != 0)
        #  $game_map.data[x, y, 2] = 0
          #p @over_data[x, y, 2]
        end
      }
    }
  end
end

class Spriteset_OverMap
  attr_accessor :bitmaps
 
  def initialize(map_data,bitmaps,viewport)
    @map_data = map_data
    @bitmaps = bitmaps
    @vport = viewport
    #create sprites
    create_sprites
    refresh
  end
  def map_data=(n)
    @map_data = n
  end
  def vport=(n)
    @vport=n
    @sprites.each{|s| s.viewport=@vport}
  end
  def vport
    @vport
  end
 
  def create_sprites
    h_size = (Graphics.height/32) + 2
    @sprites = Array.new(h_size) {|i|
      s = Sprite.new(@vport); s.y = (i*32)
      s.bitmap = Bitmap.new(Graphics.width+64,32)
      s.ox = s.oy = 32 ; s.z = s.y.to_i+200
      s
    }
  end
 
  def update
    #update sprites, refresh if necessary
    update_sprites
    refresh if need_refresh?
  end
 
  def update_sprites
    dx= $game_map.display_x * 32
    dx= dx>0 ? dx%32 : dx%-32
    dy= $game_map.display_y * 32
    dy= dy>0 ? dy%32 : dy%-32
    @sprites.each_with_index{|s,i|
      s.x = -dx
      s.y = (i*32)-dy
      s.z = s.y.to_i+200
      s.update
    }
  end
 
  def refresh
    @actual_ox = ($game_map.display_x)
    @actual_oy = ($game_map.display_y)
   
    @map_data
    @sprites.size.times{|y|
      yy=@actual_oy+y-1
      yy=(yy%$game_map.height)
      next if (yy==-1)
      t = (Graphics.width+64)/32
      @sprites[y].bitmap.clear
      t.times{|x|
        xx = @actual_ox+x-1
        xx=(xx%$game_map.width)
        id = @map_data[xx,yy,2]
        next if id==nil
        #blit each tile
        i=id/256
        ii=id%256
        b=@bitmaps[i+5]
        off= ii>127 ? 256 : 0
        r=Rect.new( (ii%8*32)+off, ((ii/8)%16)*32, 32,32)
        @sprites[y].bitmap.blt(x*32,0,b,r)
      }
    }
  end
 
  def need_refresh?
    (@actual_ox != $game_map.display_x) || (@actual_oy != $game_map.display_y)
  end
 
  def dispose
    #dispose all sprites
    @sprites.each{|s| s.dispose; s=nil}
  end
end


Does anyone know how to fix it?

KK20

I removed Oz Overtiles and it works. Any reason you need that script to be compatible with it?

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!


KK20

In the demo that you gave me, you had both of these scripts enabled. If I removed Oz Overtiles from your project, the light post pole doesn't look like it is going through the player anymore.

So my question is why do you need Oz Overtiles?

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

Ally

Because without that script, the following happens:
http://imgur.com/mDP3ybx

Apparently, the bug occurs when there are two tile close...
In fact, the lamp is 4 tile, then from the second tile onwards, the error occurs...
I believe this is the problem...
http://imgur.com/g6PiDND

http://imgur.com/8rkvJ3a

If I leave the Oz Overtiles script, the error disappears, but the problem remains in the streetlight.

KK20

February 04, 2017, 12:51:01 am #5 Last Edit: February 04, 2017, 12:53:08 am by KK20
Alright, I get it now--basically want RMXP's tileset priorities. Reinforcing the reason why RMXP is superior in every way :V:

I feel Oz Overtiles is on the right track in getting it right, but it still has flaws. I'm not scripting this, but here's what I would do.

First off, you need to be able to assign a value to tiles to give them this priority attribute again, whether it be Terrain Tags or using the Notes (I'd prefer the latter since terrain tags are used excessively in other scripts already). When loading a tileset in game, you need to change the tileset's flags to remove the "star" property (which can be done using bitwise AND with 0xFFEF); this way, any tiles that were marked as a "star" will now be drawn as if it were on the floor.

There are different ways to do this next part, but they all involve creating new sprites in Spriteset_Map. One way is to do something like Oz did where it creates sprites that are 32 pixels tall and screen-size wide. But you need to make enough sprites to handle all the different priority values. You can also just make a bunch of 32x32 sprites and place them all over the map. These sprites will be drawing those priority/"star" tiles, giving you greater control on their z-values.

After all of that, it's just a matter of moving these sprites accordingly when the screen scrolls and changing their Z-values and tile graphic.

It's a bit of work, but compared to a full Tilemap Rewrite it's not nearly as difficult or time-consuming.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

Ally

Thank you ^^
I hope to find a one Scripter that can help me solve the problem!