Jump to content
Kirin

Saba Kan's Random Dungeon Generator 0.14

Recommended Posts

This script was not written by me! I simply translated it from Japanese and posted it here to share! Do NOT ask me for support, I'm not a scripter (I'll try, but most likely fail)!

 

Important bit out of the way, let's get cranking. The script today is:

 

Random Dungeon Generator

Version 0.14

by Saba Kan of

jzrma.jpg

 

プãƒãƒ¬ã‚¢ - PetitRare

 

Updated: 2012/01/21

 

Email asking for and being granted permission to translate and share:

 

kirinelf ã•ã‚“ã¸

 

ã‚ã–ã‚ã–メールã‚りãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚

日本語ã§ã™ã¿ã¾ã›ã‚“。

 

ã‚‚ã¡ã‚ん歓迎ã—ã¾ã™ã€ã©ã†ãžç¿»è¨³ãªã•ã£ã¦ãã ã•ã„。

 

> http://www.rpgmakervxace.net

> http://forums.rpgmakerweb.com

ãŠãŠï¼ã€€ã“れã‹ã‚‰ã‚‚ãƒã‚§ãƒƒã‚¯ã•ã›ã¦ã„ãŸã ãã¾ã™ï¼

 

2012年3月26日21:42 Kirin:

> ã“ã‚“ã«ã¡ã¯ã€

>

> 僕ã¯è‹±èªžã®RPGVXAã®ã‚³ãƒƒãƒ ãƒ‹ãƒ†ã‚£ã‹ã‚‰ã®kirinelf ã§ã™ã€‚キリンã§å‘¼ã³ã¾ã™ã“ã¨

> ã‚‚ã„ã„ã§ã™ã€‚ã‚ã®ã€‚。。日本語ãŒã‚ã¾ã‚Šä¸Šæ‰‹ã§ã‚ã‚りã¾ã›ã‚“ã§ã™ã‹ã‚‰ç”³ã—訳ã‚り ã¾ã›ã‚“。よã‚ã—ããŠã­ãŒã„ã—ã¾ã™ï¼

>

> 今回ã®ãƒ¡ãƒ¼ãƒ«ã®ç†ç”±ã¯RPGVXAã®RGSS3スクリプトを翻訳ã—ãŸã„ã“ã¨ã§ã™ã€‚貴方様 ã®ã‚¹ã‚¯ãƒªãƒ—トを英語ã«ç¿»è¨³ã—ã¦ã‚‚ã„ã„ã§ã—ょã†ã‹ï¼Ÿã‚‚ã¡ã‚ã‚“

> 貴方様ã®è¨˜è¼‰ã‚‚゠りã¾ã™ã€‚自分を書ã„ãŸäº‹ã‚‚絶対言ã„ã¾ã›ã‚“。

>

> 僕ã®ç›®çš„ã¯é¢ç™½ãã†ãªã‚¹ã‚¯ãƒªãƒ—トを翻訳ã—ã¦ã€ã“ã®ã‚µã‚¤ãƒˆã«ã»ã‹ã®è‹±èªžã®ãƒ¦ãƒ¼ã‚µ ã¨åˆ†ã‹ã¡åˆã„ã¾ã™ï¼š

>

> http://www.rpgmakervxace.net

> http://forums.rpgmakerweb.com

>

> ãã®ã‚µã‚¤ãƒˆã¯è‹±èªžRPGVXAã®ä¸€ç•ªå¤§ãã„コッムニティã§ã™ã€‚

>

> ãŠè¿”事を根気よãã¦å¾…ã¦ã„ã¾ã™ã€‚

>

> kirinelf (キリン) より。

 

 

The above, translated:

 

To kirinelf:

 

Thank you for going out of your way to send an email to me.

Sorry for this being in Japanese.

 

Please be my guest and translate them as you wish.

 

> http://www.rpgmakervxace.net

> http://forums.rpgmakerweb.com

 

Oh! I'll be sure to check these sites from now on too!

 

2012年3月26日21:42 Kirin:

> Hello,

>

> I am kirinelf from the English speaking RMVXA community. You can call me Kirin.

> I'm not very good at Japanese, so I apologize for that. Pleased to make your acquaintance!

>

> The purpose of this email is to ask about translating RMVXA's RGSS3 scripts. Is it alright

> to translate your scripts into English? Of course, you will be credited. I will not claim

> to have written any of your scripts.

>

> My aim is to translate scripts I find interesting and to share them with the rest of the

> English speaking community, namely at these sites:

>

> http://www.rpgmakervxace.net

> http://forums.rpgmakerweb.com

>

> These sites are the largest English RMVXA communities.

>

> I will await your reply patiently.

>

> From kirinelf (Kirin)

 

 

So what does this script do? Think Diablo. Random dungeon generation from within the game, dynamically. No two identical dungeons. Here're two screeenshots:

 

Setup within the editor:

rtok93.jpg

 

The result:

1074ayb.jpg

 

Features

 

  • Allows you to have dynamically generated dungeons in your game.
  • Allows you to have dynamically and randomly placed events in said dungeons.
  • Automatically places events tagged with a '*' in the name as enemies in the dungeon.
  • Or you can have random encounters instead.
  • Allows you to have events that show up permanently on the minimap once discovered, as well as events that have a hollow center to be more distinct.
  • ^ Both of those can be used together!
  • Has a sub script that makes events move after your player does, similar to dungeon crawler-roguelikes.

 

There really are quite a few features and setting up shenanigans that you need to be aware of, and for that reason I've included a How to Use text file I wrote up myself after experimenting with the demo that I hope will help you guys.

 

There are three scripts: A main script that handles the dungeon generation and everything within, and two sub scripts. The first sub script allows you to have events that only move/activate when the player moves, just like in a typical dungeon crawler rogue-like. The second subscript places a minimap smack bang in the middle of the screen.

 

Without further ado, here're the three scripts:

 

1. Main script

 

#==============================================================================
# â–  Dungeon Creation 6
#   @version 0.14 12/01/21 RGSS3
#   @author Saba Kan
#   @translator kirinelf
#------------------------------------------------------------------------------
#  
#==============================================================================
module Saba
 module Dungeon
   # Minumum block size (Hard to explain, try it out yourself)
   # Default: 7
   MINIMUM_RECT_SIZE = 7

   # Minimum room size.
   # Default: 3
   MINIMUM_ROOM_SIZE = 3

   # Margin between rooms and 'blocks'. 
   # Default: 2
   MARGIN_BETWEEN_RECT_ROOM = 2

   # The percentage of corridors made. (1/n)
   # Works best with lower values. 
   # Default: 35
   MORE_COUPLE_RATE = 35

   # Variable that stores enemy amount.
   ENEMY_COUNT_VARIABLE = 1

   # Debug Mode
   # ・Always show enemies on minimap.
   DEBUG_MODE = false
 end
end

#=========================================================================
# Do not edit anything under this line unless you know what you're doing!
#=========================================================================

#==============================================================================
# â–  Dungeon_Rect
#------------------------------------------------------------------------------
#  ダンジョンを区切ã£ãŸé ˜åŸŸã‚’表ã—ã¾ã™ã€‚
#ã€€å„ Dungeon_Rect ã«ä¸€ã¤ã¥ã¤ Room ãŒå­˜åœ¨ã—ã¾ã™ã€‚
#==============================================================================
class Dungeon_Rect
 #--------------------------------------------------------------------------
 # ◠公開インスタンス変数
 #--------------------------------------------------------------------------
 attr_accessor :lx
 attr_accessor :ly
 attr_accessor :hx
 attr_accessor :hy
 attr_accessor :room
 attr_accessor :done_split_v
 attr_accessor :done_split_h
 #--------------------------------------------------------------------------
 # â— ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆåˆæœŸåŒ–
 #--------------------------------------------------------------------------
 def initialize(lx, ly, hx, hy)
   self.lx = lx
   self.ly = ly
   self.hx = hx
   self.hy = hy
   self.done_split_v = false
   self.done_split_h = false
 end
end

#==============================================================================
# â–  Room
#------------------------------------------------------------------------------
#  部屋ã§ã™ã€‚
#==============================================================================
class Room
 #--------------------------------------------------------------------------
 # ◠公開インスタンス変数
 #--------------------------------------------------------------------------
 attr_accessor :lx
 attr_accessor :ly
 attr_accessor :hx
 attr_accessor :hy
 attr_accessor :mapping
 attr_reader :width
 attr_reader :height
 attr_reader :couple_areas  # 通路ã«é¢ã—ã¦ã„ã‚‹[x, y]ã®ãƒªã‚¹ãƒˆ
 #--------------------------------------------------------------------------
 # â— ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆåˆæœŸåŒ–
 #--------------------------------------------------------------------------
 def initialize(lx, ly, hx, hy)
   self.lx = lx
   self.ly = ly
   self.hx = hx
   self.hy = hy
   @width = hx - lx
   @height = hy - ly
   @events = {}
   @couple_areas = []
   @mapping = false
 end
 #--------------------------------------------------------------------------
 # ◠イベントé…ç½®å¯èƒ½æ•°æ®‹ã‚Šã‚’å–å¾—
 #--------------------------------------------------------------------------
 def remain
   return (hx - lx) * (hy - ly) -  @events.size - @couple_areas.size
 end
 #--------------------------------------------------------------------------
 # ◠指定ã®ã‚¤ãƒ™ãƒ³ãƒˆã‚’ã“ã®éƒ¨å±‹ã®ãƒ©ãƒ³ãƒ€ãƒ ãªå ´æ‰€ã«é…ç½®
 #--------------------------------------------------------------------------
 def put_to_random_place(event)
   begin
     key = [rand(hx - lx) + lx, rand(hy - ly) + ly]
   end while @events[key] != nil || @couple_areas.include?(key)
   @events[key] = event
   event.moveto(key[0], key[1])
 end
 #--------------------------------------------------------------------------
 # ◠指定ã®åº§æ¨™ã‚’å«ã‚“ã§ã„ã‚‹ã‹ã‚’å–å¾—
 #--------------------------------------------------------------------------
 def contains(x, y)
   return lx <= x && x < hx && ly <= y && y < hy
 end
 #--------------------------------------------------------------------------
 # ◠指定ã®åº§æ¨™ã‚’明るãã™ã‚‹ã‹ã‚’å–å¾—
 #--------------------------------------------------------------------------
 def right_area?(x, y)
   return lx-1 <= x && x < hx+1 && ly-1 <= y && y < hy+1
 end
end




#==============================================================================
# â–  Couple
#------------------------------------------------------------------------------
#  通路ã§ã™ã€‚
#==============================================================================
class Couple
 #--------------------------------------------------------------------------
 # ◠公開インスタンス変数
 #--------------------------------------------------------------------------
 attr_accessor :rect0
 attr_accessor :rect1
 attr_accessor :direction
end

class Game_Map
 attr_reader :map
 attr_accessor :new_events
 #--------------------------------------------------------------------------
 # ◠定数
 #--------------------------------------------------------------------------
 COUPLE_VERTICAL = 0
 COUPLE_HORIZONAL = 1
 #--------------------------------------------------------------------------
 # ◠セットアップ
 #     map_id : マップ ID
 #--------------------------------------------------------------------------
 alias saba_setup setup
 def setup(map_id)
   saba_setup(map_id)
   @random_dungeon = nil
   make_random_dungeon if dungeon?
 end
 #--------------------------------------------------------------------------
 # ◠ランダムダンジョンを作æˆ
 #--------------------------------------------------------------------------
 def make_random_dungeon
   @rect_list = []
   @room_list = []
   @couple_list = []
   @map = load_data(sprintf("Data/Map%03d.rvdata2", @map_id))
   @floor_chip_id = @map.data[0, 0, 0]
   @floor_chip_id1 = @map.data[1, 0, 0]
   @edge_chip_id = @map.data[0, 1, 0]
   @wall_chip_id = @map.data[0, 2, 0]
   @blank_chip_id = @map.data[0, 4, 0]
   @object_chip_id0 = @map.data[0, 3, 0]
   @object_chip_id1 = @map.data[0, 3, 1]
   @object_chip_id2 = @map.data[0, 3, 2]
   make_rect
   make_room
   make_couple_more

   @init_phase = true

   put_blank_tiles
   put_couple_tiles
   put_room_tiles
   put_shadow
   put_wall_tiles
   put_edge_tiles

   setup_dungeon_events
   @random_data = @map.data
   @last_moving = false

 end
 #--------------------------------------------------------------------------
 # ◠区切りを作æˆ
 #--------------------------------------------------------------------------
 def make_rect
   split_rect(add_rect(0, 1, @map.width, @map.height))
 end
 #--------------------------------------------------------------------------
 # ◠指定㮠DungeonRect を区切る
 #--------------------------------------------------------------------------
 def split_rect(parent)
   if (parent.hy - parent.ly <= Saba::Dungeon::MINIMUM_RECT_SIZE * 2) 
     parent.done_split_v = true
   end
   if (parent.hx - parent.lx <= Saba::Dungeon::MINIMUM_RECT_SIZE * 2) 
     parent.done_split_h = true;
   end
   if ((parent.done_split_v) &&  (parent.done_split_h))
     return
   end
   child = add_rect(parent.lx, parent.ly, parent.hx, parent.hy)
   unless parent.done_split_v
     split_coord_y = random_range(parent.ly + Saba::Dungeon::MINIMUM_RECT_SIZE, parent.hy - Saba::Dungeon::MINIMUM_RECT_SIZE)
     parent.hy = split_coord_y
     child.ly = split_coord_y
     parent.done_split_v = true
     child.done_split_v = true
     add_couple(COUPLE_VERTICAL, parent, child)
     split_rect(parent)
     split_rect(child)
   else
     split_coord_x = random_range(parent.lx + Saba::Dungeon::MINIMUM_RECT_SIZE, parent.hx - Saba::Dungeon::MINIMUM_RECT_SIZE)
     parent.hx = split_coord_x
     child.lx = split_coord_x
     parent.done_split_h = true
     child.done_split_h = true
     add_couple(COUPLE_HORIZONAL, parent, child)
     split_rect(parent)
     split_rect(child)
   end
 end
 #--------------------------------------------------------------------------
 # â— ã•らã«é“を作æˆ
 #--------------------------------------------------------------------------
 def make_couple_more
   rectmap = {}
   for rect in @rect_list
     for i in rect.lx...rect.hx
       for j in rect.ly...rect.hy
         rectmap[[i, j]] = rect
       end
     end
   end

   for i in 0..(@map.width-2)
     for j in 1..(@map.height-2)
       if rectmap[[i, j]] != rectmap[[i, j + 1]]
         if rand(Saba::Dungeon::MORE_COUPLE_RATE) == 0
           add_couple(COUPLE_VERTICAL, rectmap[[i,j]], rectmap[[i, j + 1]])
         end
       end
       if rectmap[[i, j]] != rectmap[[i + 1, j]]
         if rand(Saba::Dungeon::MORE_COUPLE_RATE) == 0
           add_couple(COUPLE_HORIZONAL, rectmap[[i, j]], rectmap[[i + 1, j]])
         end
       end
     end
   end
 end
 #--------------------------------------------------------------------------
 # ◠ランダムダンジョンã‹ï¼Ÿ
 #--------------------------------------------------------------------------
 def dungeon?
   if @random_dungeon != nil
     return @random_dungeon
   end
   unless @map_infos
     @map_infos = load_data("Data/MapInfos.rvdata2")
   end
   @random_dungeon = @map_infos[@map_id].name.include?("@")
   return @random_dungeon
 end
 #--------------------------------------------------------------------------
 # ◠指定ã®åŒºé–“ã®ä¸­ã§ãƒ©ãƒ³ãƒ€ãƒ ãªå€¤ã‚’å–å¾—
 #--------------------------------------------------------------------------
 def random_range(b, e)
   return (rand(e -  + .to_i
 end
 #--------------------------------------------------------------------------
 # â— DungeonRect を作æˆã—ã¦è¿½åŠ 
 #--------------------------------------------------------------------------
 def add_rect(lx, ly, hx, hy)
   rect = Dungeon_Rect.new(lx, ly, hx, hy)
   @rect_list.push(rect)
   return rect
 end
 #--------------------------------------------------------------------------
 # â— Room を作æˆã—ã¦è¿½åŠ 
 #--------------------------------------------------------------------------
 def add_room(lx, ly, hx, hy)
   room = Room.new(lx, ly, hx, hy)
   @room_list.push(room)
   return room
 end
 #--------------------------------------------------------------------------
 # ◠部屋を作æˆ
 #--------------------------------------------------------------------------
 def make_room
   for rect in @rect_list
     w = random_range(Saba::Dungeon::MINIMUM_ROOM_SIZE, rect.hx - rect.lx - (Saba::Dungeon::MARGIN_BETWEEN_RECT_ROOM * 2) + 1);
     h = random_range(Saba::Dungeon::MINIMUM_ROOM_SIZE, rect.hy - rect.ly - (Saba::Dungeon::MARGIN_BETWEEN_RECT_ROOM * 2) + 1);
     x = random_range(rect.lx + Saba::Dungeon::MARGIN_BETWEEN_RECT_ROOM, rect.hx - Saba::Dungeon::MARGIN_BETWEEN_RECT_ROOM - w + 1);
     y = random_range(rect.ly + Saba::Dungeon::MARGIN_BETWEEN_RECT_ROOM, rect.hy - Saba::Dungeon::MARGIN_BETWEEN_RECT_ROOM - h + 1);
     rect.room = add_room(x, y, x + w, y + h);
   end
 end
 #--------------------------------------------------------------------------
 # ◠通路 を作æˆã—ã¦è¿½åŠ 
 #--------------------------------------------------------------------------
 def add_couple(direction, rect0, rect1)
   @couple_list.each {|c|
     if (c.rect0 == rect0 && c.rect1 == rect1) ||
        (c.rect0 == rect1 && c.rect1 == rect0)
       # é‡è¤‡ã¯ã¤ãらãªã„
       return
     end
   }
   couple = Couple.new
   couple.direction = direction
   couple.rect0 = rect0
   couple.rect1 = rect1
   @couple_list.push(couple)
   return couple
 end
 #--------------------------------------------------------------------------
 # ◠空ããƒãƒƒãƒ—ã‚’é…ç½®
 #--------------------------------------------------------------------------
 def put_blank_tiles
   for x in 0..@map.width
     for y in 0..@map.height
       @map.data[x, y, 0] = @blank_chip_id
       @map.data[x, y, 1] = 0
       @map.data[x, y, 2] = 0
     end
   end
 end
 #--------------------------------------------------------------------------
 # ◠床ãƒãƒƒãƒ—ã‚’é…ç½®
 #--------------------------------------------------------------------------
 def put_room_tiles
   for rect in @rect_list
     room = rect.room
     (room.hx - room.lx).times do |x|
       (room.hy - room.ly).times do |y|
         put_floor_tile(x + room.lx, y + room.ly)
       end
     end
   end
 end
 def put_floor_tile(x, y)
   if @floor_chip_id1 > 0 && rand(10) == 0
     @map.data[x, y, 0] = @floor_chip_id1
   else
     @map.data[x, y, 0] = @floor_chip_id
   end
 end
 #--------------------------------------------------------------------------
 # ◠通路ãƒãƒƒãƒ—ã‚’é…ç½®
 #--------------------------------------------------------------------------
 def put_couple_tiles
   for couple in @couple_list
     case couple.direction
     when COUPLE_HORIZONAL then
       unless couple.rect0.hx == couple.rect1.lx 
         p "Errorx:" + couple.rect0.hx.to_s + couple.rect1.lx .to_s
         next
       end
       c0x = couple.rect0.hx
       c0y = random_range(couple.rect0.room.ly + 1, couple.rect0.room.hy)
       c1x = couple.rect1.lx
       c1y = random_range(couple.rect1.room.ly + 1, couple.rect1.room.hy)
       line(c0x, c0y, c1x, c1y);
       line(couple.rect0.room.hx, c0y, c0x, c0y)
       line(couple.rect1.room.lx, c1y, c1x, c1y)
       couple.rect0.room.couple_areas.push([couple.rect0.room.hx-1, c0y])
       couple.rect1.room.couple_areas.push([couple.rect1.room.lx, c1y])
     when COUPLE_VERTICAL then
       unless couple.rect0.hy == couple.rect1.ly
         p "Errory:" + couple.rect0.hy.to_s + " " + couple.rect1.ly .to_s
         next
       end
       c0x = random_range(couple.rect0.room.lx + 1, couple.rect0.room.hx)
       c0y = couple.rect0.hy
       c1x = random_range(couple.rect1.room.lx + 1, couple.rect1.room.hx)
       c1y = couple.rect1.ly
       line(c0x, c0y, c1x, c1y)
       line(c0x, couple.rect0.room.hy, c0x, c0y)
       line(c1x, couple.rect1.room.ly, c1x, c1y)
       couple.rect0.room.couple_areas.push([c0x, couple.rect0.room.hy-1])
       couple.rect1.room.couple_areas.push([c1x, couple.rect1.room.ly])
     end
   end
 end
 #--------------------------------------------------------------------------
 # ◠指定ã®åº§æ¨™é–“ã§åºŠã‚’é…ç½®
 #--------------------------------------------------------------------------
 def line(x0, y0, x1, y1)
   min_x = [x0, x1].min
   max_x = [x0, x1].max
   min_y = [y0, y1].min
   max_y = [y0, y1].max
   if ((x0 <= x1) && (y0 >= y1))
     for i in min_x..max_x
       put_floor_tile(i, max_y)
     end
     for j in min_y..max_y
       put_floor_tile(max_x, j)
     end
   elsif ((x0 > x1) && (y0 > y1))
     for i in min_x..max_x
       put_floor_tile(i, min_y)
     end
     for j in min_y..max_y
       put_floor_tile(max_x, j)
     end
   elsif ((x0 > x1) && (y0 <= y1))
     for i in min_x..max_x
       put_floor_tile(i, min_y)
     end
     for j in min_y..max_y
       put_floor_tile(max_x, j)
     end
   elsif ((x0 <= x1) && (y0 < y1))
     for i in min_x..max_x
       put_floor_tile(i, max_y)
     end
     for j in min_y..max_y
       put_floor_tile(min_x, j)
     end
   end
 end
 #--------------------------------------------------------------------------
 # â— å£ãƒãƒƒãƒ—ã‚’é…ç½®
 #--------------------------------------------------------------------------
 def put_wall_tiles
   for y in (1..@map.height).to_a.reverse
     for x in 0..@map.width
       next unless  floor?(x, y)
       next if floor?(x, y-1)
       @map.data[x, y-1, 0] = @wall_chip_id + 15
     end
   end

   for y in (1..@map.height).to_a.reverse
     for x in 0..@map.width
       tile = @map.data[x, y, 0]
       next unless tile ==  @wall_chip_id + 15
       if floor?(x, y-1)
         put_object_tile(x, y)
         next
       end
       if floor?(x-1, y) || blank?(x-1, y)
         if floor?(x+1, y) || blank?(x+1, y)
           @map.data[x, y, 0] = @wall_chip_id + 15
         else
           @map.data[x, y, 0] = @wall_chip_id + 11
         end
       else
         if floor?(x+1, y) || blank?(x+1, y)
           @map.data[x, y, 0] = @wall_chip_id + 14
         else
           @map.data[x, y, 0] = @wall_chip_id + 10
         end
       end
     end
   end
 end
 #--------------------------------------------------------------------------
 # ◠障害物ãƒãƒƒãƒ—ã‚’é…ç½®
 #--------------------------------------------------------------------------
 def put_object_tile(x, y)
   @map.data[x, y, 0] = @object_chip_id0
   @map.data[x, y, 1] = @object_chip_id1
   @map.data[x, y, 2] = @object_chip_id2
 end
 #--------------------------------------------------------------------------
 # ◠境界ãƒãƒƒãƒ—ã‚’é…ç½®
 #--------------------------------------------------------------------------
 def put_edge_tiles
   for y in (1..@map.height).to_a.reverse
     for x in 0..@map.width
       tile = @map.data[x, y, 0]
       next if inner?(x, y)
       if inner?(x, y-1)
         if inner?(x, y+1)
           if inner?(x-1, y)
             if inner?(x+1, y)
               @map.data[x, y, 0] = @edge_chip_id + 46
             else
               @map.data[x, y, 0] = @edge_chip_id + 43
             end
           else
             if inner?(x+1, y)
               @map.data[x, y, 0] = @edge_chip_id + 45
             else
               @map.data[x, y, 0] = @edge_chip_id + 33
             end
           end
         else
           if inner?(x-1, y)
             if inner?(x+1, y)
               @map.data[x, y, 0] = @edge_chip_id + 42
             else
               @map.data[x, y, 0] = @edge_chip_id + 34
             end
           else
             if inner?(x+1, y)
               @map.data[x, y, 0] = @edge_chip_id + 36
             else
               @map.data[x, y, 0] = @edge_chip_id + 20
             end
           end
         end
       else
         if inner?(x, y+1)
           if inner?(x-1, y)
             if inner?(x+1, y)
               @map.data[x, y, 0] = @edge_chip_id + 44
             else
               @map.data[x, y, 0] = @edge_chip_id + 40
             end
           else
             if inner?(x+1, y)
               @map.data[x, y, 0] = @edge_chip_id + 38
             else
               @map.data[x, y, 0] = @edge_chip_id + 28
             end
           end
         else
           if inner?(x-1, y)
             if inner?(x+1, y)
               @map.data[x, y, 0] = @edge_chip_id + 32
             else
               @map.data[x, y, 0] = @edge_chip_id + 16
             end
           else
             if inner?(x+1, y)
               @map.data[x, y, 0] = @edge_chip_id + 24
             else
               if inner?(x+1, y+1) || inner?(x+1, y-1) ||
                  inner?(x-1, y-1) || inner?(x-1, y+1)
                 @map.data[x, y, 0] = @edge_chip_id
               else
                 @map.data[x, y, 0] = @blank_chip_id
               end
             end
           end
         end
       end
     end
   end
 end
 #--------------------------------------------------------------------------
 # ◠影タイルを置ãã¾ã™
 #--------------------------------------------------------------------------
 def put_shadow
   for y in 0..@map.height
     for x in 0..@map.width
       next unless floor?(x, y)
       next if floor?(x-1, y-1)
       next unless blank?(x-1, y)
       @map.data[x, y, 3] = 5
     end
   end
 end
 #--------------------------------------------------------------------------
 # ◠指定ã®åº§æ¨™ãŒå¢ƒç•Œã®å†…å´ã‹ã©ã†ã‹
 #--------------------------------------------------------------------------
 def inner?(x, y)
   return floor?(x, y) || wall?(x, y) || object?(x, y)
 end
 #--------------------------------------------------------------------------
 # ◠指定ã®åº§æ¨™ãŒåºŠã‹ã©ã†ã‹
 #--------------------------------------------------------------------------
 def floor?(x, y)
   return false if @map.data[x, y, 2] == @object_chip_id2
   return true if @floor_chip_id1 && @map.data[x, y, 0] == @floor_chip_id1
   return @map.data[x, y, 0] == @floor_chip_id
 end
 #--------------------------------------------------------------------------
 # ◠指定ã®åº§æ¨™ãŒã‚«ãƒ©ã‹ã©ã†ã‹
 #--------------------------------------------------------------------------
 def blank?(x, y)
   return @map.data[x, y, 0] == @blank_chip_id
 end
 #--------------------------------------------------------------------------
 # ◠指定ã®åº§æ¨™ãŒéšœå®³ç‰©ã‹ã©ã†ã‹
 #--------------------------------------------------------------------------
 def object?(x, y)
   return @map.data[x, y, 0] == @object_chip_id0
 end
 #--------------------------------------------------------------------------
 # ◠指定ã®åº§æ¨™ãŒå£ã‹ã©ã†ã‹
 #--------------------------------------------------------------------------
 def wall?(x, y)
   tile = @map.data[x, y, 0]
   return false if tile == nil || tile == 0
   return tile >= @wall_chip_id && tile <= @wall_chip_id + 15
 end
 #--------------------------------------------------------------------------
 # ◠プレイヤーをランダムãªä½ç½®ã«é…ç½®
 #--------------------------------------------------------------------------
 def setup_player_initial_position
   put_to_random_place($game_player) unless floor?($game_player.x, $game_player.y)
 end
 #--------------------------------------------------------------------------
 # ◠ダンジョンã®ç‰¹æ®Šãªã‚¤ãƒ™ãƒ³ãƒˆã‚’ランダムãªå ´æ‰€ã«é…ç½®ã™ã‚‹
 #--------------------------------------------------------------------------
 def setup_dungeon_events
   @next_enemy_event_id = 10000
   @enemy_events = []

   for event in @events.values
     if event.event.name.include?("*")
       @enemy_events.push(event.event)
       self.events[event.id].erase
     else
       put_to_random_place(event)
     end
   end
   setup_enemy
 end
 #--------------------------------------------------------------------------
 # ◠敵イベントã®åˆæœŸè¨­å®š
 #--------------------------------------------------------------------------
 def setup_enemy
   $game_variables[saba::Dungeon::ENEMY_COUNT_VARIABLE] = 0
   return if @enemy_events.count == 0
   @map.encounter_step.times do |i|
     add_random_enemy
   end
 end
 #--------------------------------------------------------------------------
 # â— ãƒ©ãƒ³ãƒ€ãƒ ãªæ•µã‚¤ãƒ™ãƒ³ãƒˆã‚’ランダムãªå ´æ‰€ã«é…ç½®ã™ã‚‹
 #--------------------------------------------------------------------------
 def add_random_enemy
   add_enemy(rand(@enemy_events.count))
 end
 #--------------------------------------------------------------------------
 # â— æŒ‡å®šã®æ•µã‚¤ãƒ™ãƒ³ãƒˆã‚’複製ã—ã¦ãƒ©ãƒ³ãƒ€ãƒ ãªå ´æ‰€ã«é…ç½®ã™ã‚‹
 #--------------------------------------------------------------------------
 def add_enemy(event_id)
   enemy_event = @enemy_events[event_id]
   event = Game_Event.new(@map_id, enemy_event)

   # イベントã®ãƒ«ãƒ¼ãƒ—内ã§ã¯æ–°ã—ã„イベントを追加ã§ããªã„ã®ã§ã€
   # 一旦別ã®å ´æ‰€ã«æ ¼ç´
   @new_events = {} unless @new_events
   @new_events[@next_enemy_event_id] = event

   event.event_id = @next_enemy_event_id
   @next_enemy_event_id += 1
   $game_variables[saba::Dungeon::ENEMY_COUNT_VARIABLE] += 1
 end
 alias saba_randomdungeon_update_events update_events
 def update_events
   saba_randomdungeon_update_events
   if @new_events
     for key in @new_events.keys
       @events[key] = @new_events[key]
       put_to_random_place(@events[key])
       $game_minimap.add_event(@events[key]) if $game_minimap
     end
   end
   @init_phase = false
 end
 #--------------------------------------------------------------------------
 # ◠指定ã®ã‚¤ãƒ™ãƒ³ãƒˆã‚’ランダムãªå ´æ‰€ã«é…ç½®ã™ã‚‹
 #--------------------------------------------------------------------------
 def put_to_random_place(event)
   if @init_phase
     room_list = @room_list.select {|room| room.remain != 0 }
   else 
     room_list = @room_list.select {|room| room.remain != 0 && room != $game_player.room }
   end
   room = room_list[rand(room_list.size)]
   room.put_to_random_place(event)
 end

 #--------------------------------------------------------------------------
 # ◠起動中ã®ãƒžãƒƒãƒ—イベントを検出ï¼ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—
 #--------------------------------------------------------------------------
 def setup_starting_map_event
   event = @events.values.find {|event| event.starting }
   event.clear_starting_flag if event
   @interpreter.setup(event.list, event.event_id) if event
   event
 end
 def room(x, y)
   for rect in @rect_list
     if rect.room.contains(x, y)
       return rect.room
     end
   end
   return nil
 end

end


class Spriteset_Map
 #--------------------------------------------------------------------------
 # â— ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆåˆæœŸåŒ–
 #--------------------------------------------------------------------------
 alias saba_dungeon_initialize initialize
 def initialize
   saba_dungeon_initialize
   @dark_sprite = Sprite_Dark.new(@viewport_dark)
   update_dark_sprite_visible
 end
 #--------------------------------------------------------------------------
 # ◠ビューãƒãƒ¼ãƒˆã®ä½œæˆ
 #--------------------------------------------------------------------------
 alias saba_dungeon_create_viewports create_viewports
 def create_viewports
   saba_dungeon_create_viewports
   @viewport_dark = Viewport.new
 end
 #--------------------------------------------------------------------------
 # ◠フレーム更新
 #--------------------------------------------------------------------------
 alias saba_dungeon_update update
 def update
   if $game_map.new_events
     $game_map.new_events.values.each do |event|
       @character_sprites.push(Sprite_Character.new(@viewport1, event))
     end
     $game_map.new_events = nil
   end
   saba_dungeon_update
   update_dark_sprite_visible
 end
 #--------------------------------------------------------------------------
 # ◠暗闇スプライトã®è¡¨ç¤ºæ›´æ–°
 #--------------------------------------------------------------------------
 def update_dark_sprite_visible
   if @dark_sprite
     if $game_map.dungeon?
       @dark_sprite.visible = true
       @dark_sprite.update
     else
       @dark_sprite.visible = false
     end
   end
 end
 #--------------------------------------------------------------------------
 # ◠解放
 #--------------------------------------------------------------------------
 alias saba_dungeon_dispose dispose
 def dispose
   @dark_sprite.dispose if @dark_sprite
   saba_dungeon_dispose
 end
 #--------------------------------------------------------------------------
 # ◠ビューãƒãƒ¼ãƒˆã®è§£æ”¾
 #--------------------------------------------------------------------------
 alias saba_dungeon_dispose_viewports dispose_viewports
 def dispose_viewports
   saba_dungeon_dispose_viewports
   @viewport_dark.dispose
 end
 #--------------------------------------------------------------------------
 # ◠キャラクタースプライトã®ä½œæˆ
 #--------------------------------------------------------------------------
 alias saba_dungeon_create_characters create_characters
 def create_characters
   saba_dungeon_create_characters
   $game_map.new_events = nil
 end
end

class Sprite_Character
 alias saba_dangeon_update update
 def update
   saba_dangeon_update
   return unless $game_map.dungeon?
   if @character.is_a?(Game_Event)
#~       if @static == nil
#~         @static = @character.name.to_i > 1000
#~       end
#~       if @static
#~         self.visible = true
       self.visible = false
     if $game_player.room
       self.visible = $game_player.room.contains(@character.x, @character.y)
     end

     case $game_player.distance(@character) 
       when 1;
         self.visible = true
         @last_visible = self.visible
       when 2;
         self.visible |= @last_visible
         @last_visible = false
     end

   end
 end
end

class Sprite_Dark < Sprite_Base
 def initialize(viewport)
   super(viewport)
   self.bitmap = Bitmap.new(Graphics.width+32*32, Graphics.height+32*32)
   refresh
   update
 end
 def update
   super

   if @last_room != $game_player.room
     refresh
     @last_room = $game_player.room
   end
   if @last_room
     self.viewport.ox = -@start_x + $game_map.display_x*32
     self.viewport.oy = -@start_y + $game_map.display_y*32
     if (self.viewport.ox - self.bitmap.width / 2 + Graphics.width / 2).abs > Graphics.width / 2 ||
        (self.viewport.oy - self.bitmap.height / 2 + Graphics.height / 2).abs > Graphics.height / 2 
       refresh
     end
     self.viewport.ox = -@start_x + $game_map.display_x*32
     self.viewport.oy = -@start_y + $game_map.display_y*32

   else
     self.viewport.ox = -$game_player.screen_x + self.bitmap.width / 2 
     self.viewport.oy = -$game_player.screen_y + self.bitmap.height / 2 + 16
   end
 end
 def refresh
   self.bitmap.clear
   self.bitmap.fill_rect(0, 0, self.bitmap.width, self.bitmap.height, Color.new(0, 0, 0, 100))
   room = $game_player.room
   if room == nil
     rect = Rect.new
     rect.x = self.bitmap.width / 2 - 48
     rect.y = self.bitmap.height / 2 - 45
     rect.width = 96
     rect.height = 96
     self.bitmap.clear_rect(rect)

     edge = Cache.system("dark_edge2")
     self.bitmap.blt(rect.x, rect.y, edge, edge.rect)
   else
     rect = Rect.new
     rect.x = self.bitmap.width / 2 - ($game_player.x - room.lx) * 32
     rect.y = self.bitmap.height / 2 - ($game_player.y - room.ly) * 32
     rect.width = (room.hx - room.lx+2) * 32
     rect.height = (room.hy - room.ly+2) * 32
     self.bitmap.clear_rect(rect)
     @start_x = $game_map.display_x*32 - self.bitmap.width / 2 + ($game_player.x - $game_map.display_x - 1)*32
     @start_y = $game_map.display_y*32 - self.bitmap.height / 2 + ($game_player.y - $game_map.display_y - 1)*32

     edge = Cache.system("dark_edge")
     self.bitmap.blt(rect.x, rect.y, edge, Rect.new(0, 0, 32, 32))
     self.bitmap.blt(rect.x+rect.width-32, rect.y, edge, Rect.new(32, 0, 32, 32))
     self.bitmap.blt(rect.x, rect.y+rect.height-32, edge, Rect.new(0, 32, 32, 32))
     self.bitmap.blt(rect.x+rect.width-32, rect.y+rect.height-32, edge, Rect.new(32, 32, 32, 32))
   end
 end
end
class Game_Event
 attr_reader :event
 attr_accessor :event_id
 attr_reader   :erased
 def name
   @event.name
 end
 alias saba_dungeon_erase erase
 def erase
   saba_dungeon_erase
   return unless enemy?
   $game_variables[saba::Dungeon::ENEMY_COUNT_VARIABLE] -= 1
 end
 def enemy?
   return name.include?("*")
 end
end

class Game_Player
 #--------------------------------------------------------------------------
 # ◠指定ä½ç½®ã«ç§»å‹•
 #--------------------------------------------------------------------------
 alias saba_dungeon_moveto moveto
 def moveto(x, y)
   saba_dungeon_moveto(x, y)
   $game_map.setup_player_initial_position if $game_map.dungeon?
 end
 def distance(event)
   min = $game_player.distance_xy_from(event.x, event.y)
   return min unless $game_player.followers.visible
   $game_player.followers.each do |character|
     dist = character.distance_xy_from(event.x, event.y)
     if dist < min
       min = dist
     end
   end
   return min
 end
end


class Game_Character
 #--------------------------------------------------------------------------
 # â— è·é›¢è¨ˆç®—
 #--------------------------------------------------------------------------
 def distance_xy_from(x, y)
   sx = distance_x_from(x)
   sy = distance_y_from(y)
   return [sx.abs, sy.abs].max
 end
end

 

 

2. Sub script #1: Events Move After Player

 

#==============================================================================
# â–  Modify Event Behaviour 6
#   @version 0.14 12/01/21 RGSS3
#   @author Saba Kan
#   @translator kirinelf
#------------------------------------------------------------------------------
#   Makes it so events only move after player does. 
#   ã„ã‚ã„ã‚ã¤ãりã‹ã‘ã§ã™ã€‚ <= Various things are still in the making?
#==============================================================================

module Saba
 module Dungeon
   # Events always move towards player?
   ENEMY_ALWAYS_TOWARD_PLAYER = true
 end
end

#=========================================================================
# Do not edit anything under this line unless you know what you're doing!
#=========================================================================

class Game_Event
 attr_reader :event_waiting
 #--------------------------------------------------------------------------
 # â— ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆåˆæœŸåŒ–
 #     event : RPG::Event
 #--------------------------------------------------------------------------
 alias saba_dungeon_initialize initialize
 def initialize(map_id, event)
   saba_dungeon_initialize(map_id, event)
   @event_id = event.id
 end
 #--------------------------------------------------------------------------
 # â— åœæ­¢æ™‚ã®æ›´æ–°
 #--------------------------------------------------------------------------
 alias saba_dungeon_update_stop update_stop
 def update_stop
   unless $game_map.dungeon?
     saba_dungeon_update_stop
     return
   end
   super
   unless @move_route_forcing
     update_self_movement if $game_player.start_move
   end
 end
 def check_waiting_event
   if @event_waiting
     start
   end
 end
 #--------------------------------------------------------------------------
 # ◠ダッシュ状態判定
 #--------------------------------------------------------------------------
 def dash?
   return super unless $game_map.dungeon?
   return $game_player.dash?
 end
 #--------------------------------------------------------------------------
 # ◠イベント起動
 #--------------------------------------------------------------------------
 alias saba_dungeon_start start
 def start
   @event_waiting = false
   saba_dungeon_start
 end
 alias saba_dungeon_update_self_movement update_self_movement
 def update_self_movement
   if stop_by_encounter?
     @stop_by_encounter_turn -= 1
     return
   end
   saba_dungeon_update_self_movement
   update_move
 end

 #--------------------------------------------------------------------------
 # ◠接触イベントã®èµ·å‹•判定
 #--------------------------------------------------------------------------
 alias saba_dungeon_check_event_trigger_touch check_event_trigger_touch
 def check_event_trigger_touch(x, y)
   return if stop_by_encounter?
   return if $game_map.interpreter.running?
   return if @starting
   return if @trigger != 2

   return if jumping?
   return unless normal_priority?
   if @trigger == 2 && $game_player.pos?(x, y)
     @event_waiting = true
     return
   end

   return unless $game_player.followers.visible
   $game_player.followers.each do |follower|
     if follower.pos?(x, y)
       @event_waiting = true
       return
     end
   end
 end
 #--------------------------------------------------------------------------
 # ◠エンカウントã«ã‚ˆã‚Šã‚¤ãƒ™ãƒ³ãƒˆä¸€æ™‚åœæ­¢
 #--------------------------------------------------------------------------
 def stop_by_encounter(turn)
   @stop_by_encounter_turn = turn
 end
 #--------------------------------------------------------------------------
 # ◠エンカウントã«ã‚ˆã‚Šã‚¤ãƒ™ãƒ³ãƒˆãŒåœæ­¢ã—ã¦ã„ã‚‹ã‹ï¼Ÿ
 #--------------------------------------------------------------------------
 def stop_by_encounter?
   return @stop_by_encounter_turn != nil && @stop_by_encounter_turn > 0
 end
 #--------------------------------------------------------------------------
 # â— ã‚¢ãƒ‹ãƒ¡ãƒ‘ã‚¿ãƒ¼ãƒ³ã®æ›´æ–°
 #--------------------------------------------------------------------------
 def update_anime_pattern
   return if stop_by_encounter?
   super
 end
 #--------------------------------------------------------------------------
 # ◠移動タイプ : è¿‘ã¥ã
 #--------------------------------------------------------------------------
 alias saba_dungeon_move_type_toward_player move_type_toward_player
 def move_type_toward_player
   unless Saba::Dungeon::ENEMY_ALWAYS_TOWARD_PLAYER
     saba_dungeon_move_type_toward_player
     return
   end
   if near_the_player?
     move_toward_player
   else
     move_random
   end
 end
 #--------------------------------------------------------------------------
 # ◠プレイヤーã«è¿‘ã¥ã
 #--------------------------------------------------------------------------
 def move_toward_player
   char = $game_player.nearest_char(x, y)
   move_toward_character(char)
 end
 #--------------------------------------------------------------------------
 # ◠キャラクターã«è¿‘ã¥ã
 #--------------------------------------------------------------------------
 def move_toward_character(character)
   sx = distance_x_from(character.x)
   sy = distance_y_from(character.y)
   if sx.abs > sy.abs
     move_straight(sx > 0 ? 4 : 6)
     if !@move_succeed && sy != 0 && !@event_waiting
       if @last_pos == [x, y + 1]
         move_straight(2)
       elsif @last_pos == [x, y - 1]
         move_straight(8)
       else
         move_straight(sy > 0 ? 8 : 2)
       end
     end
   elsif sy != 0
     move_straight(sy > 0 ? 8 : 2)
     if !@move_succeed && sx != 0 && !@event_waiting
       if @last_pos == [x + 1, y]
         move_straight(4)
       elsif @last_pos == [x + 1, y]
         move_straight(6)
       else
         move_straight(sx > 0 ? 4 : 6)
       end
     end
   end
   @last_pos = [x, y] if $game_map.room(x, y) == nil
 end
end

class Game_Player
 attr_reader :start_move
 #--------------------------------------------------------------------------
 # â— æ–¹å‘ボタン入力ã«ã‚ˆã‚‹ç§»å‹•処ç†
 #--------------------------------------------------------------------------
 alias saba_dungeon_move_by_input move_by_input
 def move_by_input
   unless $game_map.dungeon?
     saba_dungeon_move_by_input
     return
   end

   if !movable? || $game_map.interpreter.running?
     @start_move = false
     return
   end
   if Input.dir4 > 0
     return if $game_map.wait_for_event?
     unless passable?(@x, @y, Input.dir4)
       set_direction(Input.dir4)
       check_event_trigger_touch_front
       return
     end
     move_straight(Input.dir4)
     @start_move = true
   else
     @start_move = false
   end
 end
 #--------------------------------------------------------------------------
 # â—‹ 隊列ã®ã‚­ãƒ£ãƒ©ã‚‚å«ã‚“ã§ã€ä¸€ç•ªè¿‘ã„キャラをå–å¾—
 #--------------------------------------------------------------------------
 def nearest_char(x, y)
   return self unless $game_player.followers.visible
   min = $game_player.distance_x_from(x) + $game_player.distance_x_from(y)
   return self if min >= 5
   min_char = self
   for follower in $game_player.followers
     dist = follower.distance_x_from(x) + follower.distance_x_from(y)
     if dist < min
       min = dist
       min_char = follower
     end
   end
   return min_char
 end
end


class Game_Map
 #--------------------------------------------------------------------------
 # â— ã‚¤ãƒ™ãƒ³ãƒˆã®æ›´æ–°
 #--------------------------------------------------------------------------
 alias saba_dungeon_update_events update_events
 def update_events
   saba_dungeon_update_events
   return unless dungeon?
   moving = $game_player.moving?
   if ! moving
     @events.each_value {|event| event.check_waiting_event }
   end
   @last_moving = moving
 end
 #--------------------------------------------------------------------------
 # ◠エãƒãƒŸãƒ¼ã‚¤ãƒ™ãƒ³ãƒˆã®å‡¦ç†ã‚’å¾…ã£ã¦ã„ã‚‹ã‹ï¼Ÿ
 #--------------------------------------------------------------------------
 def wait_for_event?
   @events.each_value {|event| return true if event.event_waiting || event.starting }
   return false
 end
 #--------------------------------------------------------------------------
 # â— ã‚¤ãƒ™ãƒ³ãƒˆã®æ›´æ–°
 #--------------------------------------------------------------------------
 def stop_by_encounter(event_id, turn)
   @events[event_id].stop_by_encounter(turn)
 end
end

class Game_Interpreter
 def stop(turn)
   $game_map.stop_by_encounter(self.event_id, turn)
 end
end

 

 

3. Sub script #2: Minimap

 

#==============================================================================
# â–  Dungeon Creation 6 (Minimap)
#   @version 0.14 12/01/21 RGSS3
#   @author Saba Kan
#   @translator kirinelf
#------------------------------------------------------------------------------
#  
#==============================================================================
module Saba
 module Dungeon
   PLAYER_COLOR_ID = 9     # Color ID of player on Minimap.
   FOLLOWER_COLOR_ID = 1   # Color ID of followers on Minimap.
 end
end

#=========================================================================
# Do not edit anything under this line unless you know what you're doing!
#=========================================================================

class << DataManager
 #--------------------------------------------------------------------------
 # â— å„種ゲームオブジェクトã®ä½œæˆ
 #--------------------------------------------------------------------------
 alias saba_minimap_create_game_objects create_game_objects
 def create_game_objects
   saba_minimap_create_game_objects
   $game_minimap = Game_MiniMap.new
 end
 #--------------------------------------------------------------------------
 # ◠セーブ内容ã®ä½œæˆ
 #--------------------------------------------------------------------------
 alias saba_minimap_make_save_contents make_save_contents
 def make_save_contents
   contents = saba_minimap_make_save_contents
   contents[:minimap] = $game_minimap
   contents
 end
 #--------------------------------------------------------------------------
 # ◠セーブ内容ã®å±•é–‹
 #--------------------------------------------------------------------------
 alias saba_minimap_extract_save_contents extract_save_contents
 def extract_save_contents(contents)
   saba_minimap_extract_save_contents(contents)
   $game_minimap        = contents[:minimap]
 end
end

class Game_Map
 #--------------------------------------------------------------------------
 # ◠セットアップ
 #     map_id : マップ ID
 #--------------------------------------------------------------------------
 alias saba_minmap_setup setup
 def setup(map_id)
   saba_minmap_setup(map_id)
   if dungeon?
     $game_minimap.setup(self) 
   end
 end
 #--------------------------------------------------------------------------
 # ◠指定ã®åº§æ¨™ã‚’マッピング
 #--------------------------------------------------------------------------
 def mapping(x, y)
   return unless floor?(x, y)
   for rect in @rect_list
     if rect.room.contains(x, y)
       $game_player.room = rect.room
       $game_minimap.mapping_room(rect.room)
       return
     end
   end
   $game_player.room = nil
   $game_minimap.mapping(x, y)
 end
end

class Game_MiniMap
 BLANK = 0   # 空ãマップ
 FLOOR = 1   # 床
 WALL  = 2   # å£
 PASSAGE = 3 # 通路
 attr_accessor :changed_area
 attr_accessor :cleared
 attr_reader :events
 #--------------------------------------------------------------------------
 # â— ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆåˆæœŸåŒ–
 #--------------------------------------------------------------------------
 def initialize
   @map_data = {}
   @events = []
 end
 #--------------------------------------------------------------------------
 # â— ãƒžãƒƒãƒ—æƒ…å ±ã‚’åˆæœŸåŒ–
 #--------------------------------------------------------------------------
 def setup(map)
   clear
   for x in 0..map.width
     for y in 0..map.height
       @map_data[[x, y]] = BLANK
     end
   end
 end
 #--------------------------------------------------------------------------
 # ◠マッピングã•れã¦ã„ã‚‹ã‹ï¼Ÿ
 #--------------------------------------------------------------------------
 def mapping?(x, y)
   return @map_data[[x, y]] != BLANK
 end
 def floor_type(x, y)
   return @map_data[[x, y]]
 end
 #--------------------------------------------------------------------------
 # ◠部屋をマッピング
 #--------------------------------------------------------------------------
 def mapping_room(room)
   return if room.mapping
   room.mapping = true
   for x in room.lx...room.hx
     for y in room.ly...room.hy
       @map_data[[x, y]] = FLOOR
     end
   end
   mapping_edge(room)
   @changed_area = Rect.new(room.lx-1, room.ly-1, room.width+1, room.height+1)
 end
 #--------------------------------------------------------------------------
 # ◠部屋ã®å¤–å´ã‚’マッピング
 #--------------------------------------------------------------------------
 def mapping_edge(room)
   for x in (room.lx-1)...(room.hx+1)
     mapping_internal(x, room.ly-1)
     mapping_internal(x, room.hy)
   end
   for y in (room.ly)...(room.hy)
     mapping_internal(room.lx-1, y)
     mapping_internal(room.hx, y)
   end
 end
 #--------------------------------------------------------------------------
 # â— é“をマッピング
 #--------------------------------------------------------------------------
 def mapping(x, y)
   mapping_internal(x, y)
   mapping_internal(x-1, y)
   mapping_internal(x+1, y)
   mapping_internal(x, y-1)
   mapping_internal(x, y+1)
   mapping_internal(x-1, y-1)
   mapping_internal(x+1, y-1)
   mapping_internal(x-1, y+1)
   mapping_internal(x+1, y+1)
   @changed_area = Rect.new(x-1, y-1, 3, 3)
 end
 #--------------------------------------------------------------------------
 # â— é“をマッピング
 #--------------------------------------------------------------------------
 def mapping_internal(x, y)
   return if mapping?(x, y)
   if $game_map.floor?(x, y)
     @map_data[[x, y]] = PASSAGE
   else
     @map_data[[x, y]] = WALL
   end
 end
 def add_event(event)
   @events.push(event)
 end
 #--------------------------------------------------------------------------
 # ◠クリア
 #--------------------------------------------------------------------------
 def clear
   @cleared = true
   @map_data = {}
   @events = []
 end
end

class Game_Player
 attr_accessor :room
 #--------------------------------------------------------------------------
 # ◠指定ä½ç½®ã«ç§»å‹•
 #--------------------------------------------------------------------------
 alias saba_minimap_moveto moveto
 def moveto(x, y)
   saba_minimap_moveto(x, y)
   $game_map.mapping(x, y)
 end
 #--------------------------------------------------------------------------
 # ◠歩数増加
 #--------------------------------------------------------------------------
 alias saba_minimap_increase_steps increase_steps
 def increase_steps
   saba_minimap_increase_steps
   $game_map.mapping(self.x, self.y)
 end
end


class Sprite_MiniMap < Sprite_Base
 #--------------------------------------------------------------------------
 # ◠定数
 #--------------------------------------------------------------------------
 SQUARE_SIZE = 5 
 FLOOR_COLOR   = Color.new(70, 70, 180, 170)
 PASSAGE_COLOR = Color.new(160, 80, 160, 170)
 WALL_COLOR    = Color.new(200, 200, 200, 0)
 #--------------------------------------------------------------------------
 # â— ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆåˆæœŸåŒ–
 #     viewport  : ビューãƒãƒ¼ãƒˆ
 #--------------------------------------------------------------------------
 def initialize(viewport)
   super(viewport)
   @windowskin = Cache.system("Window")
   @event_sprites = {}
   create_bitmap
   update_position
   redraw_all
   @follower_sprites = {}
   if $game_player.followers.visible
     for follower in $game_player.followers
       @follower_sprites[follower] = create_character_sprite(Saba::Dungeon::FOLLOWER_COLOR_ID)
     end
   end
   @player_sprite = create_character_sprite(Saba::Dungeon::PLAYER_COLOR_ID)

   update
 end
 #--------------------------------------------------------------------------
 # ◠文字色å–å¾—
 #     n : 文字色番å·ï¼ˆ0..31)
 #--------------------------------------------------------------------------
 def text_color(n)
   @windowskin.get_pixel(64 + (n % 8) * 8, 96 + (n / 8) * 8)
 end
 #--------------------------------------------------------------------------
 # ◠キャラクター用ビットマップã®ä½œæˆ
 #--------------------------------------------------------------------------
 def create_character_sprite(color)
   if color >= 1000
     hole = true
     color -= 1000
   end
   if color >= 100
     static = true
     color -= 100
   end

   sprite_color = text_color(color) if color != 0
   return Sprite_MiniMap_Character.new(viewport, sprite_color, static, hole)
 end
 #--------------------------------------------------------------------------
 # ◠ビットマップã®ä½œæˆ
 #--------------------------------------------------------------------------
 def create_bitmap
   self.bitmap = Bitmap.new(Graphics.width, Graphics.height)
   self.bitmap.font.size = 32
   self.bitmap.font.color.set(255, 255, 255)
 end
 #--------------------------------------------------------------------------
 # â— åº§æ¨™ã®æ›´æ–°
 #--------------------------------------------------------------------------
 def update_position
   self.x = (Graphics.width - SQUARE_SIZE * $game_map.width) / 2
   self.y = (Graphics.height - SQUARE_SIZE * $game_map.height) / 2
 end
 #--------------------------------------------------------------------------
 # ◠転é€å…ƒãƒ“ãƒƒãƒˆãƒžãƒƒãƒ—ã®æ›´æ–°
 #--------------------------------------------------------------------------
 def update_bitmap
   rect = $game_minimap.changed_area
   return unless rect
   $game_minimap.changed_area = nil
   for x in rect.x..(rect.width + rect.x)
     for y in rect.y..(rect.height + rect.y)
       case $game_minimap.floor_type(x, y)
       when Game_MiniMap::FLOOR then
         color = FLOOR_COLOR
       when Game_MiniMap::WALL then
         color = WALL_COLOR
       when Game_MiniMap::PASSAGE then
         color = PASSAGE_COLOR
       else
         next
       end
       self.bitmap.fill_rect(x*SQUARE_SIZE, y*SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE, color)
     end
   end
 end

 def redraw_all
   self.bitmap.clear
   for x in 0..$game_map.width
     for y in 0..$game_map.height
       case $game_minimap.floor_type(x, y)
       when Game_MiniMap::FLOOR then
         color = FLOOR_COLOR
       when Game_MiniMap::PASSAGE then
         color = PASSAGE_COLOR
       when Game_MiniMap::WALL then
         color = WALL_COLOR
       else
         next
       end
       self.bitmap.fill_rect(x*SQUARE_SIZE, y*SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE, color)
     end
   end
 end
 #--------------------------------------------------------------------------
 # ◠フレーム更新
 #--------------------------------------------------------------------------
 def update
   super
   clear if $game_minimap.cleared
   update_bitmap if $game_minimap.changed_area
   update_visibility
   update_player
   update_events
 end
 #--------------------------------------------------------------------------
 # â— å¯è¦–çŠ¶æ…‹ã®æ›´æ–°
 #--------------------------------------------------------------------------
 def update_visibility
   #self.visible = $game_timer.working?
 end
 #--------------------------------------------------------------------------
 # â— ãƒ—ãƒ¬ã‚¤ãƒ¤ãƒ¼ã®æ›´æ–°
 #--------------------------------------------------------------------------
 def update_player
   @player_sprite.x = self.x + $game_player.x * SQUARE_SIZE
   @player_sprite.y = self.y + $game_player.y * SQUARE_SIZE

   return unless $game_player.followers.visible
   for follower in $game_player.followers
     sprite = @follower_sprites[follower] 
     sprite.x = self.x + follower.x * SQUARE_SIZE
     sprite.y = self.y + follower.y * SQUARE_SIZE
   end
 end
 #--------------------------------------------------------------------------
 # â— å…¨ã‚¤ãƒ™ãƒ³ãƒˆã®æ›´æ–°
 #--------------------------------------------------------------------------
 def update_events
   for event in $game_map.events.values
     if event.erased
       sprite = @event_sprites[event.event_id]
       if sprite
         sprite.dispose
         @event_sprites.delete(event.event_id)
       end
       $game_map.events.delete(event.event_id)
       next
     end
     update_event(event)
   end
 end
 #--------------------------------------------------------------------------
 # â— ã‚¤ãƒ™ãƒ³ãƒˆã®æ›´æ–°
 #--------------------------------------------------------------------------
 def update_event(event)
   if @event_sprites[event.event_id]
     sprite = @event_sprites[event.event_id]
   else
     sprite = create_character_sprite(event.name.to_i)
     @event_sprites[event.event_id] = sprite
   end
   if sprite.static
     sprite.visible = $game_minimap.mapping?(event.x, event.y)
   else
     sprite.visible = false
     if $game_player.room
       sprite.visible = $game_player.room.contains(event.x, event.y)
     end
     sprite.visible |= $game_player.distance(event) == 1
     sprite.visible = true if Saba::Dungeon::DEBUG_MODE
   end
   sprite.x = self.x + event.x * SQUARE_SIZE
   sprite.y = self.y + event.y * SQUARE_SIZE
 end
 def next_enemy_sprite
   unless @spare_enemy_sprites.empty?
     return @spare_enemy_sprites.pop
   else
     return create_character_sprite(true)
   end
 end
 #--------------------------------------------------------------------------
 # ◠クリア
 #--------------------------------------------------------------------------
 def clear
   self.bitmap.clear
   update_position
   @event_sprites.values.each {|s| s.dispose }
   @event_sprites = {}
   $game_minimap.cleared = false
 end
 #--------------------------------------------------------------------------
 # ◠解放
 #--------------------------------------------------------------------------
 def dispose
   self.bitmap.dispose
   @player_sprite.bitmap.dispose
   @player_sprite.dispose
   for sprite in @event_sprites.values
     sprite.dispose
   end
   for sprite in @follower_sprites.values
     sprite.dispose
   end
   super
 end
 def visible=(value)
   return if visible == value
   super
   @player_sprite.visible = value
   for sprite in @follower_sprites.values
     sprite.visible = value
   end
   for sprite in @event_sprites.values
     sprite.visible = value
   end
 end
end

class Sprite_MiniMap_Character < Sprite_Base
 attr_reader :static
 #--------------------------------------------------------------------------
 # â— ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆåˆæœŸåŒ–
 #     viewport  : ビューãƒãƒ¼ãƒˆ
 #--------------------------------------------------------------------------
 def initialize(viewport, color, static, hole)
   super(viewport)
   @alive = true
   @color = color
   @static = static
   @hole = hole
   if @color

     create_bitmap
     update
   else   
     self.visible = false

   end
 end
 #--------------------------------------------------------------------------
 # ◠ビットマップã®ä½œæˆ
 #--------------------------------------------------------------------------
 def create_bitmap
   size = Sprite_MiniMap::SQUARE_SIZE
   self.bitmap = Bitmap.new(size, size)
   if @hole
     self.bitmap.fill_rect(0, 0, size, 1, @color)
     self.bitmap.fill_rect(0, size-1, size, 1, @color)
     self.bitmap.fill_rect(0, 1, 1, size-2, @color)
     self.bitmap.fill_rect(size-1, 1, 1, size-2, @color)
   else
     self.bitmap.fill_rect(0, 0, size, size, @color)
   end
 end
 #--------------------------------------------------------------------------
 # ◠解放
 #--------------------------------------------------------------------------
 def dispose
   self.bitmap.dispose if self.bitmap
   super
 end
end

class Spriteset_Map
 attr_reader :character_sprites
 #--------------------------------------------------------------------------
 # â— ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆåˆæœŸåŒ–
 #--------------------------------------------------------------------------
 alias saba_minimap_initialize initialize
 def initialize
   saba_minimap_initialize

   @mini_map = Sprite_MiniMap.new(@viewport2)
   if $game_map.dungeon?
     update
   else
     @mini_map.visible = false
   end
 end
 #--------------------------------------------------------------------------
 # ◠解放
 #--------------------------------------------------------------------------
 alias saba_minimap_dispose dispose
 def dispose
   saba_minimap_dispose
   @mini_map.dispose if @mini_map
 end
 #--------------------------------------------------------------------------
 # ◠フレーム更新
 #--------------------------------------------------------------------------
 alias saba_minimap_update update
 def update
   saba_minimap_update
   return unless @mini_map
   if $game_map.dungeon?
     @mini_map.visible = true
     @mini_map.update
   else
     @mini_map.visible = false
   end
 end
 #--------------------------------------------------------------------------
 # ◠クリア
 #--------------------------------------------------------------------------
 def clear_minimap
   @mini_map.clear
 end
end

 

 

The script also requires two images that need to be placed in the Graphics/System folder. This is a link to the images required for the script to run: [Link] I have also attached them to this post for easy access.

 

I also highly recommend playing the demo. The link is here: [Link] This is quite a simple script IF you know what you're doing, which takes a bit of playing around. So I've included a demo to save you the trouble of accidentally ruining your current project or having to start a new project just for this. Aren't I kind?

 

For those of you who can't be bothered downloading the demo, I'm including a copy of the documentation here.

 

How to Use

 

Place the three scripts in the order I've numbered them above Main and under Materials.

 

1 - This is the main script. It generates random dungeons dynamically according to the settings and tiles I've described below.

2 - This is a sub script. It makes it so events only move after the player does, in true rogue-like fashion.

3 - This is a sub script. It sticks a minimap on the screen, invaluable for random dungeons. My only gripe with it is that it sticks it in the middle of the screen, which is kinda annoying.

 

Place the two images in the Graphics folder (dark_edge.png and dark_edge2.png) into your Graphics/System folder.

 

The setup is a little hard to explain, but here goes.

 

*******

Tiles

*******

 

Make a completely blank map. This map should be the size of the dungeon you want, and have a name starting with '@' (Ex. @Dungeon B1F). It doesn't matter what your display name is.

 

Starting in the top left corner (0,0, for those who want the coordinates), put a tile down (From TileA). This will be your floor tile. You can have two different floor tiles, side by side (0,0 and 1,0); the script will automatically and randomly insert them into the dungeon floor.

 

Underneath the floor tiles will be your ceiling and wall tiles. These go in (0,1) and (0,2) respectively. Since these tiles are generally autotiles, what you need to do is hold Shift while clicking to place a seamless tile. This goes for both the ceiling tile and wall tile.

 

Below the wall tile in (0,3) is what I like to call an obstruction tile. These are generally tiles that block the player's advance much like a wall tile, but break up the monotony by not being walls but actual objects such as rocks or pillars. The script will occasionally throw these tiles out to make things more interesting, but in my playthroughs of the demo it doesn't do that too often.

 

The last editable tile is (0,4), under the obstruction tile. This is simply the tile to use for a blank tile, and can be left empty. The difference can be seen in the demo; with a transparent blank tile, the spaces between the walls are left blank, while with the ceiling tile in that position, it fills in all the spaces between the walls with that tile, creating a labyrinth rather than just rooms in space.

 

Leave all other tiles blank. It should be noted that only the floor tiles can have two different tiles to choose from; the ceiling, wall, obstruction and blank tiles only accept the tiles on the far left (0,x).

 

This is enough to generate the dungeon itself, but it will not generate anything else. No exits, entrances or enemies. To do that, you place events in the blank map that the script will auto place for you randomly. This means that yes, the entrance to the dungeon would not be in the same place twice, and once you enter you won't be able to leave without finding the exit. Now, a bit more on events.

 

*******

Events

*******

 

The events themselves work as they normally do, with a little extras. These extras are quite interesting, and any rogue-like player would know instantly what I mean. Basically, you place a number in the event name and if the number in a certain position is '1', that event is handled differently. There are, as far as I know, two different handling methods that can be used concurrently.

 

Firstly, if the number in the hundred digit position is 1, the event will be registered on the minimap once discovered for the duration of the floor. This means that NPCs, treasure chests and the like can be shown on the minimap once you've discovered the room they're in, and will not disappear from the minimap once you leave the room as they usually do. As an example, placing '100' in the name of a treasure chest event means that even if I don't open the chest, I know where it is even if I've left the room and am on the other side of the dungeon. Same with NPCs and the like.

 

Secondly, if the number in the thousand digit position is 1, the event will be shown a little differently on the minimap. The author of the script describes it as 'donut style', where the event square is hollowed out, leaving only a thick outline. Players of rogue-likes will instantly associate this with stairs that lead to the next floor of the dungeon, although this isn't its only use. As an example, placing '1042' in the event name will cause the event to be shown as a square donut on the minimap.

 

These can be used together. For instance, in the demo, the stairs are marked '1101', and they show up as donut squares that stay even if you leave the room. The ten and one digits don't seem to matter, to my knowledge.

 

Another thing to note is that these events respawn randomly on reentering a floor. This means that any chests, doors and whatnot that use self switches can be used indefinitely as long as the player keeps exiting and reentering. This does not apply to global switches, so if you want a chest to only be accessible once, that's the only way to do it.

 

Finally, for move events, it doesn't matter where you transfer the player to in the map. Any random blank space works. Same for all events; you can just place them anywhere in the map. The script will handle things, and it'll never block the player off (In my ~20 runthroughs of the demo).

 

*******

Enemies

*******

 

And what would a rogue-like be without enemies? Unlike traditional rogue-likes, since this is just a script that generates dungeons, these enemies are more like touch encounters that will home in on the player. What this means is that enemies are generated randomly on the floor, and they then move towards the player. Upon contact with the player or any followers, battle is joined and it turns into a normal RPG using whatever battle system you're using. If you're using an ABS though, I'd recommend just setting up enemy events as usual and ignore the following since the script automatically places events anyways.

 

Anyways. To set up an enemy event, all you gotta do is make a normal event with a battle process. In the Autonomous Movement section, set the Type to Approach, Speed to Normal and Frequency to Highest. Make the trigger Event Touch. Now there's one last thing that's very important, and the core of the whole thing. In the name of the event, there has to be a '*' symbol. This instantly registers the event as an enemy, and proceeds to have the script handle it entirely. For example, 'Slime*' or 'Bat*' or even just a random numer like '2*'. Finally, to avoid being stuck in an infinite loop of battles, have an Erase Event command under the If Win condition. You can also optionally add an animation such as a Slash animation to signify you destroying the enemy and erasing it.

 

So what happens now that it's registered as an enemy? Well, here's what happens. The script will automatically copy the event and place it randomly around the map, where it will start to act in a typical rogue-like manner. With script #2, they will only move when the player does, and upon contact with the player, the battle process will start.

 

Another important thing to note is how many copies of the enemy events will be placed. This is simply the average encounter rate of the map, found in the map's properties in the bottom right corner, labelled 'Steps Average'. So if it's left at the default 30, there'll be up to 30 enemies running around your map. You might think you need to set this pretty high so the player doesn't run out of enemies to fight around the map, but you'd be wrong.

 

In line 28 of script #1, you can assign a variable to note the number of enemies on the map. At the creation of a floor, this variable will equal the Steps Average of that map, which in the demo is 5. Everytime you kill an enemy, this variable drops by 1, until it hits 0 when you've massacred every enemy on the map. What this means is that you can have a funky Parallel Process Conditional Branch checking for when this variable hits 0, then forcibly creating new enemies. This can be done by having a script call the following code:

 

$game_map.add_random_enemy

 

That should cover most of the random battles generated by the script. As a few additional notes, you can completely ignore what I've said above and have random encounters for the floors, or mix it up and have touch encounters on one and random encounters on another, like in the demo. You can also stop events from moving by putting the following in a script call:

 

stop(n)

 

where 'n' is the number of turns you want the enemy to be stopped for. This is handy for enemies you can escape from, whereupon escaping the enemy is locked in place for a few turns (5 turns in the demo) and thus allow the player to get away. With a series of conditional branches and parallel processes, it might even be possible to have the player be able to stun enemies before a fight, avoiding a battle. It'll be a pain to setup though.

 

*******

End

*******

 

And that should be that! Think I've covered everything. It's not easy, but not particularly hard either. If there're any questions, feel free to pop me a line. I'm not a scripter though, so don't expect too much on that note, but I might be able to help you out with debugging and figuring out what's going on.

 

Kirin, out.

 

 

FAQ

Q: Where do I put these scripts?

A: Above Main, under Materials. You really only need the main script; the other two are just bonuses.

 

Q: How do I use this script?

A: Read the 'How to Use.txt' file included in the demo, or refer to the same section in my post above.

 

Q: Help! I'm getting an 'Unable to find file: Graphics/System/dark_edge2' error!

A: The hint is in the error. Download the images from either this link or from the attachment and place them in the proper folder.

 

Q: Help! I'm getting an 'undefined method 'each' for nil:NilClass' error!

A: Make sure that the maps that'll be running the code have a '@' symbol before the map name (Display name doesn't matter).

 

Credit and Thanks

- Saba Kan, for making this script.

- Kirin (me), for translating this.

- Nelderson, for pointing out to me that you need to have a '@' symbol in the map editor name.

- Enterbrain, for once again making an awesome maker.

- Google Translate, for helping me with minor translations.

- The makers of the Rikai-chan addon for Mozilla and the Rikai-kun extension for Chrome, for giving us an awesome Japanese translator.

RandomDungeonGenerator.zip

Edited by kirinelf
  • Like 4

Share this post


Link to post
Share on other sites

Try it again. I was having trouble uploading stuff just now when I updated it with a tiny fix.

Share this post


Link to post
Share on other sites

I get this error in the demo:

 

Dungeon Generation line 686: NomethodError occurred.

Undefined method 'put_to_random_place' for nil:NilClass

 

 

Awesome script though! This is a real time saver for creating dungeon crawling sections in a game.

 

 

EDIT: I figured out the problem. If the monster variable is too high, it will just keep generating monsters

which can crash the game.

Edited by Sidbot

Share this post


Link to post
Share on other sites

I actually found something else. Turns out that I forgot to reassign the ENEMY_COUNT variable in the script. In the editor, I labelled variable 001 as the Enemy Count variable, while in the script it was still 141. I fixed that and it hasn't thrown up any problems so far.

 

Major derp moment. Uploading the fixed demo.

Share this post


Link to post
Share on other sites

I've a big problem I use this generator with "Sapphire Action System IV" but it make many passability bug.

For exemple I walk on a wall. So help-me.

(Note for scripter: I just have "Sapphire Action System IV" script in my project.)

Share this post


Link to post
Share on other sites

I'm not a scripter, so I can't help you with this. I'll see if I can take SASIV for a test run with this script later, and see if there're any easy fixes that can be done, but generally, I'd be a little doubtful of this working on ABS's. I'll give it a try later though.

 

Edit: When I tried this, the random dungeon generates fine but my character can't move at all. Also, the script spits out an error whenever I attack an enemy, which is related to the Dungeon Generation script. I'd go to Script Support if I were you; I have no idea how to fix this. Maybe Khas or someone else would be able to come up with a fix.

Edited by kirinelf

Share this post


Link to post
Share on other sites

Hi there. I've got a lil' problem here.

 

I've created a dungeon with 3 floors. The first goes perfectly fine, but when i enter the second floor, i get an 'undefined method 'name' for nil:NilClass' error. Or somethin like this.

 

I think i've done everythin accordin to your instructions (my floors' name start with @) so i really don't see where is the problem. Could ya help me, please ?

 

Thanks for translatin this script anyway.

Share this post


Link to post
Share on other sites

Hehe I have been using this myself, and modifying it a bit too. :3

 

Anyway the undefined name sounds like it's related to your events to me. It's obviously passing some nil value somewhere it shouldn't. You might want to give this backtrace script a try, as it gives you a better idea of what the error is. Except I, er... can't figure out for the life of me how you open that console. :/ I made a version that logs to a file instead :3 I bet I am missing something real obvious though. >_< I sure am using a lot of emoticons lately. O_o My avatar must be getting to me. ^_^ MORE DUST! OwO

 

Edit: HURPA DURP, I found the show console option under the game menu. >_<

Edited by KilloZapit

Share this post


Link to post
Share on other sites

I just wanted to say how awesome this script is. However, I can't seem to get it to work properly with XAS-ABS for RPG Maker VX Ace. Whenever I attack it gives me a, 'undefined method 'each' for nil:NilClass'. It thinks the map I'm on is trying to load the dungeon whenever I attack or something... Also, when I start a previously saved game, it gives me a floor type error given in the same format as the above.

 

Any ideas on how to get this working with XAS?

Share this post


Link to post
Share on other sites

My bro... is going to flip his shit over this. I would aswell but I am presently flipping my shit over something else.

 

The scripting support has come. Suddenly I feel more comfortable with Ace.

Share this post


Link to post
Share on other sites

I love the script, very interesting, but I get this error when I try to run a new project with just the first script loaded in.

 

"line 842: NoMethodError occured. undefined method 'room' for #<Game_Player:0x3818488>"

 

I followed the steps closely and this crash only happens after I go past the title screen. Everything seems properly named and the dungeon should generate just fine.

 

I can't find a place where 'room' is even declared as a variable of the GamePlayer class, or its parent classes. At no point does the code seem to add it, but then it moves on to accessing it, and then crashes because it doesn't exist.

 

Anyway, I'm just a tad confused about what I'm missing in my map, to cause such an error. Clearly it works for other people, so I must be missing something...

 

....Nevermind. I just noticed that the minimap script adds 'room' to the GamePlayer. Serves me right for forgetting to add all of the scripts.

Share this post


Link to post
Share on other sites

Yeah it's kind of weird how things are defined sometimes. The scripts aren't very modular like that, since there are things like that where things are defined in subscripts that should be in the main script.

Share this post


Link to post
Share on other sites

I'm more interested in the algorithm used for drawing the auto-tiles.

But...lol I can't seem to sit down and read the script. Does someone want to take the auto-tile drawing algorithm and write a separate script for it?

Edited by Tsukihime

Share this post


Link to post
Share on other sites

It's a pretty limited algorithm if you ask me... I am not sure it will even work for anything besides walls, and assumes fixed offsets from the tile. Look at the put_wall_tiles and put_edge_tiles for Game_Map.

Edited by KilloZapit

Share this post


Link to post
Share on other sites

I thought the auto-tile algorithm was supposed to be limited, considering how they shrunk it down from the XP tilesets.

Share this post


Link to post
Share on other sites

I mean the way the script does it, it won't work for general tiles.

Share this post


Link to post
Share on other sites

That's because auto-tile algorithm does not care about general tiles since general tiles are just one ID.

Autotiles have 48 ID's depending on the adjacent tiles.

Share this post


Link to post
Share on other sites

It's not that simple I think. Walls and ground autotiles looks slightly different to me. It's likely you have to figure out what group of tiles the tile is in first

Share this post


Link to post
Share on other sites

The patterns are defined for each A1, A2, A3, and A4.

If you know which group of tiles you're working with, hardcoding it is not an issue.

 

There is no reason why you would ever be working with ground and wall tiles simultaneously, and because the editor has hardcoded it like that, there is no reason why someone would design an autotile differently and expect it to work correctly.

Share this post


Link to post
Share on other sites

Yeah, just saying if you want to do it right for say, passing over every tile on the map, figuring out the group it's in and autotileing it, your probably going to have to write your own.

Edited by KilloZapit

Share this post


Link to post
Share on other sites

Whenever i load my Game and visit a new added map this error happens:

51538ac30e9c2.jpg

It's a Pain to test play the game without actually being able to play it normally.

(like how strong you are in your playthrough etc.)

That's why i like to play my game while designing it. Being able to load and save

is a Major thing to easen it for me.

So this Error is really a pain in the Nutella-bread for me.

Share this post


Link to post
Share on other sites

Try replacing this:

  def dungeon?

if @random_dungeon != nil

return @random_dungeon

end

unless @map_infos

@map_infos = load_data("Data/MapInfos.rvdata2")

end

@random_dungeon = @map_infos[@map_id].name.include?("@")

return @random_dungeon

end

with this:
  def dungeon?

if @random_dungeon.nil?

@random_dungeon = $data_mapinfos[@map_id].name.include?("@")

end

return @random_dungeon

end

Share this post


Link to post
Share on other sites

Seems like there are tons of problems around this script, though it works for some people.
I'm getting this error whenever the game loads a map (any map as far as I know):

7seVRuN.png

The scripts are from the demo.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×