02-17-2010, 08:14 PM
Momomomo's Skill Book (Translated by Mcdohl):
Instructions:
Installation:
Create a new class above "Main" and place the spoiler code into it.
Usage:
First off, go to your Database in your game after you get this script in and go to the system tab. In the bottom left hand corner in the element/attribute tab, add new slots. Now, the stuff in these lines:
Is what you put in those new elements/attributes you just made. Note that I have customized this to my needs, if you want to get rid of the stuff you don't want just delete all instances of each out of those lines above that are in the script. You new ones in the same way as well. Now, go to the skills tab, and go to the 'Fire' spell. Now, check the Elemental element/attribute to place this spell into the Elemental section of the skill book. Then just do the same for the rest of the skills by selecting to proper element/attribute for them. Now, to call this script from the main menu or from a call script, use this:
Wachuga's Maze Generator:
**BEFORE YOU PUT THIS IN, BE SURE TO PUT NEAR FANTASTICA'S DYNAMIC MAPS SCRIPT IN YOUR GAME!!!**
Instructions:
Installation:
This script has a lot of components to it, so I formatted it slightly differently then my other scripts as far as in the class browser goes.
I made an empty class and called it Maze Generator then under that I made a new empty class called ----------------------.
This is because there are four classes to this script, it organizes it a bit to do it like that.
I will list installation instructions along side the spoiler tags this time around.
Usage:
Now in order to use this you must place <rand> in the map name but there are other things as well. First of all these maps can be saved by putting <save> in the name before <rand>.
Now, if you want to control the randomness of the maze (this only does mazes for now, but Wachunga is now working on a full map generator) you have 3 options. the first <#> after <rand> controls the chances of curves and twists. the second <#> after <rand> decreases the number of dead ends. And the last <#> after <rand> increases the chance that dead ends will connect to another pathway.
Examples:
Each time you enter or exit a map that doesnt have <save> in it, it will change, so keep that in mind, also, you must place <start> in an event (I put it in the teleport) name where the begging of the maze is, carful though, the entrance and exits have to be in certain areas, otherwise your going to get a warning message when you try to enter it. Same thing with the exit, put <end> in an event name where you want the end to be at (again, I would put it in the teleport).
Make a new one called Game_Map*** and put this in it:
Now, under that class make a new one called 'Maze' and put this into it:
Under this class make another new one called 'Direction Matrix' and put this into it:
Now, under this class put one more called 'Tile' and then put this script into that:
Instructions:
Installation:
Create a new class above "Main" and place the spoiler code into it.
Usage:
First off, go to your Database in your game after you get this script in and go to the system tab. In the bottom left hand corner in the element/attribute tab, add new slots. Now, the stuff in these lines:
Quote:# Name the skill categories.
@skill_kind_name = ["Physical", "Elemental", "Non-Elemental", "Curative", "Status"]
# Next is the menu setup. It's a vertical list. List the categories in any order you want.
# Note: The categories below must coincide with the categories you listed above.
@kind_row = ["Physical",
"Elemental",
"Non-Elemental",
"Curative",
"Status"]
# Now write the element setups.You need to add elements in the Database (in the System Tab). For
# example, if you want to use a "Physical" category, go make an element called "Physical" and
# then apply it to all the skills you want them to appear under the Physical category!
@skill_kind_element_name = ["Physical", "Elemental", "Curative", "Status", "Non-Elemental"]
@skill_id_data = skill_book_id_set
end
Is what you put in those new elements/attributes you just made. Note that I have customized this to my needs, if you want to get rid of the stuff you don't want just delete all instances of each out of those lines above that are in the script. You new ones in the same way as well. Now, go to the skills tab, and go to the 'Fire' spell. Now, check the Elemental element/attribute to place this spell into the Elemental section of the skill book. Then just do the same for the rest of the skills by selecting to proper element/attribute for them. Now, to call this script from the main menu or from a call script, use this:
Quote: $scene = Scene_SkillBook.new
Skill Book Script
#=================================
# Item_Book by momomomo?
# http://f53.aaa.livedoor.jp/%7Emomomo/sou...ource.html
#----------------------------------------------------------------
#-Translated by Mcdohl
#----------------------------------------------------------------
#================================
# English is not my main language, so I'm sorry if you can't understand some of my comments.
# 11.18.2005
# Script translated, known bugs:
# -Doesn't seem to work with some custom-skill learning scripts.
# This script will add all the skills you learn throughout the game into a "Book."
# In this book you can see the stats, MP cost, element and states of each skill.
module Skill_Book_Config
# The following line (SHOW_COMPLETE_TYPE =) is very important. It will define how are
# the items counted. (The item count appears on the upper right corner, in the help window.
# Use "0" to display nothing.
# Use "1" to display it in a "items found so far/total" format.
# Use "2" to use percentage completion.
# Use "3" for...a weird item counting method...
SHOW_COMPLETE_TYPE = 3
DRAW_POW_ZERO = false
ZERO_POW_TEXT = ""
end
class Window_SkillBook_Info < Window_Selectable
include Skill_Book_Config
end
class Data_SkillBook
attr_reader :skill_kind_name
attr_reader :kind_row
attr_reader :skill_id_data
attr_reader :skill_kind_element_name
#--------------------------------------------------------------------------
# ? Setup
#--------------------------------------------------------------------------
def initialize
# Name the skill categories.
@skill_kind_name = ["Physical", "Elemental", "Non-Elemental", "Curative", "Status"]
# Next is the menu setup. It's a vertical list. List the categories in any order you want.
# Note: The categories below must coincide with the categories you listed above.
@kind_row = ["Physical",
"Elemental",
"Non-Elemental",
"Curative",
"Status"]
# Now write the element setups.You need to add elements in the Database (in the System Tab). For
# example, if you want to use a "Physical" category, go make an element called "Physical" and
# then apply it to all the skills you want them to appear under the Physical category!
@skill_kind_element_name = ["Physical", "Elemental", "Curative", "Status", "Non-Elemental"]
@skill_id_data = skill_book_id_set
end
#--------------------------------------------------------------------------
# ? Defining Kinds
#--------------------------------------------------------------------------
def kind_search(name)
if @skill_kind_name.include?(name)
return [0, @skill_kind_name.index(name)]
end
end
#--------------------------------------------------------------------------
# ? ???????????
#--------------------------------------------------------------------------
def no_add_element
no_add = 0
# ???????ID???
for i in 1...$data_system.elements.size
if $data_system.elements[i] =~ /??????/
no_add = i
break
end
end
return no_add
end
#--------------------------------------------------------------------------
# ? ?????????ID???
#--------------------------------------------------------------------------
def element_search(element_name)
return nil if element_name == nil
for i in 1...$data_system.elements.size
if $data_system.elements[i] =~ /^#{element_name}/
return i
end
end
end
#--------------------------------------------------------------------------
# ? ??????ID??
#--------------------------------------------------------------------------
def skill_book_id_set
data = []
no_add = no_add_element
if @skill_kind_element_name.size == 0
data[0] = [0]
for i in 1...$data_skills.size
skill = $data_skills[i]
next if skill.name == ""
next if skill.element_set.include?(no_add)
data[0].push(skill.id)
end
else
for i in 0...@skill_kind_element_name.size
data[i] = [0]
element_id = element_search(@skill_kind_element_name[i])
for j in 1...$data_skills.size
skill = $data_skills[j]
next if skill.name == ""
next if skill.element_set.include?(no_add)
if skill.element_set.include?(element_id)
data[i].push(skill.id)
end
end
end
end
return data
end
end
class Game_Actor < Game_Battler
#--------------------------------------------------------------------------
# ? ???????
# skill_id : ??? ID
# This seems to be how the script detects a new skill, this may be the key to making it compatible
# with custom-learning skills scripts, not sure tho.
#--------------------------------------------------------------------------
alias game_actor_skill_book_learn_skill learn_skill
def learn_skill(skill_id)
game_actor_skill_book_learn_skill(skill_id)
$game_system.add_skill_count(skill_id)
end
end
class Window_Base < Window
#--------------------------------------------------------------------------
# ? Element Set Up
# NOTE: Default RTP elements were used.
#--------------------------------------------------------------------------
def draw_attack_element(x, y, element_set)
elem_temp = []
for i in element_set
elem = $data_system.elements[i]
elem_temp.push("Fire") if elem == "Fire"
elem_temp.push("Ice") if elem == "Ice"
elem_temp.push("Thunder") if elem == "Thunder"
elem_temp.push("Water") if elem == "Water"
elem_temp.push("Earth") if elem == "Earth"
elem_temp.push("Wind") if elem == "Wind"
elem_temp.push("Light") if elem == "Light"
elem_temp.push("Darkness") if elem == "Darkness"
end
if elem_temp.size == 0
self.contents.draw_text(x, y, 64, 32, "None")
return
end
ox = 0
for name in elem_temp
cx = self.contents.text_size(name).width
self.contents.draw_text(x+ox, y, cx, 32, name)
ox += cx+8
end
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def draw_attack_wp_element(x, y, element_set)
elem_temp = []
for i in element_set
elem = $data_system.elements[i]
elem_temp.push("?") if elem == "?"
elem_temp.push("?") if elem == "?"
elem_temp.push("?") if elem == "?"
elem_temp.push("?") if elem == "?"
elem_temp.push("?") if elem == "?"
end
if elem_temp.size == 0
self.contents.draw_text(x, y, 64, 32, "??")
return
end
ox = 0
for name in elem_temp
cx = self.contents.text_size(name).width
self.contents.draw_text(x+ox, y, cx, 32, name)
ox += cx+8
end
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def draw_attack_weak_element(x, y, element_set)
elem_temp = []
for i in element_set
elem = $data_system.elements[i]
elem_temp.push("??") if elem == "? ??"
elem_temp.push("?") if elem == "? ?"
elem_temp.push("??") if elem == "? ??"
elem_temp.push("?") if elem == "? ?"
elem_temp.push("?") if elem == "? ?"
elem_temp.push("?") if elem == "? ?"
elem_temp.push("??") if elem == "? ??"
elem_temp.push("??") if elem == "? ??"
end
if elem_temp.size == 0
self.contents.draw_text(x, y, 64, 32, "??")
return
end
ox = 0
for name in elem_temp
cx = self.contents.text_size(name).width
self.contents.draw_text(x+ox, y, cx, 32, name)
ox += cx+8
end
end
#--------------------------------------------------------------------------
# ? States (Status Abnormalities like Poison, Sleep, etc.)
#--------------------------------------------------------------------------
def draw_attack_add_state(x, y, plus_state_set)
state_temp = []
for i in plus_state_set
state = $data_states[i]
state_temp.push(state.name) if state.name != ""
end
if state_temp.size == 0
self.contents.draw_text(x, y, 64, 32, "None")
return
end
ox = 0
oy = 0
for name in state_temp
cx = self.contents.text_size(name).width
if ox + cx + 4 >= self.contents.width - 128
ox = 0
oy += 1
end
self.contents.draw_text(x+ox, y+oy*32, cx, 32, name)
ox += cx+8
end
end
#--------------------------------------------------------------------------
# ? ???????
#--------------------------------------------------------------------------
def draw_scope(scope)
case scope
when 0
return ""
when 1
return ""
when 2
return ""
when 3
return ""
when 4
return ""
when 5
return ""
when 6
return ""
when 7
return ""
end
end
end
class Game_Temp
attr_accessor :skill_book_data
alias temp_skill_book_data_initialize initialize
def initialize
temp_skill_book_data_initialize
@skill_book_data = Data_SkillBook.new
end
end
class Game_System
attr_accessor :skill_count # ???????(???)
#--------------------------------------------------------------------------
# ? ?????????
#--------------------------------------------------------------------------
alias game_system_skill_book_initialize initialize
def initialize
game_system_skill_book_initialize
@skill_count = {}
end
#--------------------------------------------------------------------------
# ? ???????????(???)
# 0:??? 1:???
#--------------------------------------------------------------------------
def add_skill_count(skill_id, type=0)
if type == -1
@skill_count[skill_id] = 0
else
@skill_count[skill_id] = 1
end
end
#--------------------------------------------------------------------------
# ? ??????????????
#--------------------------------------------------------------------------
def skill_book_max
kind_data = $game_temp.skill_book_data.skill_kind_name
size = 0
for kind in kind_data
size += skill_book_category_max(kind)
end
return size
end
#--------------------------------------------------------------------------
# ? ??????????????
#--------------------------------------------------------------------------
def skill_book_now
kind_data = $game_temp.skill_book_data.skill_kind_name
size = 0
for kind in kind_data
size += skill_book_category_now(kind)
end
return size
end
#--------------------------------------------------------------------------
# ? ????????????
#--------------------------------------------------------------------------
def skill_book_complete_percentage
s_max = skill_book_max.to_f
s_now = skill_book_now.to_f
comp = s_now / s_max * 100
return comp.truncate
end
#--------------------------------------------------------------------------
# ? ????????????????????
# category:??????
#--------------------------------------------------------------------------
def skill_book_category_max(category)
id_data = $game_temp.skill_book_data.skill_id_data.dup
index = $game_temp.skill_book_data.kind_search(category)[1]
size = id_data[index].size - 1
return size
end
#--------------------------------------------------------------------------
# ? ????????????????????
# category:??????
#--------------------------------------------------------------------------
def skill_book_category_now(category)
now_skill_info = @skill_count.keys
index = $game_temp.skill_book_data.kind_search(category)[1]
# ???????ID???
no_add = $game_temp.skill_book_data.no_add_element
elename = $game_temp.skill_book_data.skill_kind_element_name[index]
element_id = $game_temp.skill_book_data.element_search(elename)
new_skill_info = []
for i in now_skill_info
skill = $data_skills[i]
next if skill == nil
next if skill.name == ""
next if skill.element_set.include?(no_add)
if element_id == nil or skill.element_set.include?(element_id)
new_skill_info.push(skill.id)
end
end
return new_skill_info.size
end
#--------------------------------------------------------------------------
# ? ??????????????????
# category:??????
#--------------------------------------------------------------------------
def skill_book_category_complete_percentage(category)
s_max = skill_book_category_max(category).to_f
s_now = skill_book_category_now(category).to_f
comp = s_now / s_max * 100
end
end
class Interpreter
def skill_book_max(category=nil)
if category == nil
return $game_system.skill_book_max
else
return $game_system.skill_book_category_max(category)
end
end
def skill_book_now(category=nil)
if category == nil
return $game_system.skill_book_now
else
return $game_system.skill_book_category_now(category)
end
end
def skill_book_comp(category=nil)
if category == nil
return $game_system.skill_book_complete_percentage
else
return $game_system.skill_book_category_complete_percentage(category)
end
end
end
class Window_SkillBook < Window_Selectable
attr_reader :data
attr_reader :item_kind
attr_reader :item_index
#--------------------------------------------------------------------------
# ? ?????????
#--------------------------------------------------------------------------
def initialize(index=0)
super(0, 64, 640, 416)
@column_max = 2
@book_data = $game_temp.skill_book_data
@data = data_set(index)
@data.shift
#@data.sort!
@item_max = @data.size
@item_kind = index
self.index = 0
#refresh
end
def new_data_set(index)
@data = data_set(index)
@data.shift
#@data.sort!
@item_max = @data.size
end
#--------------------------------------------------------------------------
# ? ????????
#--------------------------------------------------------------------------
def data_set(index)
kind_row_data = @book_data.kind_search(@book_data.kind_row[index])
@item_kind = kind_row_data[0]
@item_index = kind_row_data[1]
data = []
case @item_kind
when 0
data = @book_data.skill_id_data[@item_index].dup
end
return data
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def show?(kind, id)
case kind
when 0
if $game_system.skill_count[id] == 0 or $game_system.skill_count[id] == nil
return false
else
return true
end
end
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def item
return @data[self.index]
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def refresh
if self.contents != nil
self.contents.dispose
self.contents = nil
end
#???? 0 ??????????????????????
return if @item_max == 0
self.contents = Bitmap.new(width - 32, row_max * 32)
for i in 0...@item_max
draw_item(i)
end
end
#--------------------------------------------------------------------------
# ? ?????
# index : ????
#--------------------------------------------------------------------------
def draw_item(index)
case @item_kind
when 0
item = $data_skills[@data[index]]
id = @book_data.skill_id_data[@item_index].index(item.id)
end
return if item == nil
x = 4 + index % 2 * (288 + 32)
y = index / 2 * 32
rect = Rect.new(x, y, self.width / @column_max - 32, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
self.contents.font.color = normal_color
self.contents.draw_text(x, y, 32, 32, id.to_s)
if show?(@item_kind, item.id)
bitmap = RPG::Cache.icon(item.icon_name)
opacity = 255
self.contents.blt(x+48, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.draw_text(x+48 + 28, y, 212, 32, item.name, 0)
else
# The "??" are used in blank spaces. (the skills you haven't learned yet)
self.contents.draw_text(x+48 + 28, y, 212, 32, "??", 0)
return
end
end
end
class Window_SkillBook_Info < Window_Selectable
#--------------------------------------------------------------------------
# ? ?????????
#--------------------------------------------------------------------------
def initialize
super(0, 0+64+64, 640, 480-64-64)
@book_data = $game_temp.skill_book_data
self.contents = Bitmap.new(width - 32, height - 32)
self.index = -1
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def refresh(item_id, item_kind, item_index)
self.contents.clear
self.contents.font.size = 22
case item_kind
when 0
draw_skill_info(item_id, item_index)
end
end
#--------------------------------------------------------------------------
# ? ?????
#--------------------------------------------------------------------------
def draw_skill_info(item_id, item_index)
item = $data_skills[item_id]
rect = Rect.new(4, 0, 160, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
bitmap = RPG::Cache.icon(item.icon_name)
opacity = 255
self.contents.blt(4+48, 0 + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.font.color = normal_color
id = @book_data.skill_id_data[item_index].index(item.id)
self.contents.draw_text(4, 0, 32, 32, id.to_s)
self.contents.draw_text(4+48 + 28, 0, 212, 32, item.name, 0)
cost = item.sp_cost.to_s
# Change "MP" to whatever you want. Like "SP" for example, or just leave it in MP.
self.contents.draw_text(4+20 + 28 + 232, 0, 48, 32, "MP:", 2)
self.contents.draw_text(4+48 + 28 + 232, 0, 48, 32, cost.to_s, 2)
#skill_kind = skill_kind_name(item.element_set)
#self.contents.draw_text(320+96, 0, 160, 32, skill_kind, 0)
self.contents.font.color = text_color(2)
self.contents.draw_text(4, 32, 48, 32, "DMG", 0)
self.contents.font.color = normal_color
if item.power == 0 and DRAW_POW_ZERO == false
pow = ZERO_POW_TEXT
else
pow = item.power.to_s
end
self.contents.draw_text(4+48, 32, 48, 32, pow, 2)
self.contents.font.color = system_color
self.contents.draw_text(4, 64, 48, 32, "", 0)
self.contents.font.color = normal_color
self.contents.draw_text(4+96+16, 64, 128, 32, draw_scope(item.scope), 0)
self.contents.font.color = system_color
self.contents.draw_text(4, 96, 96, 32, "Element")
self.contents.draw_text(4, 128, 96, 32, "")
self.contents.draw_text(4, 160, 96, 32, "State")
self.contents.font.color = normal_color
draw_attack_element(4+96+16, 96, item.element_set)
draw_attack_weak_element(4+96+16, 128, item.element_set)
draw_attack_add_state(4+96+16, 160, item.plus_state_set)
@help_window.set_text(item.description)
end
#--------------------------------------------------------------------------
# ? ?????????
#--------------------------------------------------------------------------
def update_help
#???
end
end
class Scene_SkillBook
include Skill_Book_Config
#--------------------------------------------------------------------------
# ? ?????
#--------------------------------------------------------------------------
def main
# ????????
@title_window = Window_Base.new(0, 0, 640, 64)
@title_window.contents = Bitmap.new(640 - 32, 64 - 32)
@title_window.contents.draw_text(4, 0, 320, 32, "Skill Book", 0)
draw_comp
@main_window = Window_SkillBook.new
@main_window.active = false
@main_window.index = -1
@help_window = Window_Help.new
@help_window.z = 110
@help_window.y = 64
@help_window.visible = false
command = $game_temp.skill_book_data.kind_row
@kind_window = Window_Command.new(160, command)
@kind_window.z = 110
@kind_window.x = 320 - @kind_window.width / 2
@kind_window.y = 240 - @kind_window.height / 2
@kind_window.active = true
# ???????????? (?????????????)
@info_window = Window_SkillBook_Info.new
@info_window.z = 110
@info_window.visible = false
@info_window.active = false
# ?????????????
@info_window.help_window = @help_window
@visible_index = 0
@now_kind = nil
# ?????????
Graphics.transition
# ??????
loop do
# ????????
Graphics.update
# ???????
Input.update
# ??????
update
# ????????????????
if $scene != self
break
end
end
# ?????????
Graphics.freeze
# ????????
@title_window.dispose
@help_window.dispose
@main_window.dispose
@kind_window.dispose
@info_window.dispose
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def update
# ????????
#@help_window.update
@main_window.update
@kind_window.update
@info_window.update
if @info_window.active
update_info
return
end
# ?????????????????: update_target ???
if @main_window.active
update_main
return
end
# ????????????????: update_kind ???
if @kind_window.active
update_kind
return
end
end
#--------------------------------------------------------------------------
# ? ?????? (????????????????)
#--------------------------------------------------------------------------
def update_kind
# C ??????????
if Input.trigger?(Input::C)
# ?? SE ???
$game_system.se_play($data_system.decision_se)
if @now_kind != @kind_window.index
@main_window.new_data_set(@kind_window.index)
@main_window.refresh
@now_kind = @kind_window.index
end
subtitle = $game_temp.skill_book_data.kind_row[@kind_window.index]
# This is, when you enter a sub-menu. (for example Physical). Physical is the subtitle, so you
# write a text to go before Armors. The default said "Skill Book:" that way it would look this
# way when you scroll through the Physical Section..."Skill Book: Physical."
title = ""+subtitle
@title_window.contents.clear
@title_window.contents = Bitmap.new(640 - 32, 64 - 32)
@title_window.contents.draw_text(4, 0, 320, 32, title, 0)
draw_comp(subtitle)
@kind_window.active = false
@kind_window.visible = false
@main_window.active = true
@main_window.index = 0
return
end
# B ??????????
if Input.trigger?(Input::B)
# ????? SE ???
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Map.new
return
end
end
#--------------------------------------------------------------------------
# ? ?????? (?????????????????)
#--------------------------------------------------------------------------
def update_main
# B ??????????
if Input.trigger?(Input::B)
# ????? SE ???
$game_system.se_play($data_system.cancel_se)
@main_window.active = false
@kind_window.active = true
@kind_window.visible = true
@main_window.index = -1
@title_window.contents.clear
@title_window.contents = Bitmap.new(640 - 32, 64 - 32)
@title_window.contents.draw_text(4, 0, 320, 32, "Skill Book", 0)
draw_comp
return
end
# C ??????????
if Input.trigger?(Input::C)
if @main_window.item == nil or
@main_window.show?(@main_window.item_kind, @main_window.item) == false
# ??? SE ???
$game_system.se_play($data_system.buzzer_se)
return
end
# ?? SE ???
$game_system.se_play($data_system.decision_se)
@main_window.active = false
@info_window.active = true
@info_window.visible = true
@visible_index = @main_window.index
@info_window.refresh(@main_window.item, @main_window.item_kind, @main_window.item_index)
return
end
end
#--------------------------------------------------------------------------
# ? ?????? (??????????????????)
#--------------------------------------------------------------------------
def update_info
# B ??????????
if Input.trigger?(Input::B)
# ????? SE ???
$game_system.se_play($data_system.cancel_se)
@main_window.active = true
@info_window.active = false
@info_window.visible = false
@help_window.visible = false
return
end
# C ??????????
if Input.trigger?(Input::C)
# ?? SE ???
$game_system.se_play($data_system.decision_se)
return
end
if Input.trigger?(Input::L)
# ?? SE ???
$game_system.se_play($data_system.decision_se)
loop_end = false
while loop_end == false
if @visible_index != 0
@visible_index -= 1
else
@visible_index = @main_window.data.size - 1
end
loop_end = true if @main_window.show?(@main_window.item_kind,@main_window.data[@visible_index])
end
id = @main_window.data[@visible_index]
@info_window.refresh(id, @main_window.item_kind, @main_window.item_index)
return
end
if Input.trigger?(Input::R)
# ?? SE ???
$game_system.se_play($data_system.decision_se)
loop_end = false
while loop_end == false
if @visible_index != @main_window.data.size - 1
@visible_index += 1
else
@visible_index = 0
end
loop_end = true if @main_window.show?(@main_window.item_kind,@main_window.data[@visible_index])
end
id = @main_window.data[@visible_index]
@info_window.refresh(id, @main_window.item_kind, @main_window.item_index)
return
end
end
def draw_comp(category=nil)
if SHOW_COMPLETE_TYPE != 0
if category == nil
case SHOW_COMPLETE_TYPE
when 1
s_now = $game_system.skill_book_now
s_max = $game_system.skill_book_max
text = s_now.to_s + "/" + s_max.to_s
when 2
comp = $game_system.skill_book_complete_percentage
text = comp.to_s + "%"
when 3
s_now = $game_system.skill_book_now
s_max = $game_system.skill_book_max
comp = $game_system.skill_book_complete_percentage
text = s_now.to_s + "/" + s_max.to_s + " " + comp.to_s + "%"
end
else
case SHOW_COMPLETE_TYPE
when 1
s_now = $game_system.skill_book_category_now(category)
s_max = $game_system.skill_book_category_max(category)
text = s_now.to_s + "/" + s_max.to_s
when 2
comp = $game_system.skill_book_category_complete_percentage(category)
text = comp.to_s + "%"
when 3
s_now = $game_system.skill_book_category_now(category)
s_max = $game_system.skill_book_category_max(category)
comp = $game_system.skill_book_category_complete_percentage(category)
text = s_now.to_s + "/" + s_max.to_s + " " + comp.to_s + "%"
end
end
if text != nil
@title_window.contents.draw_text(320, 0, 288, 32, text, 2)
end
end
end
end
# Item_Book by momomomo?
# http://f53.aaa.livedoor.jp/%7Emomomo/sou...ource.html
#----------------------------------------------------------------
#-Translated by Mcdohl
#----------------------------------------------------------------
#================================
# English is not my main language, so I'm sorry if you can't understand some of my comments.
# 11.18.2005
# Script translated, known bugs:
# -Doesn't seem to work with some custom-skill learning scripts.
# This script will add all the skills you learn throughout the game into a "Book."
# In this book you can see the stats, MP cost, element and states of each skill.
module Skill_Book_Config
# The following line (SHOW_COMPLETE_TYPE =) is very important. It will define how are
# the items counted. (The item count appears on the upper right corner, in the help window.
# Use "0" to display nothing.
# Use "1" to display it in a "items found so far/total" format.
# Use "2" to use percentage completion.
# Use "3" for...a weird item counting method...
SHOW_COMPLETE_TYPE = 3
DRAW_POW_ZERO = false
ZERO_POW_TEXT = ""
end
class Window_SkillBook_Info < Window_Selectable
include Skill_Book_Config
end
class Data_SkillBook
attr_reader :skill_kind_name
attr_reader :kind_row
attr_reader :skill_id_data
attr_reader :skill_kind_element_name
#--------------------------------------------------------------------------
# ? Setup
#--------------------------------------------------------------------------
def initialize
# Name the skill categories.
@skill_kind_name = ["Physical", "Elemental", "Non-Elemental", "Curative", "Status"]
# Next is the menu setup. It's a vertical list. List the categories in any order you want.
# Note: The categories below must coincide with the categories you listed above.
@kind_row = ["Physical",
"Elemental",
"Non-Elemental",
"Curative",
"Status"]
# Now write the element setups.You need to add elements in the Database (in the System Tab). For
# example, if you want to use a "Physical" category, go make an element called "Physical" and
# then apply it to all the skills you want them to appear under the Physical category!
@skill_kind_element_name = ["Physical", "Elemental", "Curative", "Status", "Non-Elemental"]
@skill_id_data = skill_book_id_set
end
#--------------------------------------------------------------------------
# ? Defining Kinds
#--------------------------------------------------------------------------
def kind_search(name)
if @skill_kind_name.include?(name)
return [0, @skill_kind_name.index(name)]
end
end
#--------------------------------------------------------------------------
# ? ???????????
#--------------------------------------------------------------------------
def no_add_element
no_add = 0
# ???????ID???
for i in 1...$data_system.elements.size
if $data_system.elements[i] =~ /??????/
no_add = i
break
end
end
return no_add
end
#--------------------------------------------------------------------------
# ? ?????????ID???
#--------------------------------------------------------------------------
def element_search(element_name)
return nil if element_name == nil
for i in 1...$data_system.elements.size
if $data_system.elements[i] =~ /^#{element_name}/
return i
end
end
end
#--------------------------------------------------------------------------
# ? ??????ID??
#--------------------------------------------------------------------------
def skill_book_id_set
data = []
no_add = no_add_element
if @skill_kind_element_name.size == 0
data[0] = [0]
for i in 1...$data_skills.size
skill = $data_skills[i]
next if skill.name == ""
next if skill.element_set.include?(no_add)
data[0].push(skill.id)
end
else
for i in 0...@skill_kind_element_name.size
data[i] = [0]
element_id = element_search(@skill_kind_element_name[i])
for j in 1...$data_skills.size
skill = $data_skills[j]
next if skill.name == ""
next if skill.element_set.include?(no_add)
if skill.element_set.include?(element_id)
data[i].push(skill.id)
end
end
end
end
return data
end
end
class Game_Actor < Game_Battler
#--------------------------------------------------------------------------
# ? ???????
# skill_id : ??? ID
# This seems to be how the script detects a new skill, this may be the key to making it compatible
# with custom-learning skills scripts, not sure tho.
#--------------------------------------------------------------------------
alias game_actor_skill_book_learn_skill learn_skill
def learn_skill(skill_id)
game_actor_skill_book_learn_skill(skill_id)
$game_system.add_skill_count(skill_id)
end
end
class Window_Base < Window
#--------------------------------------------------------------------------
# ? Element Set Up
# NOTE: Default RTP elements were used.
#--------------------------------------------------------------------------
def draw_attack_element(x, y, element_set)
elem_temp = []
for i in element_set
elem = $data_system.elements[i]
elem_temp.push("Fire") if elem == "Fire"
elem_temp.push("Ice") if elem == "Ice"
elem_temp.push("Thunder") if elem == "Thunder"
elem_temp.push("Water") if elem == "Water"
elem_temp.push("Earth") if elem == "Earth"
elem_temp.push("Wind") if elem == "Wind"
elem_temp.push("Light") if elem == "Light"
elem_temp.push("Darkness") if elem == "Darkness"
end
if elem_temp.size == 0
self.contents.draw_text(x, y, 64, 32, "None")
return
end
ox = 0
for name in elem_temp
cx = self.contents.text_size(name).width
self.contents.draw_text(x+ox, y, cx, 32, name)
ox += cx+8
end
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def draw_attack_wp_element(x, y, element_set)
elem_temp = []
for i in element_set
elem = $data_system.elements[i]
elem_temp.push("?") if elem == "?"
elem_temp.push("?") if elem == "?"
elem_temp.push("?") if elem == "?"
elem_temp.push("?") if elem == "?"
elem_temp.push("?") if elem == "?"
end
if elem_temp.size == 0
self.contents.draw_text(x, y, 64, 32, "??")
return
end
ox = 0
for name in elem_temp
cx = self.contents.text_size(name).width
self.contents.draw_text(x+ox, y, cx, 32, name)
ox += cx+8
end
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def draw_attack_weak_element(x, y, element_set)
elem_temp = []
for i in element_set
elem = $data_system.elements[i]
elem_temp.push("??") if elem == "? ??"
elem_temp.push("?") if elem == "? ?"
elem_temp.push("??") if elem == "? ??"
elem_temp.push("?") if elem == "? ?"
elem_temp.push("?") if elem == "? ?"
elem_temp.push("?") if elem == "? ?"
elem_temp.push("??") if elem == "? ??"
elem_temp.push("??") if elem == "? ??"
end
if elem_temp.size == 0
self.contents.draw_text(x, y, 64, 32, "??")
return
end
ox = 0
for name in elem_temp
cx = self.contents.text_size(name).width
self.contents.draw_text(x+ox, y, cx, 32, name)
ox += cx+8
end
end
#--------------------------------------------------------------------------
# ? States (Status Abnormalities like Poison, Sleep, etc.)
#--------------------------------------------------------------------------
def draw_attack_add_state(x, y, plus_state_set)
state_temp = []
for i in plus_state_set
state = $data_states[i]
state_temp.push(state.name) if state.name != ""
end
if state_temp.size == 0
self.contents.draw_text(x, y, 64, 32, "None")
return
end
ox = 0
oy = 0
for name in state_temp
cx = self.contents.text_size(name).width
if ox + cx + 4 >= self.contents.width - 128
ox = 0
oy += 1
end
self.contents.draw_text(x+ox, y+oy*32, cx, 32, name)
ox += cx+8
end
end
#--------------------------------------------------------------------------
# ? ???????
#--------------------------------------------------------------------------
def draw_scope(scope)
case scope
when 0
return ""
when 1
return ""
when 2
return ""
when 3
return ""
when 4
return ""
when 5
return ""
when 6
return ""
when 7
return ""
end
end
end
class Game_Temp
attr_accessor :skill_book_data
alias temp_skill_book_data_initialize initialize
def initialize
temp_skill_book_data_initialize
@skill_book_data = Data_SkillBook.new
end
end
class Game_System
attr_accessor :skill_count # ???????(???)
#--------------------------------------------------------------------------
# ? ?????????
#--------------------------------------------------------------------------
alias game_system_skill_book_initialize initialize
def initialize
game_system_skill_book_initialize
@skill_count = {}
end
#--------------------------------------------------------------------------
# ? ???????????(???)
# 0:??? 1:???
#--------------------------------------------------------------------------
def add_skill_count(skill_id, type=0)
if type == -1
@skill_count[skill_id] = 0
else
@skill_count[skill_id] = 1
end
end
#--------------------------------------------------------------------------
# ? ??????????????
#--------------------------------------------------------------------------
def skill_book_max
kind_data = $game_temp.skill_book_data.skill_kind_name
size = 0
for kind in kind_data
size += skill_book_category_max(kind)
end
return size
end
#--------------------------------------------------------------------------
# ? ??????????????
#--------------------------------------------------------------------------
def skill_book_now
kind_data = $game_temp.skill_book_data.skill_kind_name
size = 0
for kind in kind_data
size += skill_book_category_now(kind)
end
return size
end
#--------------------------------------------------------------------------
# ? ????????????
#--------------------------------------------------------------------------
def skill_book_complete_percentage
s_max = skill_book_max.to_f
s_now = skill_book_now.to_f
comp = s_now / s_max * 100
return comp.truncate
end
#--------------------------------------------------------------------------
# ? ????????????????????
# category:??????
#--------------------------------------------------------------------------
def skill_book_category_max(category)
id_data = $game_temp.skill_book_data.skill_id_data.dup
index = $game_temp.skill_book_data.kind_search(category)[1]
size = id_data[index].size - 1
return size
end
#--------------------------------------------------------------------------
# ? ????????????????????
# category:??????
#--------------------------------------------------------------------------
def skill_book_category_now(category)
now_skill_info = @skill_count.keys
index = $game_temp.skill_book_data.kind_search(category)[1]
# ???????ID???
no_add = $game_temp.skill_book_data.no_add_element
elename = $game_temp.skill_book_data.skill_kind_element_name[index]
element_id = $game_temp.skill_book_data.element_search(elename)
new_skill_info = []
for i in now_skill_info
skill = $data_skills[i]
next if skill == nil
next if skill.name == ""
next if skill.element_set.include?(no_add)
if element_id == nil or skill.element_set.include?(element_id)
new_skill_info.push(skill.id)
end
end
return new_skill_info.size
end
#--------------------------------------------------------------------------
# ? ??????????????????
# category:??????
#--------------------------------------------------------------------------
def skill_book_category_complete_percentage(category)
s_max = skill_book_category_max(category).to_f
s_now = skill_book_category_now(category).to_f
comp = s_now / s_max * 100
end
end
class Interpreter
def skill_book_max(category=nil)
if category == nil
return $game_system.skill_book_max
else
return $game_system.skill_book_category_max(category)
end
end
def skill_book_now(category=nil)
if category == nil
return $game_system.skill_book_now
else
return $game_system.skill_book_category_now(category)
end
end
def skill_book_comp(category=nil)
if category == nil
return $game_system.skill_book_complete_percentage
else
return $game_system.skill_book_category_complete_percentage(category)
end
end
end
class Window_SkillBook < Window_Selectable
attr_reader :data
attr_reader :item_kind
attr_reader :item_index
#--------------------------------------------------------------------------
# ? ?????????
#--------------------------------------------------------------------------
def initialize(index=0)
super(0, 64, 640, 416)
@column_max = 2
@book_data = $game_temp.skill_book_data
@data = data_set(index)
@data.shift
#@data.sort!
@item_max = @data.size
@item_kind = index
self.index = 0
#refresh
end
def new_data_set(index)
@data = data_set(index)
@data.shift
#@data.sort!
@item_max = @data.size
end
#--------------------------------------------------------------------------
# ? ????????
#--------------------------------------------------------------------------
def data_set(index)
kind_row_data = @book_data.kind_search(@book_data.kind_row[index])
@item_kind = kind_row_data[0]
@item_index = kind_row_data[1]
data = []
case @item_kind
when 0
data = @book_data.skill_id_data[@item_index].dup
end
return data
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def show?(kind, id)
case kind
when 0
if $game_system.skill_count[id] == 0 or $game_system.skill_count[id] == nil
return false
else
return true
end
end
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def item
return @data[self.index]
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def refresh
if self.contents != nil
self.contents.dispose
self.contents = nil
end
#???? 0 ??????????????????????
return if @item_max == 0
self.contents = Bitmap.new(width - 32, row_max * 32)
for i in 0...@item_max
draw_item(i)
end
end
#--------------------------------------------------------------------------
# ? ?????
# index : ????
#--------------------------------------------------------------------------
def draw_item(index)
case @item_kind
when 0
item = $data_skills[@data[index]]
id = @book_data.skill_id_data[@item_index].index(item.id)
end
return if item == nil
x = 4 + index % 2 * (288 + 32)
y = index / 2 * 32
rect = Rect.new(x, y, self.width / @column_max - 32, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
self.contents.font.color = normal_color
self.contents.draw_text(x, y, 32, 32, id.to_s)
if show?(@item_kind, item.id)
bitmap = RPG::Cache.icon(item.icon_name)
opacity = 255
self.contents.blt(x+48, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.draw_text(x+48 + 28, y, 212, 32, item.name, 0)
else
# The "??" are used in blank spaces. (the skills you haven't learned yet)
self.contents.draw_text(x+48 + 28, y, 212, 32, "??", 0)
return
end
end
end
class Window_SkillBook_Info < Window_Selectable
#--------------------------------------------------------------------------
# ? ?????????
#--------------------------------------------------------------------------
def initialize
super(0, 0+64+64, 640, 480-64-64)
@book_data = $game_temp.skill_book_data
self.contents = Bitmap.new(width - 32, height - 32)
self.index = -1
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def refresh(item_id, item_kind, item_index)
self.contents.clear
self.contents.font.size = 22
case item_kind
when 0
draw_skill_info(item_id, item_index)
end
end
#--------------------------------------------------------------------------
# ? ?????
#--------------------------------------------------------------------------
def draw_skill_info(item_id, item_index)
item = $data_skills[item_id]
rect = Rect.new(4, 0, 160, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
bitmap = RPG::Cache.icon(item.icon_name)
opacity = 255
self.contents.blt(4+48, 0 + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.font.color = normal_color
id = @book_data.skill_id_data[item_index].index(item.id)
self.contents.draw_text(4, 0, 32, 32, id.to_s)
self.contents.draw_text(4+48 + 28, 0, 212, 32, item.name, 0)
cost = item.sp_cost.to_s
# Change "MP" to whatever you want. Like "SP" for example, or just leave it in MP.
self.contents.draw_text(4+20 + 28 + 232, 0, 48, 32, "MP:", 2)
self.contents.draw_text(4+48 + 28 + 232, 0, 48, 32, cost.to_s, 2)
#skill_kind = skill_kind_name(item.element_set)
#self.contents.draw_text(320+96, 0, 160, 32, skill_kind, 0)
self.contents.font.color = text_color(2)
self.contents.draw_text(4, 32, 48, 32, "DMG", 0)
self.contents.font.color = normal_color
if item.power == 0 and DRAW_POW_ZERO == false
pow = ZERO_POW_TEXT
else
pow = item.power.to_s
end
self.contents.draw_text(4+48, 32, 48, 32, pow, 2)
self.contents.font.color = system_color
self.contents.draw_text(4, 64, 48, 32, "", 0)
self.contents.font.color = normal_color
self.contents.draw_text(4+96+16, 64, 128, 32, draw_scope(item.scope), 0)
self.contents.font.color = system_color
self.contents.draw_text(4, 96, 96, 32, "Element")
self.contents.draw_text(4, 128, 96, 32, "")
self.contents.draw_text(4, 160, 96, 32, "State")
self.contents.font.color = normal_color
draw_attack_element(4+96+16, 96, item.element_set)
draw_attack_weak_element(4+96+16, 128, item.element_set)
draw_attack_add_state(4+96+16, 160, item.plus_state_set)
@help_window.set_text(item.description)
end
#--------------------------------------------------------------------------
# ? ?????????
#--------------------------------------------------------------------------
def update_help
#???
end
end
class Scene_SkillBook
include Skill_Book_Config
#--------------------------------------------------------------------------
# ? ?????
#--------------------------------------------------------------------------
def main
# ????????
@title_window = Window_Base.new(0, 0, 640, 64)
@title_window.contents = Bitmap.new(640 - 32, 64 - 32)
@title_window.contents.draw_text(4, 0, 320, 32, "Skill Book", 0)
draw_comp
@main_window = Window_SkillBook.new
@main_window.active = false
@main_window.index = -1
@help_window = Window_Help.new
@help_window.z = 110
@help_window.y = 64
@help_window.visible = false
command = $game_temp.skill_book_data.kind_row
@kind_window = Window_Command.new(160, command)
@kind_window.z = 110
@kind_window.x = 320 - @kind_window.width / 2
@kind_window.y = 240 - @kind_window.height / 2
@kind_window.active = true
# ???????????? (?????????????)
@info_window = Window_SkillBook_Info.new
@info_window.z = 110
@info_window.visible = false
@info_window.active = false
# ?????????????
@info_window.help_window = @help_window
@visible_index = 0
@now_kind = nil
# ?????????
Graphics.transition
# ??????
loop do
# ????????
Graphics.update
# ???????
Input.update
# ??????
update
# ????????????????
if $scene != self
break
end
end
# ?????????
Graphics.freeze
# ????????
@title_window.dispose
@help_window.dispose
@main_window.dispose
@kind_window.dispose
@info_window.dispose
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def update
# ????????
#@help_window.update
@main_window.update
@kind_window.update
@info_window.update
if @info_window.active
update_info
return
end
# ?????????????????: update_target ???
if @main_window.active
update_main
return
end
# ????????????????: update_kind ???
if @kind_window.active
update_kind
return
end
end
#--------------------------------------------------------------------------
# ? ?????? (????????????????)
#--------------------------------------------------------------------------
def update_kind
# C ??????????
if Input.trigger?(Input::C)
# ?? SE ???
$game_system.se_play($data_system.decision_se)
if @now_kind != @kind_window.index
@main_window.new_data_set(@kind_window.index)
@main_window.refresh
@now_kind = @kind_window.index
end
subtitle = $game_temp.skill_book_data.kind_row[@kind_window.index]
# This is, when you enter a sub-menu. (for example Physical). Physical is the subtitle, so you
# write a text to go before Armors. The default said "Skill Book:" that way it would look this
# way when you scroll through the Physical Section..."Skill Book: Physical."
title = ""+subtitle
@title_window.contents.clear
@title_window.contents = Bitmap.new(640 - 32, 64 - 32)
@title_window.contents.draw_text(4, 0, 320, 32, title, 0)
draw_comp(subtitle)
@kind_window.active = false
@kind_window.visible = false
@main_window.active = true
@main_window.index = 0
return
end
# B ??????????
if Input.trigger?(Input::B)
# ????? SE ???
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Map.new
return
end
end
#--------------------------------------------------------------------------
# ? ?????? (?????????????????)
#--------------------------------------------------------------------------
def update_main
# B ??????????
if Input.trigger?(Input::B)
# ????? SE ???
$game_system.se_play($data_system.cancel_se)
@main_window.active = false
@kind_window.active = true
@kind_window.visible = true
@main_window.index = -1
@title_window.contents.clear
@title_window.contents = Bitmap.new(640 - 32, 64 - 32)
@title_window.contents.draw_text(4, 0, 320, 32, "Skill Book", 0)
draw_comp
return
end
# C ??????????
if Input.trigger?(Input::C)
if @main_window.item == nil or
@main_window.show?(@main_window.item_kind, @main_window.item) == false
# ??? SE ???
$game_system.se_play($data_system.buzzer_se)
return
end
# ?? SE ???
$game_system.se_play($data_system.decision_se)
@main_window.active = false
@info_window.active = true
@info_window.visible = true
@visible_index = @main_window.index
@info_window.refresh(@main_window.item, @main_window.item_kind, @main_window.item_index)
return
end
end
#--------------------------------------------------------------------------
# ? ?????? (??????????????????)
#--------------------------------------------------------------------------
def update_info
# B ??????????
if Input.trigger?(Input::B)
# ????? SE ???
$game_system.se_play($data_system.cancel_se)
@main_window.active = true
@info_window.active = false
@info_window.visible = false
@help_window.visible = false
return
end
# C ??????????
if Input.trigger?(Input::C)
# ?? SE ???
$game_system.se_play($data_system.decision_se)
return
end
if Input.trigger?(Input::L)
# ?? SE ???
$game_system.se_play($data_system.decision_se)
loop_end = false
while loop_end == false
if @visible_index != 0
@visible_index -= 1
else
@visible_index = @main_window.data.size - 1
end
loop_end = true if @main_window.show?(@main_window.item_kind,@main_window.data[@visible_index])
end
id = @main_window.data[@visible_index]
@info_window.refresh(id, @main_window.item_kind, @main_window.item_index)
return
end
if Input.trigger?(Input::R)
# ?? SE ???
$game_system.se_play($data_system.decision_se)
loop_end = false
while loop_end == false
if @visible_index != @main_window.data.size - 1
@visible_index += 1
else
@visible_index = 0
end
loop_end = true if @main_window.show?(@main_window.item_kind,@main_window.data[@visible_index])
end
id = @main_window.data[@visible_index]
@info_window.refresh(id, @main_window.item_kind, @main_window.item_index)
return
end
end
def draw_comp(category=nil)
if SHOW_COMPLETE_TYPE != 0
if category == nil
case SHOW_COMPLETE_TYPE
when 1
s_now = $game_system.skill_book_now
s_max = $game_system.skill_book_max
text = s_now.to_s + "/" + s_max.to_s
when 2
comp = $game_system.skill_book_complete_percentage
text = comp.to_s + "%"
when 3
s_now = $game_system.skill_book_now
s_max = $game_system.skill_book_max
comp = $game_system.skill_book_complete_percentage
text = s_now.to_s + "/" + s_max.to_s + " " + comp.to_s + "%"
end
else
case SHOW_COMPLETE_TYPE
when 1
s_now = $game_system.skill_book_category_now(category)
s_max = $game_system.skill_book_category_max(category)
text = s_now.to_s + "/" + s_max.to_s
when 2
comp = $game_system.skill_book_category_complete_percentage(category)
text = comp.to_s + "%"
when 3
s_now = $game_system.skill_book_category_now(category)
s_max = $game_system.skill_book_category_max(category)
comp = $game_system.skill_book_category_complete_percentage(category)
text = s_now.to_s + "/" + s_max.to_s + " " + comp.to_s + "%"
end
end
if text != nil
@title_window.contents.draw_text(320, 0, 288, 32, text, 2)
end
end
end
end
Wachuga's Maze Generator:
**BEFORE YOU PUT THIS IN, BE SURE TO PUT NEAR FANTASTICA'S DYNAMIC MAPS SCRIPT IN YOUR GAME!!!**
Instructions:
Installation:
This script has a lot of components to it, so I formatted it slightly differently then my other scripts as far as in the class browser goes.
I made an empty class and called it Maze Generator then under that I made a new empty class called ----------------------.
This is because there are four classes to this script, it organizes it a bit to do it like that.
Quote:Maze Generator
---------------
Game_Map***
Maze
Directional Matrix
Tile
---------------
I will list installation instructions along side the spoiler tags this time around.
Usage:
Now in order to use this you must place <rand> in the map name but there are other things as well. First of all these maps can be saved by putting <save> in the name before <rand>.
Now, if you want to control the randomness of the maze (this only does mazes for now, but Wachunga is now working on a full map generator) you have 3 options. the first <#> after <rand> controls the chances of curves and twists. the second <#> after <rand> decreases the number of dead ends. And the last <#> after <rand> increases the chance that dead ends will connect to another pathway.
Examples:
Quote:My Map <rand>
My Map 2 <rand> <2> <5> <1>
Each time you enter or exit a map that doesnt have <save> in it, it will change, so keep that in mind, also, you must place <start> in an event (I put it in the teleport) name where the begging of the maze is, carful though, the entrance and exits have to be in certain areas, otherwise your going to get a warning message when you try to enter it. Same thing with the exit, put <end> in an event name where you want the end to be at (again, I would put it in the teleport).
Make a new one called Game_Map*** and put this in it:
Game_Map***
=begin
======================
Random Map Generator - version 0.51
======================
by Wachunga, based on Jamis Buck's D&D dungeon generator
==============
Instructions
==============
To indicate a map is to be randomly generated, include <rand> in its
name. You may also optionally specify custom randomness, sparsity and
dead end removal parameters to guide how the map is generated
(see comments within for more details). These may also be included
in the map name, as in this example: "XYZ <rand><0.8><5><0.8>"
(from left to right, randomness, sparsity and deadend removal in that order).
Finally, the optional parameter <save> may immediately follow <rand> to
indicate that the map should be generated randomly the first time but then
saved and remain the same thereafter instead of randomizing again.
Events are not erased on the map which will be randomly generated, but
there is no way to guarantee they'll be positioned correctly. (The only
exceptions to this are two events which determine the start and end of the
maze.)
Place an event named <start> to specify a location you'd like the player to
begin the maze (else a default is chosen). To avoid appearing inside a wall,
the start location should not be at any of the four corners of the map nor
any tile where x is even or y is odd (exceptions occur along an edge of the
map, i.e. when x=0, x=width-1, y=0 or y=height-1). The diagram below may
clarify, where discouraged starting points are marked with an X:
y\x 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
0 X X X X X X X X X X X
1 X X X X X X X X X X X X X X X X X X X X
2 X X X X X X X X X
3 X X X X X X X X X X X X X X X X X X X X
4 X X X X X X X X X
5 X X X X X X X X X X X X X X X X X X X X
6 X X X X X X X X X
7 X X X X X X X X X X X X X X X X X X X X
8 X X X X X X X X X
9 X X X X X X X X X X X X X X X X X X X X
10 X X X X X X X X X
11 X X X X X X X X X X X X X X X X X X X X
12 X X X X X X X X X
13 X X X X X X X X X X X X X X X X X X X X
14 X X X X X X X X X X X
(These restrictions are unfortunate, but necessary. Note as well that if
you're not using a wall face then y SHOULD BE even. Either way,
you should get a warning message if you've placed a start/end incorrectly.)
If you want there to be a passage leading off the map, the start location
must be placed on an edge (i.e. x=0, y=0, x=width-1 or y=height-1).
Alternatively, the start and/or exit locations can be somewhere in the
interior of the map... in this case the player arrives/exits by magic,
falling, climbing, etc.
All the above also applies for the exit location, except the event is named
<end>. Again, a default end is chosen if one is not supplied.
Of course, if the player is to be able to exit the map from either of
these two points, you must make the event teleport appropriately.
Also, the teleport into the maze should point at same square as the <start>
event, or else you may get stuck in a wall.
You can specify which tiles to use for the floor, walls, etc in the Maze
class (just add an appropriate 'elsif').
Questions and feedback should be directed to the thread in the
"User-Submitted RGSS Scripts" forum at http://www.rmxp.net/forums
=end
$save_map_list = []
class Game_Map
alias old_setup_map setup_map
def setup_map(map_id)
old_setup_map(map_id)
tags = map_name.delete(' ').scan(/<[A-Za-z0-9_.]+>/) # get all the tags
if not tags.empty? and tags[0].upcase == '<RAND>'
tags.shift # remove the first element
if not tags.empty? and tags[0].upcase == '<SAVE>'
$save_map_list.push(@map_id)
tags.shift
end
if not tags.empty?
for i in 0...tags.length
tags[i] = tags[i].delete("<>").to_f
end
end
startX = 0; startY = 2 # default starting position
endX = @map.width-1; endY = @map.height-1 # default ending position
# note that these defaults haven't yet been tested much
for i in @map.events.keys
if @map.events[i].name.upcase == '<START>'
startX = @map.events[i].x
startY = @map.events[i].y
elsif @map.events[i].name.upcase == '<END>'
endX = @map.events[i].x
endY = @map.events[i].y
end
end
# note that *tags will expand the array, passing individual elements
# (if any) as arguments (randomness, sparsity and chance to remove deadends)
# e.g. if map name includes "<rand><0.5><10><0.6>", then the call is:
# maze = Maze.new( @map.width, @map.height, startX, startY, endX, endY, 0.5, 10, 0.6)
maze = Maze.new( @map.tileset_id, @map.width, @map.height, startX, startY, endX, endY, *tags)
# set these up for teleports into the maze
maze.draw
end
end
def data=(newdata)
@map.data = newdata
end
def map_name
return load_data("Data/MapInfos.rxdata")[@map_id].name
end
end
======================
Random Map Generator - version 0.51
======================
by Wachunga, based on Jamis Buck's D&D dungeon generator
==============
Instructions
==============
To indicate a map is to be randomly generated, include <rand> in its
name. You may also optionally specify custom randomness, sparsity and
dead end removal parameters to guide how the map is generated
(see comments within for more details). These may also be included
in the map name, as in this example: "XYZ <rand><0.8><5><0.8>"
(from left to right, randomness, sparsity and deadend removal in that order).
Finally, the optional parameter <save> may immediately follow <rand> to
indicate that the map should be generated randomly the first time but then
saved and remain the same thereafter instead of randomizing again.
Events are not erased on the map which will be randomly generated, but
there is no way to guarantee they'll be positioned correctly. (The only
exceptions to this are two events which determine the start and end of the
maze.)
Place an event named <start> to specify a location you'd like the player to
begin the maze (else a default is chosen). To avoid appearing inside a wall,
the start location should not be at any of the four corners of the map nor
any tile where x is even or y is odd (exceptions occur along an edge of the
map, i.e. when x=0, x=width-1, y=0 or y=height-1). The diagram below may
clarify, where discouraged starting points are marked with an X:
y\x 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
0 X X X X X X X X X X X
1 X X X X X X X X X X X X X X X X X X X X
2 X X X X X X X X X
3 X X X X X X X X X X X X X X X X X X X X
4 X X X X X X X X X
5 X X X X X X X X X X X X X X X X X X X X
6 X X X X X X X X X
7 X X X X X X X X X X X X X X X X X X X X
8 X X X X X X X X X
9 X X X X X X X X X X X X X X X X X X X X
10 X X X X X X X X X
11 X X X X X X X X X X X X X X X X X X X X
12 X X X X X X X X X
13 X X X X X X X X X X X X X X X X X X X X
14 X X X X X X X X X X X
(These restrictions are unfortunate, but necessary. Note as well that if
you're not using a wall face then y SHOULD BE even. Either way,
you should get a warning message if you've placed a start/end incorrectly.)
If you want there to be a passage leading off the map, the start location
must be placed on an edge (i.e. x=0, y=0, x=width-1 or y=height-1).
Alternatively, the start and/or exit locations can be somewhere in the
interior of the map... in this case the player arrives/exits by magic,
falling, climbing, etc.
All the above also applies for the exit location, except the event is named
<end>. Again, a default end is chosen if one is not supplied.
Of course, if the player is to be able to exit the map from either of
these two points, you must make the event teleport appropriately.
Also, the teleport into the maze should point at same square as the <start>
event, or else you may get stuck in a wall.
You can specify which tiles to use for the floor, walls, etc in the Maze
class (just add an appropriate 'elsif').
Questions and feedback should be directed to the thread in the
"User-Submitted RGSS Scripts" forum at http://www.rmxp.net/forums
=end
$save_map_list = []
class Game_Map
alias old_setup_map setup_map
def setup_map(map_id)
old_setup_map(map_id)
tags = map_name.delete(' ').scan(/<[A-Za-z0-9_.]+>/) # get all the tags
if not tags.empty? and tags[0].upcase == '<RAND>'
tags.shift # remove the first element
if not tags.empty? and tags[0].upcase == '<SAVE>'
$save_map_list.push(@map_id)
tags.shift
end
if not tags.empty?
for i in 0...tags.length
tags[i] = tags[i].delete("<>").to_f
end
end
startX = 0; startY = 2 # default starting position
endX = @map.width-1; endY = @map.height-1 # default ending position
# note that these defaults haven't yet been tested much
for i in @map.events.keys
if @map.events[i].name.upcase == '<START>'
startX = @map.events[i].x
startY = @map.events[i].y
elsif @map.events[i].name.upcase == '<END>'
endX = @map.events[i].x
endY = @map.events[i].y
end
end
# note that *tags will expand the array, passing individual elements
# (if any) as arguments (randomness, sparsity and chance to remove deadends)
# e.g. if map name includes "<rand><0.5><10><0.6>", then the call is:
# maze = Maze.new( @map.width, @map.height, startX, startY, endX, endY, 0.5, 10, 0.6)
maze = Maze.new( @map.tileset_id, @map.width, @map.height, startX, startY, endX, endY, *tags)
# set these up for teleports into the maze
maze.draw
end
end
def data=(newdata)
@map.data = newdata
end
def map_name
return load_data("Data/MapInfos.rxdata")[@map_id].name
end
end
Now, under that class make a new one called 'Maze' and put this into it:
Maze
class Maze
WALL = 0
PASSAGE = 1
attr_reader :width
attr_reader :height
attr_reader :startX
attr_reader :startY
attr_reader :endX
attr_reader :endY
def initialize(pTileset, pWidth, pHeight, pStartX, pStartY, pEndX, pEndY,
pRandomness=0.5, pSparsity=3, pRemovalChance=0.5)
@tileset = pTileset
@width = pWidth
@height = pHeight
@startX = pStartX
@startY = pStartY
@endX = pEndX
@endY = pEndY
# prepare the base matrix
@base = Direction_Matrix.new(@width, @height, @startX, @startY, @endX, @endY, pRandomness, pSparsity, pRemovalChance)
# reset everything in the Tile module to 0
Tile.floor = 0
Tile.wall = 0
Tile.wallFace = 0
# prepare the tiles depending on the tileset
if @tileset == 27
Tile.setFloor(2,1) # 384
Tile.setWall(1,2) # 48-95
Tile.setWallFace(4,2) # 401
elsif @tileset == 51
Tile.setFloor(2,2) # 384
Tile.setWall(2,1) # 385
#elsif @tileset == 'y'
# others go here
else
# nothing specified so just use default
Tile.setFloor(2,1) # 384
Tile.setWall(1,2) # 48-95
end
# if no wall face is being used, then Y locations should be ODD (opposite of
# when using a wall face)
if (@startX % 2) == 0 and @startX != 0 and @startX != @width-1
print 'Warning: player may start in a wall (starting X location is even).'
end
if Tile.wallFace != 0
if (@startY % 2) != 0 and @startY != 0 and @startY != @height-1
print 'Warning: player may start in a wall (starting Y location is odd).'
end
else
if (@startY % 2) == 0 and @startY != 0 and @startY != @height-1
print 'Warning: player may start in a wall (starting Y location is even).'
end
end
if (@endX % 2) == 0 and @endX != 0 and @endX != @width-1
print 'Warning: maze end may be unreachable (X location is even).'
end
if Tile.wallFace != 0
if (@endY % 2) != 0 and @endY != 0 and @endY != @height-1
print 'Warning: maze end may be unreachable (Y location is odd).'
end
else
if (@endY % 2) == 0 and @endY != 0 and @endY != @height-1
print 'Warning: maze end may be unreachable (Y location is even).'
end
end
# initialized with all walls
@matrix = Array.new(@width, WALL)
for i in 0...@width
@matrix[i] = Array.new(@height, WALL)
end
setup
end
=begin
Sets up the actual maze from a base matrix of only directions.
(Basic algorithm from Jamis Buck's D&D dungeon generator.)
=end
def setup
for x in 0...@base.width
for y in 0...@base.height
dir = @base.matrix[x][y]
if (dir != 0) # not sparsified
@matrix[x*2+1][y*2+1] = PASSAGE
end
if ((dir & Direction_Matrix::NORTH) != 0)
@matrix[x*2+1][y*2] = PASSAGE
end
if ((dir & Direction_Matrix::WEST) != 0)
@matrix[x*2][y*2+1] = PASSAGE
end
# only necessary for right edge start/exit
if ((dir & Direction_Matrix::EAST) != 0)
@matrix[x*2+2][y*2+1] = PASSAGE
# if extra wall is there, need to "dig deeper"
if (@width % 2) == 0 and x*2+3 == @width-1
@matrix[x*2+3][y*2+1] = PASSAGE
end
end
# only necessary for bottom edge start/exit
if ((dir & Direction_Matrix::SOUTH) != 0)
@matrix[x*2+1][y*2+2] = PASSAGE
# if extra wall is there, need to "dig deeper"
if (@height % 2) == 0 and y*2+3 == @height-1
@matrix[x*2+1][y*2+3] = PASSAGE
end
end
end
end
end
=begin
Display the matrix in an ASCII table (useful for debugging).
(Much more readable if you're using a monospaced font for dialog boxes.)
=end
def display
char_array = Array.new(@width, 0)
for i in 0...@width
char_array[i] = Array.new(@height, 0)
end
for x in 0...@width
for y in 0...@height
tile = @matrix[x][y]
char = ' '
if ((tile == WALL)) then char << '#' end
if ((tile == PASSAGE)) then char << ' ' end
char_array[y][x] = char
end
end
display = ''
for i in 0...@height
display << char_array[i].flatten.to_s << "\n"
end
print display
end
=begin
Draw the maze using the map's tileset.
=end
def draw
newdata = Table.new(@width, @height, 3)
# put down the floor on the first layer (z=0)
z = 0
for x in 0...@width
for y in 0...@height
newdata[x,y,z] = Tile.floor
end
end
# now for the walls on the second layer (z=1)
z = 1
if Tile.wall.type.to_s.upcase != "HASH" # not autotiles
for x in 0...@width
for y in 0...@height
newdata[x,y,z] = Tile.wall if (@matrix[x][y] == WALL)
end
end
else # autotiles...
for x in 0...@width
for y in 0...@height
# skip passages
if (@matrix[x][y] == PASSAGE) then next end
# calculate adjacent walls
adj = ''
if (x == 0)
adj << '147'
else
if (y == 0) then adj << '1'
else
if (@matrix[x-1][y-1] == WALL) then adj << '1' end
end
if (@matrix[x-1][y] == WALL) then adj << '4' end
if (y == @height-1) then adj << '7'
else
if (@matrix[x-1][y+1] == WALL) then adj << '7' end
end
end
if (x == @width-1)
adj << '369'
else
if (y == 0) then adj << '3'
else
if (@matrix[x+1][y-1] == WALL) then adj << '3' end
end
if (@matrix[x+1][y] == WALL) then adj << '6' end
if (y == @height-1) then adj << '9'
else
if (@matrix[x+1][y+1] == WALL) then adj << '9' end
end
end
if (y == 0)
adj << '2'
else
if (@matrix[x][y-1] == WALL) then adj << '2' end
end
if (y == @height-1)
adj << '8'
else
if (@matrix[x][y+1] == WALL) then adj << '8' end
end
# if no adjacent walls, set it as 0
if (adj == '') then adj = '0' end
# convert to an array, sort, and then back to a string
adj = adj.split(//).sort.join
newdata[x,y,z] = eval 'Tile.wall[adj.to_i]'
# show single wall tile beneath bottom-facing walls
if Tile.wallFace > 0
if not adj.include?('8')
newdata[x,y+1,z] = Tile.wallFace
end
end
end # for
end # for
end # if-else
$game_map.data = newdata
end # draw method
end
WALL = 0
PASSAGE = 1
attr_reader :width
attr_reader :height
attr_reader :startX
attr_reader :startY
attr_reader :endX
attr_reader :endY
def initialize(pTileset, pWidth, pHeight, pStartX, pStartY, pEndX, pEndY,
pRandomness=0.5, pSparsity=3, pRemovalChance=0.5)
@tileset = pTileset
@width = pWidth
@height = pHeight
@startX = pStartX
@startY = pStartY
@endX = pEndX
@endY = pEndY
# prepare the base matrix
@base = Direction_Matrix.new(@width, @height, @startX, @startY, @endX, @endY, pRandomness, pSparsity, pRemovalChance)
# reset everything in the Tile module to 0
Tile.floor = 0
Tile.wall = 0
Tile.wallFace = 0
# prepare the tiles depending on the tileset
if @tileset == 27
Tile.setFloor(2,1) # 384
Tile.setWall(1,2) # 48-95
Tile.setWallFace(4,2) # 401
elsif @tileset == 51
Tile.setFloor(2,2) # 384
Tile.setWall(2,1) # 385
#elsif @tileset == 'y'
# others go here
else
# nothing specified so just use default
Tile.setFloor(2,1) # 384
Tile.setWall(1,2) # 48-95
end
# if no wall face is being used, then Y locations should be ODD (opposite of
# when using a wall face)
if (@startX % 2) == 0 and @startX != 0 and @startX != @width-1
print 'Warning: player may start in a wall (starting X location is even).'
end
if Tile.wallFace != 0
if (@startY % 2) != 0 and @startY != 0 and @startY != @height-1
print 'Warning: player may start in a wall (starting Y location is odd).'
end
else
if (@startY % 2) == 0 and @startY != 0 and @startY != @height-1
print 'Warning: player may start in a wall (starting Y location is even).'
end
end
if (@endX % 2) == 0 and @endX != 0 and @endX != @width-1
print 'Warning: maze end may be unreachable (X location is even).'
end
if Tile.wallFace != 0
if (@endY % 2) != 0 and @endY != 0 and @endY != @height-1
print 'Warning: maze end may be unreachable (Y location is odd).'
end
else
if (@endY % 2) == 0 and @endY != 0 and @endY != @height-1
print 'Warning: maze end may be unreachable (Y location is even).'
end
end
# initialized with all walls
@matrix = Array.new(@width, WALL)
for i in 0...@width
@matrix[i] = Array.new(@height, WALL)
end
setup
end
=begin
Sets up the actual maze from a base matrix of only directions.
(Basic algorithm from Jamis Buck's D&D dungeon generator.)
=end
def setup
for x in 0...@base.width
for y in 0...@base.height
dir = @base.matrix[x][y]
if (dir != 0) # not sparsified
@matrix[x*2+1][y*2+1] = PASSAGE
end
if ((dir & Direction_Matrix::NORTH) != 0)
@matrix[x*2+1][y*2] = PASSAGE
end
if ((dir & Direction_Matrix::WEST) != 0)
@matrix[x*2][y*2+1] = PASSAGE
end
# only necessary for right edge start/exit
if ((dir & Direction_Matrix::EAST) != 0)
@matrix[x*2+2][y*2+1] = PASSAGE
# if extra wall is there, need to "dig deeper"
if (@width % 2) == 0 and x*2+3 == @width-1
@matrix[x*2+3][y*2+1] = PASSAGE
end
end
# only necessary for bottom edge start/exit
if ((dir & Direction_Matrix::SOUTH) != 0)
@matrix[x*2+1][y*2+2] = PASSAGE
# if extra wall is there, need to "dig deeper"
if (@height % 2) == 0 and y*2+3 == @height-1
@matrix[x*2+1][y*2+3] = PASSAGE
end
end
end
end
end
=begin
Display the matrix in an ASCII table (useful for debugging).
(Much more readable if you're using a monospaced font for dialog boxes.)
=end
def display
char_array = Array.new(@width, 0)
for i in 0...@width
char_array[i] = Array.new(@height, 0)
end
for x in 0...@width
for y in 0...@height
tile = @matrix[x][y]
char = ' '
if ((tile == WALL)) then char << '#' end
if ((tile == PASSAGE)) then char << ' ' end
char_array[y][x] = char
end
end
display = ''
for i in 0...@height
display << char_array[i].flatten.to_s << "\n"
end
print display
end
=begin
Draw the maze using the map's tileset.
=end
def draw
newdata = Table.new(@width, @height, 3)
# put down the floor on the first layer (z=0)
z = 0
for x in 0...@width
for y in 0...@height
newdata[x,y,z] = Tile.floor
end
end
# now for the walls on the second layer (z=1)
z = 1
if Tile.wall.type.to_s.upcase != "HASH" # not autotiles
for x in 0...@width
for y in 0...@height
newdata[x,y,z] = Tile.wall if (@matrix[x][y] == WALL)
end
end
else # autotiles...
for x in 0...@width
for y in 0...@height
# skip passages
if (@matrix[x][y] == PASSAGE) then next end
# calculate adjacent walls
adj = ''
if (x == 0)
adj << '147'
else
if (y == 0) then adj << '1'
else
if (@matrix[x-1][y-1] == WALL) then adj << '1' end
end
if (@matrix[x-1][y] == WALL) then adj << '4' end
if (y == @height-1) then adj << '7'
else
if (@matrix[x-1][y+1] == WALL) then adj << '7' end
end
end
if (x == @width-1)
adj << '369'
else
if (y == 0) then adj << '3'
else
if (@matrix[x+1][y-1] == WALL) then adj << '3' end
end
if (@matrix[x+1][y] == WALL) then adj << '6' end
if (y == @height-1) then adj << '9'
else
if (@matrix[x+1][y+1] == WALL) then adj << '9' end
end
end
if (y == 0)
adj << '2'
else
if (@matrix[x][y-1] == WALL) then adj << '2' end
end
if (y == @height-1)
adj << '8'
else
if (@matrix[x][y+1] == WALL) then adj << '8' end
end
# if no adjacent walls, set it as 0
if (adj == '') then adj = '0' end
# convert to an array, sort, and then back to a string
adj = adj.split(//).sort.join
newdata[x,y,z] = eval 'Tile.wall[adj.to_i]'
# show single wall tile beneath bottom-facing walls
if Tile.wallFace > 0
if not adj.include?('8')
newdata[x,y+1,z] = Tile.wallFace
end
end
end # for
end # for
end # if-else
$game_map.data = newdata
end # draw method
end
Under this class make another new one called 'Direction Matrix' and put this into it:
Directional Matrix
=begin
A matrix whose elements each contains 1-4 directions (north, east, south,
west) forming the basis for a maze or dungeon.
(Basic algorithms from Jamis Buck's D&D dungeon generator.)
=end
class Direction_Matrix
NORTH = 0b00001
EAST = 0b00010
SOUTH = 0b00100
WEST = 0b01000
ALL_DIRS = NORTH | EAST | SOUTH | WEST
FLAG = 0b10000
attr_reader :width
attr_reader :height
attr_reader :matrix
def initialize(pWidth, pHeight, pStartX, pStartY, pEndX, pEndY,
pRandomness, pSparsity, pRemovalChance)
@width = pWidth/2
@height = pHeight/2
# convert to Direction_Matrix's dimensions
@startX = pStartX/2
@startY = pStartY/2
@endX = pEndX/2
@endY = pEndY/2
# if even, decrement by 1
@width -= 1 if (pWidth % 2 == 0)
@height -= 1 if (pHeight % 2 == 0)
if @startX != 0
@startX -= 1 if (pStartX % 2 == 0)
end
if @startY != 0
@startY -= 1 if (pStartY % 2 == 0)
end
if @endX != 0
@endX -= 1 if (pEndX % 2 == 0)
end
if @endY != 0
@endY -= 1 if (pEndY % 2 == 0)
end
# handle a weird situation
if @startX >= @width then @startX = @width-1 end
if @endX >= @width then @endX = @width-1 end
@randomness = pRandomness
@sparsity = pSparsity
@removalChance = pRemovalChance
@matrix = Array.new(@width, 0)
for i in 0...@width
@matrix[i] = Array.new(@height, 0)
end
generate
# we need the original start/end locations and width/height in these cases
if pStartY == 0
@matrix[@startX][@startY] |= NORTH
elsif pStartX == 0
@matrix[@startX][@startY] |= WEST
elsif (pStartX == @width*2+1 and (pWidth % 2) == 0) or
(pStartX == @width*2 and (pWidth % 2) != 0)
@matrix[@startX][@startY] |= EAST
elsif (pStartY == @height*2+1 and (pHeight % 2) == 0) or
(pStartY == @height*2 and (pHeight % 2) != 0)
@matrix[@startX][@startY] |= SOUTH
end
if pEndY == 0
@matrix[@endX][@endY] |= NORTH
elsif pEndX == 0
@matrix[@endX][@endY] |= WEST
elsif (pEndX == @width*2+1 and (pWidth % 2) == 0) or
(pEndX == @width*2 and (pWidth % 2) != 0)
@matrix[@endX][@endY] |= EAST
elsif (pEndY == @height*2+1 and (pHeight % 2) == 0) or
(pEndY == @height*2 and (pHeight % 2) != 0)
@matrix[@endX][@endY] |= SOUTH
end
sparsify
removeDeadends
end
=begin
The algorithm for generating random mazes is as follows:
(1) randomly pick a starting tile from the map
(2) pick a random direction and move that way as long as there
is a new tile in that direction and hasn't been visited yet
(3) perform (2) until there is no valid direction to move in, then
pick a new tile that HAS been visited before and perform (2)
and (3) until all the tiles have been visited
=end
def generate
testedDirs = lastDir = straightStretch = 0
x = @startX
y = @startY
remaining = @width * @height - 1
# loop for all remaining tiles
while (remaining > 0)
if (testedDirs == ALL_DIRS)
# we're stuck so choose an already-visited tile
while true
x = rand(@width)
y = rand(@height)
break if @matrix[x][y] != 0
end
testedDirs = @matrix[x][y]
end
# eliminate impossible directions
if (x < 1) then testedDirs |= WEST
elsif (x+1 > @width) then testedDirs |= EAST
end
if (y < 1) then testedDirs |= NORTH
elsif (y+1 > @height) then testedDirs |= SOUTH
end
randomSelection = false
# depending on randomness parameter of map,
# either select direction randomly or continue straight
# (but no stretch can be longer than half the width/height)
if ( rand < @randomness)
randomSelection = true
else
case lastDir
when NORTH
if ( y>0 and straightStretch < @height/2 and @matrix[x][y-1]==0 )
direction = lastDir
else randomSelection = true
end
when EAST
if ( x+1<@width and straightStretch < @width/2 and @matrix[x+1][y]==0 )
direction = lastDir
else randomSelection = true
end
when SOUTH
if ( y+1<@height and straightStretch < @height/2 and @matrix[x][y+1]==0 )
direction = lastDir
else randomSelection = true
end
when WEST
if ( x>0 and straightStretch < @width/2 and @matrix[x-1][y]==0 )
direction = lastDir
else randomSelection = true
end
else randomSelection = true
end
end
if (randomSelection)
# reset
direction = 0
straightStretch = 0
# pick random direction
# keep trying until a valid one is found
while ( (direction == 0) or ((testedDirs & direction) != 0) )
temp_x = x
temp_y = y
case rand(4)
when 0 # north
if (y > 0) then direction = NORTH; temp_y-=1
else testedDirs |= NORTH
end
when 1 # east
if (x+1 < @width) then direction = EAST; temp_x+=1
else testedDirs |= EAST
end
when 2 # south
if (y+1 < @height) then direction = SOUTH; temp_y+=1
else testedDirs |= SOUTH
end
when 3 # west
if (x > 0) then direction = WEST; temp_x-=1
else testedDirs |= WEST
end
end
# check next square to ensure it's valid
if ( @matrix[temp_x][temp_y] != 0 )
# record direction as tested
testedDirs |= direction
# if all directions are invalid, impossible to
# select random direction so break out
if (testedDirs == ALL_DIRS) then break end
direction = 0
end
end
else
straightStretch+=1
end
# if all directions are tested, move on to next
# iteration where an already-visited tile will be picked
if (testedDirs == ALL_DIRS) then next end
lastDir = direction
# set selected direction in maze at both current tile
# and destination tile
@matrix[x][y] |= direction
case direction
when NORTH then y-=1; direction = SOUTH
when EAST then x+=1; direction = WEST
when SOUTH then y+=1; direction = NORTH
when WEST then x-=1; direction = EAST
end
@matrix[x][y] |= direction
testedDirs = @matrix[x][y]
remaining-=1
end
end
=begin
Sparsify the maze by the given amount ("sparsity") representing the
number of times to sparsify (i.e. shorten deadends, creating empty areas so the
maze isn't perfectly dense).
A smaller maze will sparsify faster than a larger maze, so the smaller the maze,
the smaller the number should be to accomplish the same relative amount of "sparsification".
=end
def sparsify
for i in 0...@sparsity
for x in 0...@width
for y in 0...@height
# don't sparsify from the beginning or end points --
# this guarantees a solution to the maze
if (x == @startX) and (y == @startY) then next end
if (x == @endX) and (y == @endY) then next end
dir = @matrix[x][y]
# if only one direction, found a deadend
# so otherwise, go to next tile
if not [NORTH, EAST, SOUTH, WEST].include?(dir)
next
end
# remove deadend
@matrix[x][y] = 0
# for previous tile, remove direction to removed deadend
# also temporarily flag it as visited so any new deadends
# created aren't sparsified in the same pass
case dir
when NORTH
@matrix[x][y-1] &= ~SOUTH
@matrix[x][y-1] |= FLAG
when EAST
@matrix[x+1][y] &= ~WEST
@matrix[x+1][y] |= FLAG
when SOUTH
@matrix[x][y+1] &= ~NORTH
@matrix[x][y+1] |= FLAG
when WEST
@matrix[x-1][y] &= ~EAST
@matrix[x-1][y] |= FLAG
end
end
end
# clear the flags for the next sparsifying pass
for x in 0...@width
for y in 0...@height
@matrix[x][y] &= ~FLAG
end
end
end
end
=begin
Display the matrix in an ASCII table (useful for debugging)
(Much more readable if you're using a monospaced font for dialog boxes.)
=end
def display
char_array = Array.new(@width, 0)
for i in 0...@width
char_array[i] = Array.new(@height, 0)
end
for x in 0...@width
for y in 0...@height
dir = @matrix[x][y]
char = '['
if ((dir & NORTH) != 0) then char << 'N' else char << ' ' end
if ((dir & EAST) != 0) then char << 'E' else char << ' ' end
if ((dir & WEST) != 0) then char << 'W' else char << ' ' end
if ((dir & SOUTH) != 0) then char << 'S' else char << ' ' end
char << ']'
char_array[y][x] = char
end
end
display = ''
for i in 0...@height
display << char_array[i].flatten.to_s << "\n"
end
print display
end
=begin
Clears the given percentage ("removalChance") of deadends from the maze by
causing the deadends to extend until they hit another passage. As this
causes cycles in the maze, it can result in multiple possible solutions
to the maze (but makes it seem more natural).
=end
def removeDeadends
for x in 0...@width
for y in 0...@height
dir = @matrix[x][y]
# if only one direction, found a deadend
# so otherwise, go to next tile
if not [NORTH, EAST, SOUTH, WEST].include?(dir)
next
end
# random roll to see if this deadend is skipped
if (rand > @removalChance) then next end
cur_x = x; cur_y = y
back_dir = dir
# continue as long as new corridor not reached
while (@matrix[cur_x][cur_y] == back_dir)
direction = 0
testedDirs = 0
# pick random direction
# keep trying until a valid one is found
while (direction == 0)
temp_x = cur_x
temp_y = cur_y
case rand(4)
when 0 # north
if (cur_y > 0) then direction = NORTH; back_dir = SOUTH; temp_y-=1
else testedDirs |= NORTH
end
when 1 # east
if (cur_x+1 < @width) then direction = EAST; back_dir = WEST; temp_x+=1
else testedDirs |= EAST
end
when 2 # south
if (cur_y+1 < @height) then direction = SOUTH; back_dir = NORTH; temp_y+=1
else testedDirs |= SOUTH
end
when 3 # west
if (cur_x > 0) then direction = WEST; back_dir = EAST; temp_x-=1
else testedDirs |= WEST
end
end
# check if deadend tile already goes this way
if ( @matrix[cur_x][cur_y] == direction )
# record direction as tested
testedDirs |= direction
direction = 0
end
# if all directions are invalid, impossible to
# select random direction so break out
if (testedDirs == ALL_DIRS) then break end
end
if (testedDirs == ALL_DIRS) then break end
# add new direction to deadend
@matrix[cur_x][cur_y] |= direction
# add new direction to tile adjacent to deadend
@matrix[temp_x][temp_y] |= back_dir
# move on to next tile
cur_x = temp_x; cur_y = temp_y
end
end
end
end
end
A matrix whose elements each contains 1-4 directions (north, east, south,
west) forming the basis for a maze or dungeon.
(Basic algorithms from Jamis Buck's D&D dungeon generator.)
=end
class Direction_Matrix
NORTH = 0b00001
EAST = 0b00010
SOUTH = 0b00100
WEST = 0b01000
ALL_DIRS = NORTH | EAST | SOUTH | WEST
FLAG = 0b10000
attr_reader :width
attr_reader :height
attr_reader :matrix
def initialize(pWidth, pHeight, pStartX, pStartY, pEndX, pEndY,
pRandomness, pSparsity, pRemovalChance)
@width = pWidth/2
@height = pHeight/2
# convert to Direction_Matrix's dimensions
@startX = pStartX/2
@startY = pStartY/2
@endX = pEndX/2
@endY = pEndY/2
# if even, decrement by 1
@width -= 1 if (pWidth % 2 == 0)
@height -= 1 if (pHeight % 2 == 0)
if @startX != 0
@startX -= 1 if (pStartX % 2 == 0)
end
if @startY != 0
@startY -= 1 if (pStartY % 2 == 0)
end
if @endX != 0
@endX -= 1 if (pEndX % 2 == 0)
end
if @endY != 0
@endY -= 1 if (pEndY % 2 == 0)
end
# handle a weird situation
if @startX >= @width then @startX = @width-1 end
if @endX >= @width then @endX = @width-1 end
@randomness = pRandomness
@sparsity = pSparsity
@removalChance = pRemovalChance
@matrix = Array.new(@width, 0)
for i in 0...@width
@matrix[i] = Array.new(@height, 0)
end
generate
# we need the original start/end locations and width/height in these cases
if pStartY == 0
@matrix[@startX][@startY] |= NORTH
elsif pStartX == 0
@matrix[@startX][@startY] |= WEST
elsif (pStartX == @width*2+1 and (pWidth % 2) == 0) or
(pStartX == @width*2 and (pWidth % 2) != 0)
@matrix[@startX][@startY] |= EAST
elsif (pStartY == @height*2+1 and (pHeight % 2) == 0) or
(pStartY == @height*2 and (pHeight % 2) != 0)
@matrix[@startX][@startY] |= SOUTH
end
if pEndY == 0
@matrix[@endX][@endY] |= NORTH
elsif pEndX == 0
@matrix[@endX][@endY] |= WEST
elsif (pEndX == @width*2+1 and (pWidth % 2) == 0) or
(pEndX == @width*2 and (pWidth % 2) != 0)
@matrix[@endX][@endY] |= EAST
elsif (pEndY == @height*2+1 and (pHeight % 2) == 0) or
(pEndY == @height*2 and (pHeight % 2) != 0)
@matrix[@endX][@endY] |= SOUTH
end
sparsify
removeDeadends
end
=begin
The algorithm for generating random mazes is as follows:
(1) randomly pick a starting tile from the map
(2) pick a random direction and move that way as long as there
is a new tile in that direction and hasn't been visited yet
(3) perform (2) until there is no valid direction to move in, then
pick a new tile that HAS been visited before and perform (2)
and (3) until all the tiles have been visited
=end
def generate
testedDirs = lastDir = straightStretch = 0
x = @startX
y = @startY
remaining = @width * @height - 1
# loop for all remaining tiles
while (remaining > 0)
if (testedDirs == ALL_DIRS)
# we're stuck so choose an already-visited tile
while true
x = rand(@width)
y = rand(@height)
break if @matrix[x][y] != 0
end
testedDirs = @matrix[x][y]
end
# eliminate impossible directions
if (x < 1) then testedDirs |= WEST
elsif (x+1 > @width) then testedDirs |= EAST
end
if (y < 1) then testedDirs |= NORTH
elsif (y+1 > @height) then testedDirs |= SOUTH
end
randomSelection = false
# depending on randomness parameter of map,
# either select direction randomly or continue straight
# (but no stretch can be longer than half the width/height)
if ( rand < @randomness)
randomSelection = true
else
case lastDir
when NORTH
if ( y>0 and straightStretch < @height/2 and @matrix[x][y-1]==0 )
direction = lastDir
else randomSelection = true
end
when EAST
if ( x+1<@width and straightStretch < @width/2 and @matrix[x+1][y]==0 )
direction = lastDir
else randomSelection = true
end
when SOUTH
if ( y+1<@height and straightStretch < @height/2 and @matrix[x][y+1]==0 )
direction = lastDir
else randomSelection = true
end
when WEST
if ( x>0 and straightStretch < @width/2 and @matrix[x-1][y]==0 )
direction = lastDir
else randomSelection = true
end
else randomSelection = true
end
end
if (randomSelection)
# reset
direction = 0
straightStretch = 0
# pick random direction
# keep trying until a valid one is found
while ( (direction == 0) or ((testedDirs & direction) != 0) )
temp_x = x
temp_y = y
case rand(4)
when 0 # north
if (y > 0) then direction = NORTH; temp_y-=1
else testedDirs |= NORTH
end
when 1 # east
if (x+1 < @width) then direction = EAST; temp_x+=1
else testedDirs |= EAST
end
when 2 # south
if (y+1 < @height) then direction = SOUTH; temp_y+=1
else testedDirs |= SOUTH
end
when 3 # west
if (x > 0) then direction = WEST; temp_x-=1
else testedDirs |= WEST
end
end
# check next square to ensure it's valid
if ( @matrix[temp_x][temp_y] != 0 )
# record direction as tested
testedDirs |= direction
# if all directions are invalid, impossible to
# select random direction so break out
if (testedDirs == ALL_DIRS) then break end
direction = 0
end
end
else
straightStretch+=1
end
# if all directions are tested, move on to next
# iteration where an already-visited tile will be picked
if (testedDirs == ALL_DIRS) then next end
lastDir = direction
# set selected direction in maze at both current tile
# and destination tile
@matrix[x][y] |= direction
case direction
when NORTH then y-=1; direction = SOUTH
when EAST then x+=1; direction = WEST
when SOUTH then y+=1; direction = NORTH
when WEST then x-=1; direction = EAST
end
@matrix[x][y] |= direction
testedDirs = @matrix[x][y]
remaining-=1
end
end
=begin
Sparsify the maze by the given amount ("sparsity") representing the
number of times to sparsify (i.e. shorten deadends, creating empty areas so the
maze isn't perfectly dense).
A smaller maze will sparsify faster than a larger maze, so the smaller the maze,
the smaller the number should be to accomplish the same relative amount of "sparsification".
=end
def sparsify
for i in 0...@sparsity
for x in 0...@width
for y in 0...@height
# don't sparsify from the beginning or end points --
# this guarantees a solution to the maze
if (x == @startX) and (y == @startY) then next end
if (x == @endX) and (y == @endY) then next end
dir = @matrix[x][y]
# if only one direction, found a deadend
# so otherwise, go to next tile
if not [NORTH, EAST, SOUTH, WEST].include?(dir)
next
end
# remove deadend
@matrix[x][y] = 0
# for previous tile, remove direction to removed deadend
# also temporarily flag it as visited so any new deadends
# created aren't sparsified in the same pass
case dir
when NORTH
@matrix[x][y-1] &= ~SOUTH
@matrix[x][y-1] |= FLAG
when EAST
@matrix[x+1][y] &= ~WEST
@matrix[x+1][y] |= FLAG
when SOUTH
@matrix[x][y+1] &= ~NORTH
@matrix[x][y+1] |= FLAG
when WEST
@matrix[x-1][y] &= ~EAST
@matrix[x-1][y] |= FLAG
end
end
end
# clear the flags for the next sparsifying pass
for x in 0...@width
for y in 0...@height
@matrix[x][y] &= ~FLAG
end
end
end
end
=begin
Display the matrix in an ASCII table (useful for debugging)
(Much more readable if you're using a monospaced font for dialog boxes.)
=end
def display
char_array = Array.new(@width, 0)
for i in 0...@width
char_array[i] = Array.new(@height, 0)
end
for x in 0...@width
for y in 0...@height
dir = @matrix[x][y]
char = '['
if ((dir & NORTH) != 0) then char << 'N' else char << ' ' end
if ((dir & EAST) != 0) then char << 'E' else char << ' ' end
if ((dir & WEST) != 0) then char << 'W' else char << ' ' end
if ((dir & SOUTH) != 0) then char << 'S' else char << ' ' end
char << ']'
char_array[y][x] = char
end
end
display = ''
for i in 0...@height
display << char_array[i].flatten.to_s << "\n"
end
print display
end
=begin
Clears the given percentage ("removalChance") of deadends from the maze by
causing the deadends to extend until they hit another passage. As this
causes cycles in the maze, it can result in multiple possible solutions
to the maze (but makes it seem more natural).
=end
def removeDeadends
for x in 0...@width
for y in 0...@height
dir = @matrix[x][y]
# if only one direction, found a deadend
# so otherwise, go to next tile
if not [NORTH, EAST, SOUTH, WEST].include?(dir)
next
end
# random roll to see if this deadend is skipped
if (rand > @removalChance) then next end
cur_x = x; cur_y = y
back_dir = dir
# continue as long as new corridor not reached
while (@matrix[cur_x][cur_y] == back_dir)
direction = 0
testedDirs = 0
# pick random direction
# keep trying until a valid one is found
while (direction == 0)
temp_x = cur_x
temp_y = cur_y
case rand(4)
when 0 # north
if (cur_y > 0) then direction = NORTH; back_dir = SOUTH; temp_y-=1
else testedDirs |= NORTH
end
when 1 # east
if (cur_x+1 < @width) then direction = EAST; back_dir = WEST; temp_x+=1
else testedDirs |= EAST
end
when 2 # south
if (cur_y+1 < @height) then direction = SOUTH; back_dir = NORTH; temp_y+=1
else testedDirs |= SOUTH
end
when 3 # west
if (cur_x > 0) then direction = WEST; back_dir = EAST; temp_x-=1
else testedDirs |= WEST
end
end
# check if deadend tile already goes this way
if ( @matrix[cur_x][cur_y] == direction )
# record direction as tested
testedDirs |= direction
direction = 0
end
# if all directions are invalid, impossible to
# select random direction so break out
if (testedDirs == ALL_DIRS) then break end
end
if (testedDirs == ALL_DIRS) then break end
# add new direction to deadend
@matrix[cur_x][cur_y] |= direction
# add new direction to tile adjacent to deadend
@matrix[temp_x][temp_y] |= back_dir
# move on to next tile
cur_x = temp_x; cur_y = temp_y
end
end
end
end
end
Now, under this class put one more called 'Tile' and then put this script into that:
Tile
module Tile
@floor = 0
@wallFace = 0
@wall = 0
# to be extended with others to make maps "pretty", e.g. random ground features
=begin
The following array lists systematic keys which are based on adjacent
walls (where 'W' is the wall itself):
1 2 3
4 W 6
7 8 9
e.g. 268 is the key that will be used to refer to the autotile
which has adjacent walls north, east, and south. For the Castle Prison
tileset (autotile #1), this is 67.
(It's a bit unwieldy, but it works.)
=end
Autotile_Keys = [
12346789,
2346789,
1246789,
246789,
1234678,
234678,
124678,
24678,
1234689,
234689,
124689,
24689,
123468,
23468,
12468,
2468,
23689,
2689,
2368,
268,
46789,
4678,
4689,
468,
12478,
1248,
2478,
248,
12346,
2346,
1246,
246,
28,
46,
689,
68,
478,
48,
124,
24,
236,
26,
8,
6,
2,
4,
0 ]
# many autotiles handle multiple situations
# this hash keeps track of which keys are identical
# to ones already defined above
Duplicate_Keys = {
123689 => 23689,
236789 => 23689,
1236789 => 23689,
34689 => 4689,
14689 => 4689,
134689 => 4689,
14678 => 4678,
34678 => 4678,
134678 => 4678,
146789 => 46789,
346789 => 46789,
1346789 => 46789,
23467 => 2346,
23469 => 2346,
234679 => 2346,
123467 => 12346,
123469 => 12346,
1234679 => 12346,
12467 => 1246,
12469 => 1246,
124679 => 1246,
124789 => 12478,
123478 => 12478,
1234789 => 12478,
146 => 46,
346 => 46,
467 => 46,
469 => 46,
1346 => 46,
1467 => 46,
1469 => 46,
3467 => 46,
3469 => 46,
4679 => 46,
13467 => 46,
13469 => 46,
14679 => 46,
34679 => 46,
134679 => 46,
128 => 28,
238 => 28,
278 => 28,
289 => 28,
1238 => 28,
1278 => 28,
1289 => 28,
2378 => 28,
2389 => 28,
2789 => 28,
12378 => 28,
12389 => 28,
12789 => 28,
23789 => 28,
123789 => 28,
1247 => 124,
2369 => 236,
147 => 4,
247 => 24,
14 => 4,
47 => 4,
1478 => 478,
3478 => 478,
4789 => 478,
134789 => 478,
14789 => 478,
13478 => 478,
34789 => 478,
1234 => 124,
1247 => 124,
1249 => 124,
12347 => 124,
12349 => 124,
12479 => 124,
123479 => 124,
1236 => 236,
2367 => 236,
2369 => 236,
12367 => 236,
12369 => 236,
23679 => 236,
123679 => 236,
12368 => 2368,
23678 => 2368,
123678 => 2368,
12348 => 1248,
12489 => 1248,
123489 => 1248,
1689 => 689,
3689 => 689,
6789 => 689,
13689 => 689,
16789 => 689,
36789 => 689,
136789 => 689,
12689 => 2689,
26789 => 2689,
126789 => 2689,
23478 => 2478,
24789 => 2478,
234789 => 2478
}
def Tile.setFloor(row, col)
if row > 1
@floor = Tile.index(row, col)
else # autotiles
@floor = Hash.new(0)
j = Tile.index(row, col)
for i in Autotile_Keys
@floor[i] = j
j += 1
end
# add duplicates
for i in Duplicate_Keys.keys
@floor[i] = @floor[Duplicate_Keys[i]]
end
end
end
def Tile.floor
@floor
end
def Tile.floor=(value)
@floor = value
end
def Tile.wall=(value)
@wall = value
end
def Tile.wallFace=(value)
@wallFace = value
end
def Tile.setWallFace(row, col)
if row > 1
@wallFace = Tile.index(row, col)
else # autotiles
@wallFace = Hash.new(0)
j = Tile.index(row, col)
for i in Autotile_Keys
@wallFace[i] = j
j += 1
end
# add duplicates
for i in Duplicate_Keys.keys
@wallFace[i] = @wallFace[Duplicate_Keys[i]]
end
end
end
def Tile.wallFace
@wallFace
end
def Tile.setWall(row, col)
if row > 1
@wall = Tile.index(row, col)
else # autotiles
@wall = Hash.new(0)
j = Tile.index(row, col)
for i in Autotile_Keys
@wall[i] = j
j += 1
end
# add duplicates
for i in Duplicate_Keys.keys
@wall[i] = @wall[Duplicate_Keys[i]]
end
end
end
def Tile.wall
@wall
end
=begin
This method returns the index of a specific tile in the tileset,
or the base index for one of the 7 autotiles.
Parameters:
row - row where the tile is found within the tileset ( 1+ )
col - column where the tile is found within the tileset ( 1-8 )
Note: this method is NOT zero-indexed, i.e. rows and columns start at 1
e.g.
index(1,2) returns 48
index(2,1) returns 384
index(4,8) returns 407
By the way, here's an example of how autotile indexes work...
Autotile in column 2:
row\col| 1 2 3 4 5 6 7 8
---------------------------
1 | 48 49 50 51 52 53 54 55
2 | 56 57 58 59 60 61 62 63
3 | 64 65 66 67 68 69 70 71
4 | 72 73 74 75 76 77 78 79
5 | 80 81 82 83 84 85 86 87
6 | 88 89 90 91 92 93 94 95
The function to return the index of a single tile within an autotile
(given by at_index) is (at_index-1)*48 + col-1 + (row-1)*8
(where row, col, and at_index are again NOT zero-indexed)
=end
def Tile.index(row, col)
if row > 1 # if not autotiles
return 383 + col + 8*(row-2)
else
return (col-1)*48
end
end
end
@floor = 0
@wallFace = 0
@wall = 0
# to be extended with others to make maps "pretty", e.g. random ground features
=begin
The following array lists systematic keys which are based on adjacent
walls (where 'W' is the wall itself):
1 2 3
4 W 6
7 8 9
e.g. 268 is the key that will be used to refer to the autotile
which has adjacent walls north, east, and south. For the Castle Prison
tileset (autotile #1), this is 67.
(It's a bit unwieldy, but it works.)
=end
Autotile_Keys = [
12346789,
2346789,
1246789,
246789,
1234678,
234678,
124678,
24678,
1234689,
234689,
124689,
24689,
123468,
23468,
12468,
2468,
23689,
2689,
2368,
268,
46789,
4678,
4689,
468,
12478,
1248,
2478,
248,
12346,
2346,
1246,
246,
28,
46,
689,
68,
478,
48,
124,
24,
236,
26,
8,
6,
2,
4,
0 ]
# many autotiles handle multiple situations
# this hash keeps track of which keys are identical
# to ones already defined above
Duplicate_Keys = {
123689 => 23689,
236789 => 23689,
1236789 => 23689,
34689 => 4689,
14689 => 4689,
134689 => 4689,
14678 => 4678,
34678 => 4678,
134678 => 4678,
146789 => 46789,
346789 => 46789,
1346789 => 46789,
23467 => 2346,
23469 => 2346,
234679 => 2346,
123467 => 12346,
123469 => 12346,
1234679 => 12346,
12467 => 1246,
12469 => 1246,
124679 => 1246,
124789 => 12478,
123478 => 12478,
1234789 => 12478,
146 => 46,
346 => 46,
467 => 46,
469 => 46,
1346 => 46,
1467 => 46,
1469 => 46,
3467 => 46,
3469 => 46,
4679 => 46,
13467 => 46,
13469 => 46,
14679 => 46,
34679 => 46,
134679 => 46,
128 => 28,
238 => 28,
278 => 28,
289 => 28,
1238 => 28,
1278 => 28,
1289 => 28,
2378 => 28,
2389 => 28,
2789 => 28,
12378 => 28,
12389 => 28,
12789 => 28,
23789 => 28,
123789 => 28,
1247 => 124,
2369 => 236,
147 => 4,
247 => 24,
14 => 4,
47 => 4,
1478 => 478,
3478 => 478,
4789 => 478,
134789 => 478,
14789 => 478,
13478 => 478,
34789 => 478,
1234 => 124,
1247 => 124,
1249 => 124,
12347 => 124,
12349 => 124,
12479 => 124,
123479 => 124,
1236 => 236,
2367 => 236,
2369 => 236,
12367 => 236,
12369 => 236,
23679 => 236,
123679 => 236,
12368 => 2368,
23678 => 2368,
123678 => 2368,
12348 => 1248,
12489 => 1248,
123489 => 1248,
1689 => 689,
3689 => 689,
6789 => 689,
13689 => 689,
16789 => 689,
36789 => 689,
136789 => 689,
12689 => 2689,
26789 => 2689,
126789 => 2689,
23478 => 2478,
24789 => 2478,
234789 => 2478
}
def Tile.setFloor(row, col)
if row > 1
@floor = Tile.index(row, col)
else # autotiles
@floor = Hash.new(0)
j = Tile.index(row, col)
for i in Autotile_Keys
@floor[i] = j
j += 1
end
# add duplicates
for i in Duplicate_Keys.keys
@floor[i] = @floor[Duplicate_Keys[i]]
end
end
end
def Tile.floor
@floor
end
def Tile.floor=(value)
@floor = value
end
def Tile.wall=(value)
@wall = value
end
def Tile.wallFace=(value)
@wallFace = value
end
def Tile.setWallFace(row, col)
if row > 1
@wallFace = Tile.index(row, col)
else # autotiles
@wallFace = Hash.new(0)
j = Tile.index(row, col)
for i in Autotile_Keys
@wallFace[i] = j
j += 1
end
# add duplicates
for i in Duplicate_Keys.keys
@wallFace[i] = @wallFace[Duplicate_Keys[i]]
end
end
end
def Tile.wallFace
@wallFace
end
def Tile.setWall(row, col)
if row > 1
@wall = Tile.index(row, col)
else # autotiles
@wall = Hash.new(0)
j = Tile.index(row, col)
for i in Autotile_Keys
@wall[i] = j
j += 1
end
# add duplicates
for i in Duplicate_Keys.keys
@wall[i] = @wall[Duplicate_Keys[i]]
end
end
end
def Tile.wall
@wall
end
=begin
This method returns the index of a specific tile in the tileset,
or the base index for one of the 7 autotiles.
Parameters:
row - row where the tile is found within the tileset ( 1+ )
col - column where the tile is found within the tileset ( 1-8 )
Note: this method is NOT zero-indexed, i.e. rows and columns start at 1
e.g.
index(1,2) returns 48
index(2,1) returns 384
index(4,8) returns 407
By the way, here's an example of how autotile indexes work...
Autotile in column 2:
row\col| 1 2 3 4 5 6 7 8
---------------------------
1 | 48 49 50 51 52 53 54 55
2 | 56 57 58 59 60 61 62 63
3 | 64 65 66 67 68 69 70 71
4 | 72 73 74 75 76 77 78 79
5 | 80 81 82 83 84 85 86 87
6 | 88 89 90 91 92 93 94 95
The function to return the index of a single tile within an autotile
(given by at_index) is (at_index-1)*48 + col-1 + (row-1)*8
(where row, col, and at_index are again NOT zero-indexed)
=end
def Tile.index(row, col)
if row > 1 # if not autotiles
return 383 + col + 8*(row-2)
else
return (col-1)*48
end
end
end