#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
# Blacksmith Shop
# Author: ForeverZer0
# Type: Custom Shop System
# Date: 4.23.2011
# Version: v.2.0
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
#
# Explanation:
# Will allow you to create a complete blacksmithing system. The player will be
# able to forge equipment/items by using combinations of weapons, armors, and
# items in their possession. Also includes a "Enchantment" feature that will
# allow the player to use special items to add stats, elementel efficiencies,
# and state altering to weapons and armor. The extraction feature allows for
# the breaking down of current equipment and items into other ones.
#
# Features:
# - Completely configurable item requirements for every item.
# - Configurable blacksmith 'fees' for every weapon/armor
# - Can use as many different items, with different quantities for each piece
# of equipment.
# - Variable "skill" levels for Blacksmith shops, which lets you decide
# which features the Blacksmith can do.
# - Only have to use a single script call to for the Blacksmith's shop.
# - Can recycle old equipment by extracting items from weapons/armors/items.
#
# Instructions:
# - Place script below debug and above main
# - Configuration and instructions for each are below
# - To call blacksmith shop, this script call:
#
# w = [ WEAPON_IDS ] (Use as many as needed, seperate with commas)
# a = [ ARMOR_IDS ]
# i = [ ITEM_IDS ]
# $scene = Scene_BlackSmith.new(w, a, i)
#
# - All IDs that you included in the script call for items will be be
# available for forging in that shop.
# - You can also include a fourth argument to the call to set the Blacksmith's
# "skill level". Just make an array of true/false elemenets, set up like
# this:
#
# [CAN_FORGE?, CAN_EXTRACT?, CAN_ENCHANT?]
#
# If you are not using the Enchant feature, omit the last option. Just make
# sure that if you do include this argument that the array has a value for
# each skill.
#
# Credits/Thanks:
# - ForeverZer0, for the script.
# - RoseSkye, huge thanks for beta-testing and demo map.
#
# Author's Notes:
# Please report any bugs/issues at
[Tens de ter uma conta e sessão iniciada para poderes visualizar este link]#
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
module Blacksmith
#===============================================================================
# BEGIN CONFIGURATION
#===============================================================================
FORGE_SE = ['006-System06', 80, 100]
# SE played when an item is forged. ['FILENAME', VOLUME, PITCH]
EXTRACT_SE = ['020-Teleport03', 80, 100]
# SE played when an item extraction is performed. ['FILENAME', VOLUME, PITCH]
ENCHANT_SE = ['020-Teleport03', 80, 100]
# SE played when an item enchantment is performed. ['FILENAME', VOLUME, PITCH]
USE_ENCHANTMENTS = true
# Set to true to enable the "Enchant" feature of the system.
NO_ENCHANT_WEAPONS = []
NO_ENCHANT_ARMORS = []
# Include IDs of any equipment that cannot be enchanted in the respective
# arrays, seperating by commas. Ignore these if not using enchant feature.
# Define the colors used for the text in the Blacksmith shop.
PLUS_COLOR = Color.new(128, 255, 128)
MINUS_COLOR = Color.new(255, 128, 128)
MAP_BACK = true
# Set to true if you would like slightly opaque windows with the map showing
# through.
#-----------------------------------------------------------------------------
# FORGE DATABASE
#-----------------------------------------------------------------------------
# Define the materials used for each weapon/armor/item that can be forged and
# extracted. They configuration is slightly different than what it was in the
# first version of the script. You can seperately define materials that are
# given during extraction if you like, or ignore it and it will simply return
# the same materials it takes to forge them. It works like this:
#
# STEP 1:
# Create a new "case" in the appropriate method below for the type of item
# you are trying to define. There are three of them, one each for weapons,
# armors, and items. Just use this syntax:
#
# when DATABASE_ID then []
#
# STEP 2:
# Now you can begin to add materials to forge the item. Each material has
# an number which defines what type of item is is. Here is the "key":
#
# 0 = Weapon
# 1 = Armor
# 2 = Item
#
# To define a material for an item, you simply create a three element array
# using this format:
# [ITEM_TYPE, DATABASE_ID, QUANTITY]
#
# ...and add it the appropriate empty array in the case statement you made
# in Step 1. You can add as many different items as you please to forge an
# weapon/armor/item, simply seperate the material arrays with commas. See
# below for a few examples.
#-----------------------------------------------------------------------------
def self.weapon_forges(id)
return case id
when 1 then [[2, 33, 3], [2, 42, 1]] # Bronze Sword
when 2 then [[0, 1, 1], [2, 34, 2], [2, 42, 1]] # Iron Sword
when 3 then [[0, 2, 1], [2, 34, 10]] # Steel Sword
when 4 then [[0, 2, 2], [2, 35, 3], [2, 41, 1]] # Mythril Sword
when 5 then [[2, 33, 5], [2, 43, 1]] # Bronze Spear
when 6 then [[2, 34, 4], [0, 5, 1], [2, 43, 1]] # Iron Spear
when 7 then [[0, 6, 2], [2, 34, 2], [2, 43, 1]] # Steel Spear
when 8 then [[2, 35, 8], [2, 43, 1]] # Mythril Spear
end
end
def self.armor_forges(id)
return case id
when 1 then []
when 2 then []
when 3 then []
when 4 then []
when 5 then []
end
end
def self.item_forges(id)
return case id
when 2 then [[2, 1, 5]]
when 3 then [[2, 2, 5]]
when 5 then [[2, 4, 5]]
when 6 then [[2, 5, 5]]
end
end
#-----------------------------------------------------------------------------
# EXTRACT DATABASE
#-----------------------------------------------------------------------------
# Here you can define the items received when a specific item is extracted.
# It can be setup the same as way as above. Items left undefined will return
# the same items that are required to forge it. You can define an item with an
# empty array to have it return no items, though it can still return gold.
#-----------------------------------------------------------------------------
def self.weapon_extractions(id)
return case id
when 1 then [[2, 33, 1], [2, 42, 1]]
when 2 then [[2, 34, 1], [2, 41, 1]]
when 3 then [[2, 34, 2], [0, 1, 1]]
when 4 then [[2, 33, 5], [2, 34, 5], [2, 41, 1]]
when 5 then [[2, 33, 1], [2, 43, 1]]
when 6 then [[2, 34, 1], [2, 43, 1]]
when 7 then [[2, 34, 2], [0, 5, 1]]
when 8 then [[2, 33, 5], [2, 34, 5], [2, 43, 1]]
else
self.weapon_forges(id)
end
end
def self.armor_extractions(id)
return case id
when 1 then []
when 2 then []
when 3 then []
when 4 then []
when 5 then []
else
self.weapon_forges(id)
end
end
def self.item_extractions(id)
return case id
when 1 then [] # Potion
when 2 then [[2, 1, 2]] # High Potion
when 3 then [[2, 2, 2], [2, 1, 2]] # Full Potion
when 4 then [] # Perfume
when 5 then [[2, 4, 2]] # High Perfume
when 6 then [[2, 4, 2], [2, 5, 2]] # Full Perfume
else
self.item_forges(id)
end
end
#-----------------------------------------------------------------------------
# GOLD DATABASE
#-----------------------------------------------------------------------------
# Here you can define the amount of gold that is required to forge an item,
# and the amount that is given if extracted. There are three methods, one each
# for weapons, armors, and items. Simply follow this pattern for each
# category:
#
# when DATABASE_ID then [FORGE_PRICE, EXTRACT_GOLD,]
#-----------------------------------------------------------------------------
def self.weapon_gold(id)
return case id
when 1 then [200, 50]
when 2 then [450, 225]
when 3 then [1000, 525]
when 4 then [1200, 200]
when 5 then [300, 75]
when 6 then [550, 275]
when 7 then [1200, 600]
when 8 then [1500, 650]
else
[0, 0]
end
end
def self.armor_gold(id)
return case id
when 1 then []
when 2 then []
when 3 then []
when 4 then []
when 5 then []
else
[0, 0]
end
end
def self.item_gold(id)
return case id
when 1 then [100, 0]
when 2 then [50, 25]
when 3 then [250, 25]
when 4 then [100, 0]
when 5 then [50, 25]
when 6 then [250, 25]
else
[0, 0]
end
end
#-----------------------------------------------------------------------------
# ENCHANT DATABASE
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Here you can define what items will alter stats when used to enchant with.
# You need to create a two element array, and add it to the respective array
# below that corresponds with the desired item.
#
# ex.
# when ITEM_ID then [[KEYWORD, VALUE], [KEYWORD, VALUE]]
#
# KEYWORD: See below for a list of possible keywords. Stat changes that
# can affect only weapons will have no effect on armors, and
# vice-versa.
# VALUE : The amount by which to change the stat. Negative values will
# lower the stat.
#-----------------------------------------------------------------------------
# KEYWORDS:
#
# 'ATK' (Weapon Only) 'DEX' 'PDEF'
# 'EVA' (Armor Only) 'AGI' 'MDEF'
# 'STR' 'INT'
#
# ** Keywords have to be written EXACTLY as they appear.
#-----------------------------------------------------------------------------
def self.enchant_stats(item_id)
return case item_id
when 39 then [['AGI', 5]] # Carrot
when 40 then [['STR', 15], ['ATK', 5]] # Behemoth Juice
end
end
#-----------------------------------------------------------------------------
# Define state altering enchantments.
#
# ex.
# when ITEM_ID then [[VALUE, STATE_ID], [VALUE, STATE_ID]]
#
# VALUE: One of three different values to represent states efficiency.
# -1 = Minus state (Does nothing on armors)
# 0 = Neutral
# 1 = Plus state
# STATE_ID: The ID in the database of the state.
#-----------------------------------------------------------------------------
def self.enchant_states(item_id)
return case item_id
when 38 then [[1, 2], [1, 4], [1, 6]] # Chaos Orb
end
end
#-----------------------------------------------------------------------------
# Define element altering enchantments.
#
# ex.
# when ITEM_ID then [[VALUE, ELEMENT_ID], [VALUE, ELEMENT_ID]]
#
# VALUE: One of two different values to represent element efficiency.
# true = Uses element
# false = Doesn't use element (Negates element if present)
# ELEMENT_ID: The ID in the database of the element.
#-----------------------------------------------------------------------------
def self.enchant_elements(item_id)
return case item_id
when 36 then [[true, 3], [false, 5]] # Amethyst
when 37 then [[true, 1]] # Ruby
end
end
#-----------------------------------------------------------------------------
# Define the amount of gold it takes to enchant a weapon or armor with the
# item.
#-----------------------------------------------------------------------------
def self.enchant_gold(item_id)
return case item_id
when 36 then 1500
when 37 then 1100
when 38 then 1337
when 39 then 250
when 40 then 7500
else
0
end
end
#===============================================================================
# END CONFIGURATION
#===============================================================================
def self.materials?(type, id)
# Get the required materials for the item
materials = case type
when 0 then [self.weapon_forges(id), self.weapon_gold(id)]
when 1 then [self.armor_forges(id), self.armor_gold(id)]
when 2 then [self.item_forges(id), self.item_gold(id)]
end
materials[0] = [] if materials[0] == nil
# Check gold, skipping item check if there is not enough.
if $game_party.gold >= materials[1][0]
# Iterate all required materials, making sure enough are in inventory.
materials[0].each {|item|
# Branch by the type of the item.
result = case item[0]
when 0 then ($game_party.weapon_number(item[1]) >= item[2])
when 1 then ($game_party.armor_number(item[1]) >= item[2])
when 2 then ($game_party.item_number(item[1]) >= item[2])
end
# End iteration and return false immidiately if missing required item.
return false unless result
}
return true
end
return false
end
#-----------------------------------------------------------------------------
def self.update_database(item)
# Open the Weapons or Armors .rxdata file and add the created item.
begin
if item.is_a?(RPG::Weapon)
file, data = 'Data/Weapons.rxdata', $data_weapons
elsif item.is_a?(RPG::Armor)
file, data = 'Data/Armors.rxdata', $data_armors
else
return
end
data[item.id] = item
file = File.open(file, 'wb')
Marshal.dump(data, file)
file.close
rescue
print "Could not add #{item.name} to Database."
end
end
#-----------------------------------------------------------------------------
def self.create_item(base_item, enchant_item)
base = base_item.clone
# Do to clone only making shallow copies, it is necessary to also create
# seperate clones of the element and state sets, otherwise the original
# is affected too.
if base_item.is_a?(RPG::Weapon)
elem_set = base_item.element_set.clone
plus_state_set = base_item.plus_state_set.clone
minus_state_set = base_item.minus_state_set.clone
else
guard_elem_set = base_item.guard_element_set.clone
guard_state_set = base_item.guard_state_set.clone
end
# Gather the enchantment data.
stats = self.enchant_stats(enchant_item.id)
states = self.enchant_states(enchant_item.id)
elements = self.enchant_elements(enchant_item.id)
# Iterate through stats
if stats != nil
stats.each {|stat|
case stat[0]
when 'ATK'
if base.is_a?(RPG::Weapon)
base.atk += stat[1]
end
when 'EVA'
if base.is?(RPG::Armor)
base.eva += stat[1]
end
when 'STR' then base.str_plus += stat[1]
when 'DEX' then base.dex_plus += stat[1]
when 'AGI' then base.agi_plus += stat[1]
when 'INT' then base.int_plus += stat[1]
when 'PDEF' then base.pdef_plus += stat[1]
when 'MDEF' then base.mdef_plus += stat[1]
end
}
end
# Iterate through states
if states != nil
states.each {|state|
id = state[1]
if base.is_a?(RPG::Weapon)
case state[0]
when -1
minus_state_set.push(id) unless minus_state_set.include?(id)
plus_state_set -= [id]
when 0
minus_state_set -= [id]
plus_state_set -= [id]
when 1
plus_state_set.push(id) unless plus_state_set.include?(id)
minus_state_set -= [id]
end
elsif base.is_a?(RPG::Armor)
if state[0] == 0
guard_state_set -= [id]
elsif state[0] == 1
guard_state_set.push(id) unless guard_state_set.inlcude?(id)
end
end
}
end
# Iterate through elements
if elements != nil
elements.each {|element|
id = element[1]
if base.is_a?(RPG::Weapon)
if element[0] && !elem_set.include?(id)
elem_set.push(id)
else
elem_set -= [id]
end
elsif base.is_a?(RPG::Armor)
if element[0] && !guard_elem_set.include?(id)
guard_elem_set.push(id)
else
guard_elem_set -= [id]
end
end
}
end
# Give the weapon a new ID, remove the old item, and add the new one.
if base.is_a?(RPG::Weapon)
$game_party.lose_weapon(base_item.id, 1)
base.id = $data_weapons.size
base.element_set = elem_set
base.plus_state_set = plus_state_set
base.minus_state_set = minus_state_set
$data_weapons[base.id] = base
$game_party.gain_weapon(base.id, 1)
elsif base.is_a?(RPG::Armor)
$game_party.lose_armor(base_item.id, 1)
base.id = $data_armors.size
base.guard_element_set = guard_elem_set
base.guard_state_set = guard_state_set
$data_armors[base.id] = base
$game_party.gain_armor(base.id, 1)
end
# Add new item to class equipment
self.update_class_equipment(base_item, base)
# Save the new item to the database.
self.update_database(base)
end
#-----------------------------------------------------------------------------
def self.update_class_equipment(old, new)
# Adds the created item to class equipment that could equip the original
$data_classes.each_index {|i|
next if $data_classes[i] == nil
if old.is_a?(RPG::Weapon) && $data_classes[i].weapon_set.include?(old.id)
$data_classes[i].weapon_set.push(new.id)
elsif old.is_a?(RPG::Armor) && $data_classes[i].armor_set.include?(old.id)
$data_classes[i].armor_set.push(new.id)
end
}
# Marshal the new data.
begin
file = File.open('Data/Classes.rxdata', 'wb')
Marshal.dump($data_classes, file)
file.close
rescue
print "Could not update RPG::Class database."
end
end
end
$blacksmith = 2.0
#===============================================================================
# ** Window_BlacksmithCommand
#===============================================================================
class Window_BlacksmithCommand < Window_Selectable
def initialize(level)
super(0, 64, 480, 64)
@level = level
if Blacksmith::USE_ENCHANTMENTS
@item_max = @column_max = 4
@commands = ['Forge', 'Extract', 'Enchant', 'Exit']
else
@item_max = @column_max = 3
@commands = ['Forge', 'Extract', 'Exit']
end
self.contents = Bitmap.new(self.width - 32, self.height - 32)
refresh
self.index = 0
end
#-----------------------------------------------------------------------------
def refresh
self.contents.clear
(0...@item_max).each {|i| draw_item(i) }
end
#-----------------------------------------------------------------------------
def draw_item(index)
w = self.width / @item_max
self.contents.font.color = @level[index] ? normal_color : disabled_color
self.contents.draw_text(4 + (w * index), 0, w, 32, @commands[index])
end
end
#===============================================================================
# ** Window_BlacksmithForge
#===============================================================================
class Window_BlacksmithForge < Window_Selectable
def initialize(shop_goods)
super(0, 128, 368, 352)
# Initialize window and create instance variable to store available goods.
@shop_goods = shop_goods
self.active = self.visible = false
refresh
self.index = 0
end
#-----------------------------------------------------------------------------
def item
return @data[self.index]
end
#-----------------------------------------------------------------------------
def refresh(enchanting = false)
# Dispose bitmap and set to nil if not already.
if self.contents != nil
self.contents = self.contents.dispose
end
# Set flag for enchanting
@enchanting = enchanting
# Create array of equipment, depending on flag
if @enchanting
@data = []
# Add weapons
($data_weapons - [nil]).each {|weapon|
if $game_party.weapon_number(weapon.id) > 0 &&
!Blacksmith::NO_ENCHANT_WEAPONS.include?(weapon.id)
@data.push(weapon)
end
}
# Add Armor
($data_armors - [nil]).each {|armor|
if $game_party.armor_number(armor.id) > 0 &&
!Blacksmith::NO_ENCHANT_ARMORS.include?(armor.id)
@data.push(armor)
end
}
else
@data = @shop_goods
end
# Create a new bitmap, sized for available items
@item_max = @data.size
if @item_max > 0
self.contents = Bitmap.new(width - 32, row_max * 32)
(0...@item_max).each {|i| draw_item(i) }
end
end
#-----------------------------------------------------------------------------
def draw_item(index)
item = @data[index]
# Set a few local variables depending on the type of item.
case item
when RPG::Weapon
quantity = $game_party.weapon_number(item.id)
price, type = Blacksmith.weapon_gold(item.id)[0], 0
when RPG::Armor
quantity = $game_party.armor_number(item.id)
price, type = Blacksmith.armor_gold(item.id)[0], 1
when RPG::Item
quantity = $game_party.item_number(item.id)
price, type = Blacksmith.item_gold(item.id)[0], 2
end
# Don't check material requirments for forging wjen enchanting
result = @enchanting ? true : Blacksmith.materials?(type, item.id)
# Determine the color to use for drawing the item name.
if quantity < 99 && result
self.contents.font.color = normal_color
else
self.contents.font.color = disabled_color
end
# Draw the item name, icon, and price.
x, y = 4, index * 32
rect = Rect.new(x, y, self.width - 32, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
bitmap = RPG::Cache.icon(item.icon_name)
opacity = self.contents.font.color == normal_color ? 255 : 128
self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.draw_text(x + 28, y, 212, 32, item.name, 0)
if !@enchanting
self.contents.draw_text(x + 240, y, 88, 32, price.to_s, 2)
end
end
#-----------------------------------------------------------------------------
def update_help
@help_window.set_text(self.item == nil ? '' : self.item.description)
end
end
#===============================================================================
# ** Window_BlacksmithExtract
#===============================================================================
class Window_BlacksmithExtract < Window_Selectable
def initialize
super(0, 128, 368, 352)
self.active = self.visible = false
refresh
self.index = 0
end
#-----------------------------------------------------------------------------
def item
return @data[self.index]
end
#-----------------------------------------------------------------------------
def refresh
# Dispose current bitmap if defined.
if self.contents != nil
self.contents = self.contents.dispose
end
# Create list of items in inventory
@data = []
(1...$data_weapons.size).each {|i|
result = (Blacksmith.weapon_extractions(i) != nil ||
Blacksmith.weapon_gold(i)[1] != 0)
if $game_party.weapon_number(i) > 0 && result
@data.push($data_weapons[i])
end
}
(1...$data_armors.size).each {|i|
result = (Blacksmith.armor_extractions(i) != nil ||
Blacksmith.armor_gold(i)[1] != 0)
if $game_party.armor_number(i) > 0 && result
@data.push($data_armors[i])
end
}
(1...$data_items.size).each {|i|
result = (Blacksmith.item_extractions(i) != nil ||
Blacksmith.item_gold(i)[1] != 0)
if $game_party.item_number(i) > 0 && result
@data.push($data_items[i])
end
}
@item_max = @data.size
# Create a new bitmap that will contain the listed items
if @item_max > 0
self.contents = Bitmap.new(width - 32, row_max * 32)
(0...@item_max).each {|i| draw_item(i) }
end
end
#-----------------------------------------------------------------------------
def draw_item(index)
item = @data[index]
# Set a few local variables depending on the type of item.
quantity = case item
when RPG::Weapon then $game_party.weapon_number(item.id)
when RPG::Armor then $game_party.armor_number(item.id)
when RPG::Item then $game_party.item_number(item.id)
end
# Draw the name, icon, and quantity of the item.
x, y = 4, index * 32
rect = Rect.new(x, y, self.width / @column_max - 32, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
bitmap = RPG::Cache.icon(item.icon_name)
self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.draw_text(x + 28, y, 212, 32, item.name, 0)
end
#-----------------------------------------------------------------------------
def update_help
@help_window.set_text(self.item == nil ? '' : self.item.description)
end
end
#===============================================================================
# ** Window_BlacksmithMaterials
#===============================================================================
class Window_BlacksmithMaterials < Window_Base
attr_accessor :active
def initialize
# Initialize window size and coordinates.
super(0, 128, 368, 352)
self.visible = @active = false
end
#-----------------------------------------------------------------------------
def refresh(item, type = 0)
# Clear the bitmap and set the new materials.
if self.contents != nil
self.contents = self.contents.dispose
end
set_materials(item, type)
# Create a new bitmap, based off the amount of materials
if @materials != nil && @materials.size > 0
self.contents = Bitmap.new(self.width - 32, 64 + (@materials.size * 32))
# Draw each material and quantity required.
self.contents.font.color = system_color
word = type == 0 ? 'Cost' : ($data_system.words.gold + ':')
self.contents.draw_text(4, 0, 212, 32, word, 0)
text = type == 0 ? 'Required Materials:' : 'Extractable Materials:'
self.contents.draw_text(4, 32, 368, 32, text, 0)
self.contents.font.color = normal_color
self.contents.draw_text(244, 0, 88, 32, @price.to_s, 2)
# Enumerate through each material.
@materials.each_index {|i|
# Set local variable to current item, depending on type.
case @materials[i][0]
when 0
item = $data_weapons[@materials[i][1]]
enough = $game_party.weapon_number(item.id) >= @materials[i][2]
when 1
item = $data_armors[@materials[i][1]]
enough = $game_party.armor_number(item.id) >= @materials[i][2]
when 2
item = $data_items[@materials[i][1]]
enough = $game_party.item_number(item.id) >= @materials[i][2]
end
next if item == nil
# Set local variable to store required amount of this item.
required = @materials[i][2]
# Set color of text, draw grayed if out if forging and not enough.
self.contents.font.color = normal_color
if type == 0 && !enough
self.contents.font.color = disabled_color
end
# Set coordinates of current line.
x, y = 4, 64 + (i * 32)
# Draw item name, icon, and required amount.
rect = Rect.new(x, y, self.width - 32, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
bitmap = RPG::Cache.icon(item.icon_name)
opacity = self.contents.font.color == normal_color ? 255 : 128
self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.draw_text(x + 28, y, 212, 32, item.name)
self.contents.draw_text(x + 272, y, 48, 32, 'x', 0)
self.contents.draw_text(x + 272, y, 48, 32, required.to_s, 2)
}
elsif @price > 0
self.contents = Bitmap.new(self.width - 32, 64)
self.contents.font.color = system_color
self.contents.draw_text(4, 0, 212, 32, $data_system.words.gold + ':')
self.contents.font.color = normal_color
self.contents.draw_text(244, 0, 88, 32, @price.to_s, 2)
self.contents.draw_text(4, 32, 368, 32, 'No Materials')
end
end
#-----------------------------------------------------------------------------
def set_materials(item, type)
# Sets the required/extractable items for the passed item.
id = item.id
if item.is_a?(RPG::Weapon)
@materials = type == 0 ? Blacksmith.weapon_forges(id) :
Blacksmith.weapon_extractions(id)
@price = Blacksmith.weapon_gold(id)[type]
elsif item.is_a?(RPG::Armor)
@materials = type == 0 ? Blacksmith.armor_forges(id) :
Blacksmith.armor_extractions(id)
@price = Blacksmith.armor_gold(id)[type]
else
if @materials != 2
@materials = type == 0 ? Blacksmith.item_forges(id) :
Blacksmith.item_extractions(id)
@price = Blacksmith.item_gold(id)[type]
end
end
end
#-----------------------------------------------------------------------------
def update
# Allow scrolling of bitmap if materials don't fit in window.
if @active && self.contents != nil && self.contents.height > 320
if Input.trigger?(Input::UP)
if self.oy > 0
self.oy -= 32
$game_system.se_play($data_system.cursor_se)
end
elsif Input.trigger?(Input::DOWN)
if (self.oy + 320) < self.contents.height
self.oy += 32
$game_system.se_play($data_system.cursor_se)
end
end
end
end
end
#===============================================================================
# ** Window_BlacksmithStatus
#===============================================================================
class Window_BlacksmithStatus < Window_Base
def initialize
super(368, 128, 272, 352)
self.contents = Bitmap.new(width - 32, height - 32)
# Create array of sprites same size as party
@sprites = [Sprite.new, Sprite.new, Sprite.new, Sprite.new]
#@sprites = Array.new($game_party.actors.size, Sprite.new)
# Set coordinates of each sprite
@sprites.each_index {|i|
@sprites[i].x, @sprites[i].y = 380, 194 + (i * 64)#(i * 34)
@sprites[i].z = self.z + 10
}
self.visible = false
# Array of flags for walking
@walk = Array.new($game_party.actors.size, false)
@count, @item = 0, nil
refresh
end
#-----------------------------------------------------------------------------
def refresh
# Clear bitmap and turn off visiblity of each sprite.
self.contents.clear
@sprites.each {|sprite| sprite.visible = false }
# Return if selected item index is undefined.
return if @item == nil
self.contents.font.size = Font.default_size + 2
quantity = case @item
when RPG::Item then $game_party.item_number(@item.id)
when RPG::Weapon then $game_party.weapon_number(@item.id)
when RPG::Armor then $game_party.armor_number(@item.id)
end
self.contents.font.color = system_color
self.contents.draw_text(4, 0, 200, 32, 'Possessed:')
self.contents.font.color = normal_color
self.contents.draw_text(204, 0, 32, 32, quantity.to_s, 2)
# Disable walking animation and end method if selected item is a normal item
if @item.is_a?(RPG::Item)
@walk.collect! {|value| false }
return
end
# Change the font size.
self.contents.font.size = Font.default_size - 1
# Iterate each actor...
$game_party.actors.each_index {|i|
chr = $game_party.actors[i]
# Set local variable to highlighted piece of equipment.
if @item.is_a?(RPG::Weapon)
eqp = $data_weapons[chr.weapon_id]
else
armors = [chr.armor1_id, chr.armor2_id, chr.armor3_id, chr.armor4_id]
eqp = $data_armors[armors[@item.kind]]
end
# Draw the actor sprite.
draw_actor_graphic(i, chr.equippable?(@item))
# Draw message and return if unequippable.
unless chr.equippable?(@item)
self.contents.font.color = normal_color
self.contents.draw_text(32, 54 + (i * 64), 150, 32, 'Cannot Equip')
next
else
# Create array of stat changes.
# [str, dex, agi, int, pdef, mdef, (atk || eva)]
stats = [
(@item == nil ? 0 : @item.str_plus) - (eqp == nil ? 0 : eqp.str_plus),
(@item == nil ? 0 : @item.dex_plus) - (eqp == nil ? 0 : eqp.dex_plus),
(@item == nil ? 0 : @item.agi_plus) - (eqp == nil ? 0 : eqp.agi_plus),
(@item == nil ? 0 : @item.int_plus) - (eqp == nil ? 0 : eqp.int_plus),
(@item == nil ? 0 : @item.pdef) - (eqp == nil ? 0 : eqp.pdef),
(@item == nil ? 0 : @item.mdef) - (eqp == nil ? 0 : eqp.mdef)
]
if @item.is_a?(RPG::Weapon)
stats.push(
(@item == nil ? 0 : @item.atk) - (eqp == nil ? 0 : eqp.atk))
elsif @item.is_a?(RPG::Armor)
stats.push(
(@item == nil ? 0 : @item.eva) - (eqp == nil ? 0 : eqp.eva))
end
# Set local variable to each piece of equipments' name
current_name = eqp == nil ? '' : eqp.name
new_name = @item == nil ? '' : @item.name
# If stats are all equal, show message and end method.
if stats.all? {|stat| stat == 0 }
self.contents.font.color = normal_color
if current_name != new_name
self.contents.draw_text(32, 54 + (i * 64), 150, 32, 'No Change')
else
self.contents.draw_text(32, 54 + (i * 64), 150, 32, 'Equipped')
end
next
end
# Draw any stat changes, using colors to show plus/minus changes
self.contents.font.size = (Font.default_size - 1)
self.contents.font.color = normal_color
self.contents.draw_text(104, 42 + (64*i), 32, 32, 'STR ') if stats[0] != 0
self.contents.draw_text(104, 58 + (64*i), 32, 32, 'DEX ') if stats[1] != 0
self.contents.draw_text(104, 74 + (64*i), 32, 32, 'AGI ') if stats[2] != 0
self.contents.draw_text(176, 42 + (64*i), 32, 32, 'INT ') if stats[3] != 0
self.contents.draw_text(32, 58 + (64*i), 32, 32, 'PDF ') if stats[4] != 0
self.contents.draw_text(32, 74 + (64*i), 32, 32, 'MDF ') if stats[5] != 0
if stats[-1] != 0
# Show stats changes for atk/eva, depending on the equipment type
stat = @item.is_a?(RPG::Weapon) ? 'ATK ' : 'EVA '
self.contents.draw_text(32, 42 + (64 * i), 32, 32, stat) if stat != 0
end
# Show any stat changes
stats.each_index {|j|
next if stats[j] == 0
xy = case j
when 0 then [132, 42 + (64 * i)]
when 1 then [132, 58 + (64 * i)]
when 2 then [132, 74 + (64 * i)]
when 3 then [198, 42 + (64 * i)]
when 4 then [60, 58 + (64 * i)]
when 5 then [60, 74 + (64 * i)]
when 6 then [60, 42 + (64 * i)]
end
# Set color and operator depending on value
if stats[j] < 0
self.contents.font.color, sign = Blacksmith::MINUS_COLOR, '-'
else
self.contents.font.color, sign = Blacksmith::PLUS_COLOR, '+'
end
self.contents.draw_text(xy[0], xy[1], 8, 32, sign, 1)
self.contents.draw_text(xy[0] + 10, xy[1], 24, 32, stats[j].abs.to_s)
}
end
}
end
#-----------------------------------------------------------------------------
def item=(item)
if @item != item
# Change the item variable and refresh.
@item = item
refresh
end
end
#-----------------------------------------------------------------------------
def draw_actor_graphic(id, equipable)
# Draws the actor graphic
actor = $game_party.actors[id]
@sprites[id].bitmap = RPG::Cache.character(actor.character_name,
actor.character_hue)
@sprites[id].src_rect.set(0, 0, @sprites[id].bitmap.width / 4,
@sprites[id].bitmap.height / 4)
# Set walking animation if item is equippable.
@walk[id] = equipable
@sprites[id].tone = Tone.new(0, 0, 0, equipable ? 0 : 255)
@sprites[id].visible = true
end
#-----------------------------------------------------------------------------
def update
super
# Update the walking animation.
@count = (@count + 1) % 40
$game_party.actors.each_index {|i|
next unless @walk[i]
if @sprites[i].bitmap != nil
w = @sprites[i].bitmap.width / 4
h = @sprites[i].bitmap.height / 4
x = (@count / 10) * w
@sprites[i].src_rect.set(x, 0, w, h)
end
}
end
#-----------------------------------------------------------------------------
def visible=(bool)
super
# Set visible to the actor sprites as well.
@sprites.each {|sprite| sprite.visible = bool }
end
#-----------------------------------------------------------------------------
def dispose
super
# Dispose the actor sprites as well.
@sprites.each {|sprite| sprite.dispose }
end
end
#===============================================================================
# ** Window_BlacksmithExtract
#===============================================================================
class Window_BlacksmithEnchant < Window_Selectable
def initialize
super(0, 128, 368, 352)
self.active = self.visible = false
refresh
self.index = 0
end
#-----------------------------------------------------------------------------
def item
return @data[self.index]
end
#-----------------------------------------------------------------------------
def refresh
# Dispose current bitmap if defined.
if self.contents != nil
self.contents = self.contents.dispose
end
# Create list of items in inventory
@data = []
($data_items - [nil]).each {|item|
result = false
result = true if Blacksmith.enchant_stats(item.id) != nil
result = true if Blacksmith.enchant_states(item.id) != nil
result = true if Blacksmith.enchant_elements(item.id) != nil
@data.push(item) if result
}
@item_max = @data.size
# Create a new bitmap that will contain the listed items
if @item_max > 0
self.contents = Bitmap.new(width - 32, row_max * 32)
(0...@item_max).each {|i| draw_item(i) }
end
end
#-----------------------------------------------------------------------------
def draw_item(index)
item = @data[index]
# Set a few local variables depending on the type of item.
quantity = $game_party.item_number(item.id)
# Draw the name, icon, and quantity of the item.
x, y = 4, index * 32
rect = Rect.new(x, y, self.width / @column_max - 32, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
bitmap = RPG::Cache.icon(item.icon_name)
self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24))
self.contents.draw_text(x + 28, y, 212, 32, item.name, 0)
self.contents.draw_text(x + 240, y, 16, 32, ':', 1)
self.contents.draw_text(x + 256, y, 24, 32, quantity.to_s, 2)
end
#-----------------------------------------------------------------------------
def update_help
@help_window.set_text(self.item == nil ? '' : self.item.description)
end
end
#===============================================================================
# ** Scene_Blacksmith
#===============================================================================
class Scene_Blacksmith
def initialize(weapons = [], armors = [], items = [], level = nil)
# Set available goods for this shop based off passed argument.
@goods = []
@goods += weapons.collect {|id| $data_weapons[id] }
@goods += armors.collect {|id| $data_armors[id] }
@goods += items.collect {|id| $data_items[id] }
@goods.uniq!
# Configure the level variable
@level = (level == nil) ? Array.new(4, true) : (level + [true])
@enchants = Blacksmith::USE_ENCHANTMENTS
end
#-----------------------------------------------------------------------------
def main
# Create a Proc to handle confirmation of choices
@confirm_proc = Proc.new {
@help_window.set_text('Are you sure?')
window = Window_Command.new(160, ['Confirm', 'Cancel'])
window.x, window.y, window.z = 224, 192, 9999
loop { Graphics.update; Input.update; window.update
if Input.trigger?(Input::C) || Input.trigger?(Input::B)
result = (Input.trigger?(Input::C) && window.index == 0)
$game_system.se_play($data_system.cancel_se) unless result
window.dispose
break(result)
end
}
}
# Initialize the needed windows.
@command_window = Window_BlacksmithCommand.new(@level)
@forge_window = Window_BlacksmithForge.new(@goods)
@extract_window = Window_BlacksmithExtract.new
@materials_window = Window_BlacksmithMaterials.new
@enchant_window = Window_BlacksmithEnchant.new
@status_window = Window_BlacksmithStatus.new
@dummy_window = Window_Base.new(0, 128, 640, 352)
@gold_window = Window_Gold.new
@gold_window.x, @gold_window.y = 480, 64
@help_window = Window_Help.new
# Bind the help window to the other windows.
@forge_window.help_window = @extract_window.help_window = @help_window
@enchant_window.help_window = @help_window
# Set a windows array for easier handling of all windows.
@windows = [@command_window, @forge_window, @extract_window, @help_window,
@materials_window, @status_window, @dummy_window, @gold_window, @enchant_window]
# Create map sprite if configured to do so, and set window opacity
if Blacksmith::MAP_BACK
@spriteset = Spriteset_Map.new
@windows.each {|window| window.opacity = 160 }
end
# Execute the transition and start the main loop.
Graphics.transition
loop {Graphics.update; Input.update; update; break if $scene != self }
# Freeze the Graphics and dispose the windows
Graphics.freeze
@windows.each {|window| window.dispose }
if Blacksmith::MAP_BACK && @spriteset != nil
@spriteset.dispose
end
end
#-----------------------------------------------------------------------------
def update
# Update the windows
@windows.each {|window| window.update }
# Branch method depending on current action.
if @command_window.active
update_command
elsif @extract_window.active
update_extract
elsif @forge_window.active
update_forge
elsif @materials_window.active
update_materials
elsif @enchant_window.active
update_enchant
end
end
#-----------------------------------------------------------------------------
def back_to_map
# Play SE and return to the map.
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Map.new
end
#-----------------------------------------------------------------------------
def update_command
# Set help text depending on the selected index.
help_text = case @command_window.index
when 0 then 'Use materials to forge new weapons, armors, and items.'
when 1 then 'Extract materials from weapons, armors, and items.'
when 2 then !@enchants ? 'Exit the shop.' :
'Enchant weapons, armors, and items using other items.'
when 3 then 'Exit the shop.'
end
@help_window.set_text(help_text)
# Check for Input.
if Input.trigger?(Input::B)
back_to_map
elsif Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
# Branch depending on command index
case @command_window.index
when 0
# Play SE and return if option is locked.
unless @level[0]
$game_system.se_play($data_system.buzzer_se)
return
end
# Shift scene to forge phase.
@dummy_window.visible = false
@forge_window.refresh(false)
@command_window.active = false
@forge_window.active = @forge_window.visible = true
@status_window.visible = true
when 1
# Play SE and return if option is locked.
unless @level[1]
$game_system.se_play($data_system.buzzer_se)
return
end
# Shift scene to extract phase
@extract_window.refresh
@command_window.active = @dummy_window.visible = false
@extract_window.active = @extract_window.visible = true
@status_window.visible = true
when 2
# Play SE and return if option is locked.
if @enchants
unless @level[2]
$game_system.se_play($data_system.buzzer_se)
return
end
# Shift scene to enchant phase.
@forge_window.refresh(true)
@command_window.active = @dummy_window.visible = false
@forge_window.active = @forge_window.visible = true
@status_window.visible = true
else
back_to_map
end
when 3
back_to_map
end
end
end
#-----------------------------------------------------------------------------
def update_forge
# Update for input when forge window is active.
@item = @status_window.item = @forge_window.item
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@command_window.active = @dummy_window.visible = true
@forge_window.active = @forge_window.visible = false
@status_window.visible = false
elsif Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
@forge_window.active = @forge_window.visible = false
if @command_window.index == 0
@materials_window.refresh(@item, 0)
@materials_window.visible = @materials_window.active = true
else
@enchant_window.refresh
@enchant_window.visible = @enchant_window.active = true
end
end
end
#-----------------------------------------------------------------------------
def update_extract
# Update for input when extraction window is active.
@item = @status_window.item = @extract_window.item
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@command_window.active = @dummy_window.visible = true
@extract_window.active = @extract_window.visible = false
@status_window.visible = false
elsif Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
@materials_window.refresh(@item, 1)
@extract_window.active = @extract_window.visible = false
@materials_window.visible = @materials_window.active = true
end
end
#-----------------------------------------------------------------------------
def update_enchant
# Update input on the enchantment items screen.
if Input.trigger?(Input::B)
# Return to previous screen if cancel button is pressed.
$game_system.se_play($data_system.cancel_se)
@enchant_window.visible = @enchant_window.active = false
@forge_window.active = @forge_window.visible = true
elsif Input.trigger?(Input::C) && @confirm_proc.call
enchant_item
end
end
#-----------------------------------------------------------------------------
def enchant_item
# Apply enchantment to weapon/armor using item
$game_party.lose_item(@enchant_window.item.id, 1)
Blacksmith.create_item(@forge_window.item, @enchant_window.item)
# Play SE
$game_system.se_play(RPG::AudioFile.new(*Blacksmith::ENCHANT_SE))
# Refesh windows
[@enchant_window, @status_window].each {|window| window.refresh }
@forge_window.refresh(true)
# Return to previous screen
@enchant_window.visible = @enchant_window.active = false
@forge_window.active = @forge_window.visible = true
end
#-----------------------------------------------------------------------------
def update_materials
# Show help text.
text = 'Press the Action Button to proceed. Press Cancel to go back'
@help_window.set_text(text)
if Input.trigger?(Input::B)
# Return to previous screen if cancel button is pressed.
$game_system.se_play($data_system.cancel_se)
@materials_window.visible = @materials_window.active = false
if @command_window.index == 0
@forge_window.active = @forge_window.visible = true
else
@extract_window.active = @extract_window.visible = true
end
elsif Input.trigger?(Input::C) && @confirm_proc.call
@command_window.index == 0 ? forge_item : extract_item
end
end
#-----------------------------------------------------------------------------
def forge_item
# Set local variables depending on item type.
case @item
when RPG::Weapon
quantity, type = $game_party.weapon_number(@item.id), 0
materials = Blacksmith.weapon_forges(@item.id)
price = Blacksmith.weapon_gold(@item.id)[0]
when RPG::Armor
quantity, type = $game_party.armor_number(@item.id), 1
materials = Blacksmith.armor_forges(@item.id)
price = Blacksmith.armor_gold(@item.id)[0]
when RPG::Item
quantity, type = $game_party.item_number(@item.id), 2
materials = Blacksmith.item_forges(@item.id)
price = Blacksmith.item_gold(@item.id)[0]
end
# If player doesn't have the materials or gold, play SE and end method.
unless Blacksmith.materials?(type, @item.id)
$game_system.se_play($data_system.buzzer_se)
return
end
# End method and play buzzer if inventory is full.
return $game_system.se_play($data_system.buzzer_se) if quantity == 99
# Play the defined SE used when forging.
$game_system.se_play(RPG::AudioFile.new(*Blacksmith::FORGE_SE))
# Remove required materials from inventory and subtract gold cost.
if materials != nil
materials.each {|material|
case material[0]
when 0 then $game_party.lose_weapon(material[1], material[2])
when 1 then $game_party.lose_armor(material[1], material[2])
when 2 then $game_party.lose_item(material[1], material[2])
end
}
end
$game_party.lose_gold(price)
# Add forged item
case @item
when RPG::Weapon then $game_party.gain_weapon(@item.id, 1)
when RPG::Armor then $game_party.gain_armor(@item.id, 1)
when RPG::Item then $game_party.gain_item(@item.id, 1)
end
# Reset windows.
@materials_window.visible = @materials_window.active = false
@forge_window.active = @forge_window.visible = true
# Refresh any windows that may have changed
[@status_window, @gold_window, @extract_window, @forge_window,
@enchant_window].each {|window| window.refresh }
end
#-----------------------------------------------------------------------------
def extract_item
# Set local variables depending on item type.
case @item
when RPG::Weapon
quantity = $game_party.weapon_number(@item.id)
materials = Blacksmith.weapon_extractions(@item.id)
price = Blacksmith.weapon_gold(@item.id)[1]
when RPG::Armor
quantity = $game_party.armor_number(@item.id)
materials = Blacksmith.armor_extractions(@item.id)
price = Blacksmith.armor_gold(@item.id)[1]
when RPG::Item
quantity = $game_party.item_number(@item.id)
materials = Blacksmith.item_extractions(@item.id)
price = Blacksmith.item_gold(@item.id)[1]
end
# If nothing is defined for the extraction, return.
if materials == nil || (materials.empty? && price == 0)
return $game_system.se_play($data_system.buzzer_se)
end
# Play extraction SE
$game_system.se_play(RPG::AudioFile.new(*Blacksmith::EXTRACT_SE))
# Perform extraction, adding materials and increasing gold.
materials.each {|material|
case material[0]
when 0 then $game_party.gain_weapon(material[1], material[2])
when 1 then $game_party.gain_armor(material[1], material[2])
when 2 then $game_party.gain_item(material[1], material[2])
end
}
$game_party.gain_gold(price)
# Remove extracted item from inventory
case @item
when RPG::Weapon then $game_party.lose_weapon(@item.id, 1)
when RPG::Armor then $game_party.lose_armor(@item.id, 1)
when RPG::Item then $game_party.lose_item(@item.id, 1)
end
# Reset windows.
@materials_window.visible = @materials_window.active = false
@extract_window.active = @extract_window.visible = true
# Refresh any windows that may have changed
[@status_window, @gold_window, @extract_window].each {|window| window.refresh }
end
end