Synthesis Shop (VX)
Version: 1.0
Author: Zylos
Date: February 25, 2011
Description
This is a simple script for a Final Fantasy IX synthesis shop. In a synthesis shop, the player can combine two materials (along with some money) to create new weapons. This script allows the user to easily turn the synthesis shop on and off with a switch, and set up what items can be made, how much they cost, and what materials are needed, simply by typing the numbers on the item's notebox in the database. No need to edit anything in the script except possibly what switch you'd like to use to turn it on.
Features
- Combine two materials to make rarer or better items.
- Easily customizable using item notes. No need to edit the script
- As near to the exact synthesis system from FFIX as RPG Maker VX can get.
Screenshots Instructions
- Place this script in the materials section, above Main.
- Check the number for the switch you'd like to use to turn the synthesis shops on or off. The default switch ID is 20.
- Check or create the items, weapons, or armors you want to be able to synthesize in the synthesis shop. In the Notes section in the bottom-right corner of your desired item, add in the following data:
- \cost[] - This is the price of the item.
- \type1[] - The type of object for the first required material.
Use 0 for item, 1 for weapon, and 2 for armor. - \type2[] - The type of object for the second required material.
Use 0 for item, 1 for weapon, and 2 for armor. - \id1[] - The ID of the first required material.
- \id2[] - The ID of the second required material.
- So for example, if you wanted to create a broad sword with two long swords for 150G under the default database settings, you would type in \cost[150], \type1[1], \type2[1], \id1[2], and \id2[2]. Do this for every item you wish to synthesize in the shop.
- To create a synthesis shop in the game, simply flip on the synthesis switch that you designated earlier and set up a shop like you normally would, using only the goods you have already marked for synthesis. Be sure to remember to turn the switch off again afterward too.
Script
#==============================================================================
# Synthesis Shop (VX)
# Version: 1.0
# Author: Zylos (rmrk.net)
# Date: February 25, 2011
#------------------------------------------------------------------------------
# Description:
#
# This is a simple script for a Final Fantasy IX synthesis shop. In a synthesis
# shop, the player can combine two materials (along with some money) to create
# new weapons. This script allows the user to easily turn the synthesis shop
# on and off with a switch, and set up what items can be made, how much they
# cost, and what materials are needed, simply by typing the numbers on the
# item's notebox in the database. No need to edit anything in the script except
# for what switch you'd like to use.
#
#------------------------------------------------------------------------------
# Instructions:
#
# - Place this script in the materials section, above Main.
# - Check the number for the switch you'd like to use to turn the synthesis
# shops on or off. The default switch ID is 20, and can be changed just
# below these instructions.
# - Check or create the items, weapons, or armors you want to be able to
# synthesize in the synthesis shop. In the Notes section in the bottom-right
# corner of your desired item, add in the following data:
#
# \cost[] - This is the price of the item.
# \type1[] - The type of object for the first required material.
# Use 0 for item, 1 for weapon, and 2 for armor.
# \type2[] - The type of object for the second required material.
# Use 0 for item, 1 for weapon, and 2 for armor.
# \id1[] - The ID of the first required material.
# \id2[] - The ID of the second required material.
#
# So for example, if you wanted to create a broad sword with two long swords
# for 150G under the default database settings, you would type in
# \cost[150], \type1[1], \type2[1], \id1[2], and \id2[2]. Do this for every
# item you wish to synthesize in the shop.
# - To create a synthesis shop in the game, simply flip on the synthesis
# switch that you designated earlier and set up a shop like you normally
# would, using only the goods you have already marked for synthesis. Be
# sure to remember to turn the switch off again afterward too.
#
#==============================================================================
module Synth_Switch
#============================================================================
# IMPORTANT! Edit this to change the switch that calls up the synthesis
# screen. If this switch is off, nothing will happen. If this switch is on,
# then normal shops will changed into synthesis shops instead.
#
# Editable switch:
#============================================================================
Synthesis_Switch = 20 #Synthesis Switch
#============================================================================
# Other than this bit here, you won't need to edit anything in the script
# itself. Everything else can be done in the noteboxes of the database.
#============================================================================
end
#==============================================================================
# ** Module RPG
#------------------------------------------------------------------------------
# The coding used in checking the noteboxes of the synthesizable items.
#==============================================================================
module RPG
class BaseItem
def s_cost # The price of the synthesized good.
@s_cost = self.note[/\\COST\[(\d+)\]/i] != nil ? $1.to_i : 0 if @s_cost == nil
return @s_cost
end
def s_req_1_type # The object type of the first required material.
@s_req_1_type = self.note[/\\TYPE1\[(\d+)\]/i] != nil ? $1.to_i : 0 if @s_req_1_type == nil
return @s_req_1_type
end
def s_req_1_id # The ID of the first required material.
@s_req_1_id = self.note[/\\ID1\[(\d+)\]/i] != nil ? $1.to_i : 1 if @s_req_1_id == nil
return @s_req_1_id
end
def s_req_2_type # The object type of the second required material.
@s_req_2_type = self.note[/\\TYPE2\[(\d+)\]/i] != nil ? $1.to_i : 0 if @s_req_2_type == nil
return @s_req_2_type
end
def s_req_2_id # The ID of the second required material.
@s_req_2_id = self.note[/\\ID2\[(\d+)\]/i] != nil ? $1.to_i : 1 if @s_req_2_id == nil
return @s_req_2_id
end
end
end
#==============================================================================
# ** Scene_Map
#------------------------------------------------------------------------------
# The switch redirecting a normal shop call to a synthesis shop.
#==============================================================================
class Scene_Map < Scene_Base
def call_shop
$game_temp.next_scene = nil
if $game_switches[Synth_Switch::Synthesis_Switch]
$scene = Scene_Synthesis.new
else
$scene = Scene_Shop.new
end
end
end
#==============================================================================
# ** Window_Base
#------------------------------------------------------------------------------
# Adding a bit to the window base to add transparency to faces.
#==============================================================================
class Window_Base < Window
def draw_face(face_name, face_index, x, y, size = 96, opacity = 255)
bitmap = Cache.face(face_name)
rect = Rect.new(0, 0, 0, 0)
rect.x = face_index % 4 * 96 + (96 - size) / 2
rect.y = face_index / 4 * 96 + (96 - size) / 2
rect.width = size
rect.height = size
self.contents.blt(x, y, bitmap, rect,opacity)
bitmap.dispose
end
def draw_actor_face(actor, x, y, size = 96, opacity = 255)
draw_face(actor.face_name, actor.face_index, x, y, size, opacity)
end
end
#==============================================================================
# ** Window_SynthBuy
#------------------------------------------------------------------------------
# This window displays the synthesizable goods in the synthesis shop.
#==============================================================================
class Window_SynthBuy < Window_Selectable
#--------------------------------------------------------------------------
# * Object Initialization
# x : window X coordinate
# y : window Y coordinate
#--------------------------------------------------------------------------
def initialize(x, y)
super(x, y, 304, 232)
@shop_goods = $game_temp.shop_goods
refresh
self.index = 0
end
#--------------------------------------------------------------------------
# * Get Item
#--------------------------------------------------------------------------
def item
return @data[self.index]
end
#--------------------------------------------------------------------------
# * Get Required Material One
#--------------------------------------------------------------------------
def req1
type1 = item.s_req_1_type
id1 = item.s_req_1_id
case type1
when 0
@req1 = $data_items[id1]
when 1
@req1 = $data_weapons[id1]
when 2
@req1 = $data_armors[id1]
end
return @req1
end
#--------------------------------------------------------------------------
# * Get Required Material Two
#--------------------------------------------------------------------------
def req2
type2 = item.s_req_2_type
id2 = item.s_req_2_id
case type2
when 0
@req2 = $data_items[id2]
when 1
@req2 = $data_weapons[id2]
when 2
@req2 = $data_armors[id2]
end
return @req2
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
@data = []
for goods_item in @shop_goods
case goods_item[0]
when 0
item = $data_items[goods_item[1]]
when 1
item = $data_weapons[goods_item[1]]
when 2
item = $data_armors[goods_item[1]]
end
if item != nil
@data.push(item)
end
end
@item_max = @data.size
create_contents
for i in 0...@item_max
draw_item(i)
end
end
#--------------------------------------------------------------------------
# * Draw Item
#--------------------------------------------------------------------------
def draw_item(index)
item = @data[index]
number = $game_party.item_number(item)
type1 = item.s_req_1_type
id1 = item.s_req_1_id
case type1
when 0
req1 = $data_items[id1]
when 1
req1 = $data_weapons[id1]
when 2
req1 = $data_armors[id1]
end
type2 = item.s_req_2_type
id2 = item.s_req_2_id
case type2
when 0
req2 = $data_items[id2]
when 1
req2 = $data_weapons[id2]
when 2
req2 = $data_armors[id2]
end
if req1 == req2
enabled = (item.s_cost <= $game_party.gold and number < 99 and $game_party.item_number(req1) > 1)
else
enabled = (item.s_cost <= $game_party.gold and number < 99 and $game_party.item_number(req1) > 0 and $game_party.item_number(req2) > 0)
end
rect = item_rect(index)
self.contents.clear_rect(rect)
draw_item_name(item, rect.x, rect.y, enabled)
rect.width -= 4
self.contents.draw_text(rect, item.s_cost, 2)
end
#--------------------------------------------------------------------------
# * Help Text Update
#--------------------------------------------------------------------------
def update_help
@help_window.set_text(item == nil ? "" : item.description)
end
end
#==============================================================================
# ** Window_SynthStatus1
#------------------------------------------------------------------------------
# This window displays the current amount of gold, the number of items
# possessed, and the number of items currently equiped.
#==============================================================================
class Window_SynthStatus1 < Window_Base
#--------------------------------------------------------------------------
# * Object Initialization
# x : window X coordinate
# y : window Y coordinate
#--------------------------------------------------------------------------
def initialize(x, y)
super(x, y, 240, 116)
@item = nil
refresh
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
self.contents.font.color = system_color
self.contents.draw_text(4, 0, 200, WLH*1.5, "Funds")
cd = contents.text_size(Vocab::gold).width
self.contents.font.color = normal_color
self.contents.draw_text(4, 0, 200-cd-2, WLH*1.5, $game_party.gold, 2)
self.contents.font.color = system_color
self.contents.draw_text(4, 0, 200, WLH*1.5, Vocab::gold, 2)
number = $game_party.item_number(@item)
self.contents.font.color = system_color
self.contents.draw_text(4, 0, 190, WLH*3.5, "Stock")
self.contents.font.color = normal_color
self.contents.draw_text(4, 0, 190, WLH*3.5, number, 2)
number2 = 0
for actor in $game_party.members
if actor.equips.include?(@item) then number2 = number2 + 1
end
end
self.contents.font.color = system_color
self.contents.font.color.alpha = @item.is_a?(RPG::Item) ? 128 : 255
self.contents.draw_text(4, 0, 190, WLH*5.5, "Equiped")
self.contents.font.color = normal_color
self.contents.font.color.alpha = @item.is_a?(RPG::Item) ? 128 : 255
self.contents.draw_text(4, 0, 190, WLH*5.5, number2, 2)
end
#--------------------------------------------------------------------------
# * Set Item
#--------------------------------------------------------------------------
def item=(item)
if @item != item
@item = item
refresh
end
end
end
#==============================================================================
# ** Window_SynthRequire
#------------------------------------------------------------------------------
# This window displays the items necessary to synthesize.
#==============================================================================
class Window_SynthRequire < Window_Base
#--------------------------------------------------------------------------
# * Object Initialization
# x : window X coordinate
# y : window Y coordinate
#--------------------------------------------------------------------------
def initialize(x, y)
super(x, y, 240, 116)
@item = nil
@req1 = nil
@req2 = nil
refresh
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
if @item != nil
self.contents.font.color = system_color
self.contents.draw_text(4, 0, 200, WLH, "Requires")
enabled = ($game_party.item_number(@req1) > 0)
draw_item_name(@req1, 15, 25, enabled)
enabled = @req1==@req2 ? ($game_party.item_number(@req2) > 1) : ($game_party.item_number(@req2) > 0)
draw_item_name(@req2, 15, 52, enabled)
end
end
#--------------------------------------------------------------------------
# * Set Item
#--------------------------------------------------------------------------
def item=(item)
if @item != item
@item = item
type1 = item.s_req_1_type
id1 = item.s_req_1_id
case type1
when 0
@req1 = $data_items[id1]
when 1
@req1 = $data_weapons[id1]
when 2
@req1 = $data_armors[id1]
end
type2 = item.s_req_2_type
id2 = item.s_req_2_id
case type2
when 0
@req2 = $data_items[id2]
when 1
@req2 = $data_weapons[id2]
when 2
@req2 = $data_armors[id2]
end
refresh
end
end
end
#==============================================================================
# ** Window_SynthStatus2
#------------------------------------------------------------------------------
# This displays how much of an improvement or disadvantage the equipment gives
# to the individual actors in the current party. If the selection is an item
# rather than equipment, then nothing will happen.
#==============================================================================
class Window_SynthStatus2 < Window_Base
#--------------------------------------------------------------------------
# * Object Initialization
# x : window X coordinate
# y : window Y coordinate
#--------------------------------------------------------------------------
def initialize(x, y)
super(x, y, 544, 128)
@item = nil
refresh
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
if @item != nil
number = $game_party.item_number(@item)
for actor in $game_party.members
#--------------------------------------------------------------------
# This can be used to center the actor's pictures instead, if it looks
# awkward with more or less than four actors in a party at one time.
#--------------------------------------------------------------------
#o = $game_party.members.size
#x = ((actor.index+1)*((self.width-32)/o))-(((self.width-32)/o)/2)-48
x = actor.index*136
y = 0
draw_actor_parameter_change(actor, x, y)
end
end
end
#--------------------------------------------------------------------------
# * Draw Actor's Current Equipment and Parameters
# actor : actor
# x : draw spot x-coordinate
# y : draw spot y-coordinate
#--------------------------------------------------------------------------
def draw_actor_parameter_change(actor, x, y)
return if @item.is_a?(RPG::Item)
enabled = actor.equippable?(@item)
draw_actor_face(actor, x, y, size = 96, opacity = enabled ? 255 : 100)
self.contents.font.color = text_color(15)
self.contents.font.color.alpha = enabled ? 180 : 60
self.contents.draw_text(x+2, y+2, 200, WLH, actor.name)
self.contents.font.color = normal_color
self.contents.font.color.alpha = enabled ? 255 : 100
self.contents.draw_text(x, y, 200, WLH, actor.name)
if @item.is_a?(RPG::Weapon)
item1 = weaker_weapon(actor)
elsif actor.two_swords_style and @item.kind == 0
item1 = nil
else
item1 = actor.equips[1 + @item.kind]
end
if enabled
if @item.is_a?(RPG::Weapon)
atk1 = item1 == nil ? 0 : item1.atk
atk2 = @item == nil ? 0 : @item.atk
change = atk2 - atk1
else
def1 = item1 == nil ? 0 : item1.def
def2 = @item == nil ? 0 : @item.def
change = def2 - def1
end
self.contents.font.color = text_color(15)
self.contents.font.color.alpha = enabled ? 180 : 60
self.contents.draw_text(x, y + 72, 96, WLH, sprintf("%+d", change), 2)
if change == 0
self.contents.font.color = normal_color
end
if change > 0
self.contents.font.color = power_up_color
end
if change < 0
self.contents.font.color = power_down_color
end
self.contents.draw_text(x, y + 70, 96, WLH, sprintf("%+d", change), 2)
end
end
#--------------------------------------------------------------------------
# * Get Weaker Weapon Equipped by the Actor (for dual wielding)
# actor : actor
#--------------------------------------------------------------------------
def weaker_weapon(actor)
if actor.two_swords_style
weapon1 = actor.weapons[0]
weapon2 = actor.weapons[1]
if weapon1 == nil or weapon2 == nil
return nil
elsif weapon1.atk < weapon2.atk
return weapon1
else
return weapon2
end
else
return actor.weapons[0]
end
end
#--------------------------------------------------------------------------
# * Set Item
# item : new item
#--------------------------------------------------------------------------
def item=(item)
if @item != item
@item = item
refresh
end
end
end
#==============================================================================
# ** Window_SynthNumber
#------------------------------------------------------------------------------
# This window is for inputting quantity of items to synthesize on the
# synth screen.
#==============================================================================
class Window_SynthNumber < Window_Base
#--------------------------------------------------------------------------
# * Object Initialization
# x : window X coordinate
# y : window Y coordinate
#--------------------------------------------------------------------------
def initialize(x, y)
super(x, y, 304, 232)
@item = nil
@max = 1
@price = 0
@number = 1
@req1 = nil
@req2 = nil
end
#--------------------------------------------------------------------------
# * Set Items, Max Quantity, and Price
#--------------------------------------------------------------------------
def set(item, max, price)
@item = item
@max = max
@price = item.s_cost
type1 = item.s_req_1_type
id1 = item.s_req_1_id
case type1
when 0
@req1 = $data_items[id1]
when 1
@req1 = $data_weapons[id1]
when 2
@req1 = $data_armors[id1]
end
type2 = item.s_req_2_type
id2 = item.s_req_2_id
case type2
when 0
@req2 = $data_items[id2]
when 1
@req2 = $data_weapons[id2]
when 2
@req2 = $data_armors[id2]
end
@number = 1
refresh
end
#--------------------------------------------------------------------------
# * Set Inputted Quantity
#--------------------------------------------------------------------------
def number
return @number
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
y = 20
self.contents.clear
draw_item_name(@item, 0, y)
self.contents.font.color = normal_color
self.contents.draw_text(212, y, 20, WLH, "×")
self.contents.draw_text(248, y, 20, WLH, @number, 2)
self.cursor_rect.set(244, y, 28, WLH)
self.contents.font.color = system_color
self.contents.draw_text(0, y + (2.5*WLH), 200, WLH, "Requires:")
self.contents.font.color = normal_color
draw_item_name(@req1, 10, y + (3.5*WLH))
self.contents.draw_text(212, y + (3.5*WLH), 20, WLH, "×")
self.contents.draw_text(248, y + (3.5*WLH), 20, WLH, @number, 2)
draw_item_name(@req2, 10, y + (4.5*WLH))
self.contents.draw_text(212, y + (4.5*WLH), 20, WLH, "×")
self.contents.draw_text(248, y + (4.5*WLH), 20, WLH, @number, 2)
draw_currency_value(@price * @number, 4, y + (6.5*WLH), 264)
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
if self.active
last_number = @number
if Input.repeat?(Input::RIGHT) and @number < @max
@number += 1
end
if Input.repeat?(Input::LEFT) and @number > 1
@number -= 1
end
if Input.repeat?(Input::UP) and @number < @max
@number = [@number + 10, @max].min
end
if Input.repeat?(Input::DOWN) and @number > 1
@number = [@number - 10, 1].max
end
if @number != last_number
Sound.play_cursor
refresh
end
end
end
end
#==============================================================================
# ** Scene_Synthesis
#------------------------------------------------------------------------------
# This class performs the actual synthesis, much like a shop.
#==============================================================================
class Scene_Synthesis < Scene_Base
#--------------------------------------------------------------------------
# * Start processing
#--------------------------------------------------------------------------
def start
super
create_menu_background
@help_window = Window_Help.new
@buy_window = Window_SynthBuy.new(0, 56)
@buy_window.active = true
@buy_window.visible = true
@buy_window.help_window = @help_window
@number_window = Window_SynthNumber.new(0, 56)
@number_window.active = false
@number_window.visible = false
@status1_window = Window_SynthStatus1.new(304, 56)
@status1_window.item = @buy_window.item
@status1_window.visible = true
@status2_window = Window_SynthStatus2.new(0, 288)
@status2_window.item = @buy_window.item
@status2_window.visible = true
@require_window = Window_SynthRequire.new(304, 172)
@require_window.visible = true
@require_window.item = @buy_window.item
end
#--------------------------------------------------------------------------
# * Termination Processing
#--------------------------------------------------------------------------
def terminate
super
dispose_menu_background
@help_window.dispose
@buy_window.dispose
@number_window.dispose
@status1_window.dispose
@status2_window.dispose
@require_window.dispose
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
update_menu_background
@help_window.update
@buy_window.update
@number_window.update
@status1_window.update
@status2_window.update
@require_window.update
if @buy_window.active
update_buy_selection
elsif @number_window.active
update_number_input
end
end
#--------------------------------------------------------------------------
# * Update Buy Item Selection
#--------------------------------------------------------------------------
def update_buy_selection
@status1_window.item = @buy_window.item
@status2_window.item = @buy_window.item
@require_window.item = @buy_window.item
if Input.trigger?(Input::B)
Sound.play_decision
$scene = Scene_Map.new
end
if Input.trigger?(Input::C)
@item = @buy_window.item
@req1 = @buy_window.req1
@req2 = @buy_window.req2
if @req1 == @req2 and $game_party.item_number(@req1) <= 1
req3 = true
end
number = $game_party.item_number(@item)
if @item == nil or @item.s_cost > $game_party.gold or number == 99 or $game_party.item_number(@req1) == 0 or $game_party.item_number(@req2) == 0 or req3 == true
Sound.play_buzzer
else
Sound.play_decision
max = @item.s_cost == 0 ? 99 : $game_party.gold / @item.s_cost
if @req1 != @req2
if max > $game_party.item_number(@req1) or max > $game_party.item_number(@req2)
max = $game_party.item_number(@req1) <= $game_party.item_number(@req2) ? $game_party.item_number(@req1) : $game_party.item_number(@req2)
end
else
if max > ($game_party.item_number(@req1)/2)
max = ($game_party.item_number(@req1)/2)
end
end
max = [max, 99 - number].min
@buy_window.active = false
@buy_window.visible = false
@number_window.set(@item, max, @item.s_cost)
@number_window.active = true
@number_window.visible = true
end
end
end
#--------------------------------------------------------------------------
# * Update Number Input
#--------------------------------------------------------------------------
def update_number_input
if Input.trigger?(Input::B)
cancel_number_input
elsif Input.trigger?(Input::C)
decide_number_input
end
end
#--------------------------------------------------------------------------
# * Cancel Number Input
#--------------------------------------------------------------------------
def cancel_number_input
Sound.play_cancel
@number_window.active = false
@number_window.visible = false
@buy_window.active = true
@buy_window.visible = true
end
#--------------------------------------------------------------------------
# * Confirm Number Input
#--------------------------------------------------------------------------
def decide_number_input
Sound.play_shop
@number_window.active = false
@number_window.visible = false
$game_party.lose_gold(@number_window.number * @item.s_cost)
$game_party.gain_item(@item, @number_window.number)
$game_party.lose_item(@req1, @number_window.number)
$game_party.lose_item(@req2, @number_window.number)
@buy_window.refresh
@status1_window.refresh
@status2_window.refresh
@require_window.refresh
@buy_window.active = true
@buy_window.visible = true
end
end
Credit
Thanks
- dartdaman, for requesting this.
- Final Fantasy IX...? Sure, thanks Square.
Known Issues
I'll be honest, I have absolutely no idea if this will work with
any of the other custom item scripts. It should work for most scripts save for things like MA's Grid Inventory script, I imagine, but let me know if you find something it doesn't work with that it should.
Demo
See Attached.
Author's Notes
Yes, I'm perfectly aware that there are other (and probably better) synthesis scripts out there. However, I made this anyways for two reasons. One, I wanted something as close as possible to the system they had in Final Fantasy IX, and two, I just wanted to see if I had learned enough to make a full custom script on my own. I think I succeeded, so yay me.