Okay, this is driving me absolutely nuts so hopefully someone will know the answer.
I'm currently working on a script request for a friend (to those here whose requests I said I would look at, don't worry, they're coming!) where he needs shops to track what items are sold, and unlock new items depending on what you've sold to the shop. That part works perfectly, yay!
However, I also added a message box that tells you which items were unlocked (so that you know what shiny new toys you just got, obviously). The problem is that although the message box appears, the shop is still active and pressing enter doesn't get rid of the message. I need input for the shop to wait until the message box is done with, but no matter what I try I can't seem to figure out how.
Here's the snippet I have so far that deals with the message:
if !added_items.empty?
$game_message.add("Thanks! I can now sell you the following items:")
added_items.each_with_index do |item, i|
if i < added_items.size - 1
$game_message.add("#{item}, ")
else
$game_message.add("#{item}")
end
end
@message_window.update
end
If anyone can offer any insight on how to suppress input for a scene while a message is showing (and for that matter how to get the message box to recognise input) I would be really appreciative.
What version of rpg maker are you using? That is an important bit of information.
Oh, poo bunnies, knew I'd forgotten something!
I'm using VX Ace.
lol cool...well I was looking and I can't find a clear reason what-so-ever but I have a theory...try @message_window.activate i think to make that window active...
Maybe you can try adding a conditional like
if @message_window.visible == true
if Input.trigger?(:C) || Input.trigger?(:B)
@message_window.visible = false
end
end
It's just a theory though and I'm not THAT experienced in RGSS.
I'd already tried adding a .activate which didn't seem to do anything at all.
I tried adding a conditional like you said as well but that doesn't appear to have any effect. :(
Doh! :( You have the whole thing up somewhere so we (or at least I) can look at it? I might be able to come up with a much better idea if I saw the whole thing and could work from there to build onto it.
$imported = {} if $imported.nil?
$imported['cshop'] = true
puts 'Load: Shop script by Clyve'
module CSHOP
module REGEXP
ITEM_REQ = /<require ([IWA])(\d+), (\d+)>/i
end
end
class RPG::ShopSales
#------------------------
attr_accessor :item_sales
attr_accessor :weapon_sales
attr_accessor :armor_sales
#------------------------
def initialize
# arrys that track how many each item has been sold. index = item id
@item_sales = []
@weapon_sales = []
@armor_sales = []
end
end
class Scene_Shop < Scene_MenuBase
alias :shopsales_prepare :prepare
def prepare(goods, purchase_only)
shopsales_prepare(goods, purchase_only)
add_available_goods
end
alias :shopsales_start :start
def start
shopsales_start
@message_window = Window_Message.new
end
def add_available_goods
# CHECK NOTETAGS AND WHETHER $data_shopsales's DATA IS ENOUGH
# FOR THE ITEMS TO BE AVAILABLE OR NOT, THEN ADD THE ITEM TO @goods
# IF ITS AVAILABLE.
# @goods is an array with three values
# @goods[0] is either 0, 1, or 2.
# 0 is Items ($data_items)
# 1 is Weapons ($data_weapons)
# 2 is Armors ($data_armors)
# @goods[1] is the index of the item.
# @goods[2] is a different price than the one in the database, it needs to
# be set to 0 for it to use the price in the database
for i in 1...$data_items.size
if !$data_items[i].sell_req.empty?
include = true
for req in $data_items[i].sell_req
if req[0] == 0
if $data_shopsales.item_sales[req[1]] < req[2]
include = false
end
elsif req[0] == 1
if $data_shopsales.weapon_sales[req[1]] < req[2]
include = false
end
elsif req[0] == 2
if $data_shopsales.armor_sales[req[1]] < req[2]
include = false
end
end
end
@goods.push([0, i, 0]) if include == true
end
# This is where you'll use @goods[0]
end
for i in 1...$data_weapons.size
if !$data_weapons[i].sell_req.empty?
include = true
for req in $data_weapons[i].sell_req
if req[0] == 0
if $data_shopsales.item_sales[req[1]] < req[2]
include = false
end
elsif req[0] == 1
if $data_shopsales.weapon_sales[req[1]] < req[2]
include = false
end
elsif req[0] == 2
if $data_shopsales.armor_sales[req[1]] < req[2]
include = false
end
end
end
@goods.push([1, i, 0]) if include == true
end
# This is where you'll use @goods[1]
end
for i in 1...$data_armors.size
if !$data_armors[i].sell_req.empty?
include = true
for req in $data_armors[i].sell_req
if req[0] == 0
if $data_shopsales.item_sales[req[1]] < req[2]
include = false
end
elsif req[0] == 1
if $data_shopsales.weapon_sales[req[1]] < req[2]
include = false
end
elsif req[0] == 2
if $data_shopsales.armor_sales[req[1]] < req[2]
include = false
end
end
end
@goods.push([2, i, 0]) if include == true
end
# This is where you'll use @goods[2]
end
end
# Increase Items of Type Sold
alias :shopsales_do_sell :do_sell
def do_sell(number)
shopsales_do_sell(number)
added_items = []
case item_type
when 0
$data_shopsales.item_sales[@item.id] += number
# This is where you'll use @goods[0]
when 1
$data_shopsales.weapon_sales[@item.id] += number
# This is where you'll use @goods[1]
when 2
$data_shopsales.armor_sales[@item.id] += number
# This is where you'll use @goods[2]
end
for i in 1...$data_items.size
if !$data_items[i].sell_req.empty?
include = true
for req in $data_items[i].sell_req
if req[0] == 0
if $data_shopsales.item_sales[req[1]] < req[2]
include = false
end
elsif req[0] == 1
if $data_shopsales.weapon_sales[req[1]] < req[2]
include = false
end
elsif req[0] == 2
if $data_shopsales.armor_sales[req[1]] < req[2]
include = false
end
end
end
if include == true && !@goods.include?([0, i, 0])
@goods.push([0, i, 0])
added_items.push($data_items[i].name)
end
end
end
for i in 1...$data_weapons.size
if !$data_weapons[i].sell_req.empty?
include = true
for req in $data_weapons[i].sell_req
if req[0] == 0
if $data_shopsales.item_sales[req[1]] < req[2]
include = false
end
elsif req[0] == 1
if $data_shopsales.weapon_sales[req[1]] < req[2]
include = false
end
elsif req[0] == 2
if $data_shopsales.armor_sales[req[1]] < req[2]
include = false
end
end
end
if include == true && !@goods.include?([1, i, 0])
@goods.push([1, i, 0])
added_items.push($data_weapons[i].name)
end
end
end
for i in 1...$data_armors.size
if !$data_armors[i].sell_req.empty?
include = true
for req in $data_armors[i].sell_req
if req[0] == 0
if $data_shopsales.item_sales[req[1]] < req[2]
include = false
end
elsif req[0] == 1
if $data_shopsales.weapon_sales[req[1]] < req[2]
include = false
end
elsif req[0] == 2
if $data_shopsales.armor_sales[req[1]] < req[2]
include = false
end
end
end
if include == true && !@goods.include?([2, i, 0])
@goods.push([2, i, 0])
added_items.push($data_armors[i].name)
end
end
end
if !added_items.empty?
$game_message.add("Thanks! I can now sell you the following items:")
added_items.each_with_index do |item, i|
if i < added_items.size - 1
$game_message.add("#{item}, ")
else
$game_message.add("#{item}")
end
end
@message_window.update
end
end
# Checks Item Type of @item
def item_type
if @item.is_a?(RPG::Item)
return 0
elsif @item.is_a?(RPG::Weapon)
return 1
elsif @item.is_a?(RPG::Armor)
return 2
end
end
end
module DataManager
# Initialize Shop Sales data
class <<self; alias shopsales_load_database load_database; end
def self.load_database
shopsales_load_database
$data_shopsales = RPG::ShopSales.new
load_item_notetags
init_shopsales_data
end
def self.load_item_notetags
groups = [$data_items, $data_weapons, $data_armors]
for group in groups
for obj in group
next if obj.nil?
obj.load_item_notetags
end
end
puts "Read: Item Requirements Notetags"
end
def self.init_shopsales_data
for index in 0..$data_items.size
$data_shopsales.item_sales[index] = 0
end
for index in 0..$data_weapons.size
$data_shopsales.weapon_sales[index] = 0
end
for index in 0..$data_armors.size
$data_shopsales.armor_sales[index] = 0
end
end
# Dump Shop Sales data into save file
class <<self; alias shopsales_make_save_contents make_save_contents; end
def self.make_save_contents
shopsales_make_save_contents
contents[:shopsales] = $data_shopsales
contents
end
# Load Shop Sales data from save file
class <<self; alias shopsales_extract_save_contents extract_save_contents; end
def self.extract_save_contents(contents)
shopsales_extract_save_contents(contents)
if contents[:shopsales]
$data_shopsales = contents[:shopsales]
else
$data_shopsales = RPG::ShopSales.new
init_shopsales_data
end
end
end
class RPG::BaseItem
attr_reader :sell_req
def load_item_notetags
@sell_req = []
@note.split(/[\r\n]+/).each do |line|
case line
when CSHOP::REGEXP::ITEM_REQ
case $1
when "I"
@sell_req.push([0, $2.to_i, $3.to_i])
when "W"
@sell_req.push([1, $2.to_i, $3.to_i])
when "A"
@sell_req.push([2, $2.to_i, $3.to_i])
end
end
end
end
end
thanks I'll take a look and see what I can come up with.
Appreciate it, I've tried pretty much everything I could think of and I just can't get my head around it.
Quote from: Trihan on May 05, 2012, 08:43:20 PM
Appreciate it, I've tried pretty much everything I could think of and I just can't get my head around it.
Can you explain the usage a little for me so i can test this while I'm working on it? I noticed your note-tag thing up at the top but a brief explanation would be appreciated.
I saw the "<require ([IWA])(\d+), (\d+)>" portion and I was curious about that mostly
And it's really no problem. I try to help with scripts when I can because I find it is good for me so I can learn the stuff as I do it :)
Yeah. If you put <require [I, W or A depending on whether the requirement is an item, weapon or armour][item id], [quantity]> in an item's notetag, it will be added to the shop's available stock when you've sold the required item(s). If you want multiple requirements, just use more than one tag.
Example: If I want the shop to sell Hi-Potion after I sell it 5 Potions, I'd put
<require I1, 5>
in the notetag for Hi-Potion.
Cool cool. I'll get to work on it. Just remembered I needed to work on a flyer for my friend's art exhibit and I been putting it off lmao. I'll work on this after and see if I can come up with some ideas.
Have you tried deactivating the shops windows?
I'll try looking in it too, maybe we can find something together ;)
EDIT:
Strange, I can't get it to work Oo
it won't enter the do_sell method it seems, so there's no update to the amount of items sold...
Any ideas?
Quote from: mobychan on May 06, 2012, 06:56:16 AM
Have you tried deactivating the shops windows?
I'll try looking in it too, maybe we can find something together ;)
EDIT:
Strange, I can't get it to work Oo
it won't enter the do_sell method it seems, so there's no update to the amount of items sold...
Any ideas?
Yeah I'm kind of lost too. I tried a few things but I don't think it's working. I'm thinking you're going to need to create a custom message window and not use the default one and when you do it, use the set_handler function so like when you meet the conditions of the sell, it will show the new custom message window and pass on the information that you want it to show and activate the custom window. The handlers could be :ok and :cancel and both link to the same method that hides and deactivates the custom message window and activates the window that was previously active which is probably the sell window considering the nature of the script.
The thing is, I've tried that as well. It shows the custom window but I can't seem to get it to accept input so it just kind of hangs there.
did you implement the right methods (ok/cancel or whatever you called the handlers) and set them to your window?
something like this:
@window_list.set_handler(:ok, method(:on_list_ok))
@window_list.set_handler(:cancel, method(:on_list_cancel))
Here's what I have:
if !added_items.empty?
@sell_window.deactivate
@unlock_window = Window_Unlocks.new(added_items.size + 1)
@unlock_window.set_handler(:ok, method(:on_unlock_cancel))
@unlock_window.set_handler(:cancel, method(:on_unlock_cancel))
@unlock_window.display_items(added_items)
@unlock_window.show.activate
end
then the on_unlock_cancel method is
def on_unlock_cancel
puts "Success"
@sell_window.activate
@unlock_window.dispose
end
I'm not getting anything in the debug window, so it's clearly not running the handler method. However, it's definitely showing the window and activating it.
Have you tried using a Window_Command or Window_Selectable as Base Class?
I'm not sure if Input is being processed in a normal window
Edit: Ok input is not processed in Window_Base
It is a Window_Selectable.
Edit: For completion's sake, here's the window code:
class Window_Unlocks < Window_Selectable
def initialize(num_items)
super(0, 0, 240, fitting_height(num_items))
self.back_opacity = 255
update_placement
@show_count = 0
end
def update_placement
self.x = (Graphics.width - width) / 2
self.y = (Graphics.height - height) / 2
self.z = 255
end
def display_items(items)
contents.clear
draw_text(0, 0, contents_width, line_height, "ITEMS UNLOCKED", 1)
items.each_with_index do |item, i|
draw_icon(item.icon_index, 0, line_height * (i + 1), true)
draw_text(0, line_height * (i + 1), contents_width, line_height, item.name, 1)
end
end
end
I actually think I know what the issue is, though I don't know how to resolve it.
Basically my do_sell alias is activating the custom window, but then immediately after the end_number_input method is reactivating the sell window. I need to find a way to "pause" input until the custom window is gone.
Maybe you forgot to call super in the update method of your scene?
I think I once forgot that too and it had the same effect...
Scene_Shop doesn't seem to have an update method.
It inherits the update method of Scene_MenuBase, which inherits it from Scene_Base. An here it updates the Input:
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
update_basic
end
#--------------------------------------------------------------------------
# * Update Frame (Basic)
#--------------------------------------------------------------------------
def update_basic
Graphics.update
Input.update
update_all_windows
end
How do you call the update method of a scene in the middle of the scene, though? There's no example of that being done anywhere in the default scripts.
It's called automatically in Scene_Base:
#--------------------------------------------------------------------------
# * Main
#--------------------------------------------------------------------------
def main
start
post_start
update until scene_changing?
pre_terminate
terminate
end
Okay, so I'm back to the problem of the custom window not accepting input because the sell window is being reactivated right after I activate it. :D
maybe an if clause inside the update method, that (de)activates the windows accordingly?
Can you find out where it gets activated again?
def on_number_ok
Sound.play_shop
case @command_window.current_symbol
when :buy
do_buy(@number_window.number)
when :sell
do_sell(@number_window.number)
end
end_number_input
@gold_window.refresh
@status_window.refresh
end
def end_number_input
@number_window.hide
case @command_window.current_symbol
when :buy
activate_buy_window
when :sell
activate_sell_window
end
end
As far as I can tell, it's calling do_sell when you confirm the quantity, then calling end_number_input, which calls activate_sell_window.
Progress! I've got it accepting input for the custom window but the quantity window disappears first which makes it look a bit naff.
Woohoo! Got it! It works perfectly now. :D
care to share the current code once more?
I'll see if I can get it to work here and look into it, if you want ^^
Now that I've resolved the issue, I'll post the finished script in the VXA forum once the guy I'm making it for has confirmed it does everything he wanted it to.
Sweet :) Sorry I couldn't help too much. Looking forward to seeing the whole thing :)