The RPG Maker Resource Kit

RMRK RPG Maker Creation => RPG Maker General => General Scripting => Topic started by: Trihan on May 05, 2012, 07:51:12 PM

Title: [SOLVED] [VXA] Message boxes in scenes other than map
Post by: Trihan on May 05, 2012, 07:51:12 PM
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.
Title: Re: Message boxes in scenes other than map
Post by: Lethrface on May 05, 2012, 07:55:17 PM
What version of rpg maker are you using?  That is an important bit of information.
Title: Re: Message boxes in scenes other than map
Post by: Trihan on May 05, 2012, 08:01:02 PM
Oh, poo bunnies, knew I'd forgotten something!

I'm using VX Ace.
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Lethrface on May 05, 2012, 08:17:33 PM
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.
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Trihan on May 05, 2012, 08:20:54 PM
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. :(
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Lethrface on May 05, 2012, 08:33:22 PM
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.
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Trihan on May 05, 2012, 08:39:26 PM
$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
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Lethrface on May 05, 2012, 08:41:46 PM
thanks I'll take a look and see what I can come up with.
Title: Re: [VXA] Message boxes in scenes other than map
Post by: 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.
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Lethrface on May 05, 2012, 08:49:52 PM
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 :)
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Trihan on May 05, 2012, 08:52:18 PM
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.
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Lethrface on May 05, 2012, 09:30:20 PM
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.
Title: Re: [VXA] Message boxes in scenes other than map
Post by: 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?
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Lethrface on May 06, 2012, 07:39:58 AM
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. 
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Trihan on May 06, 2012, 09:23:18 AM
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.
Title: Re: [VXA] Message boxes in scenes other than map
Post by: mobychan on May 06, 2012, 09:39:24 AM
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))
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Trihan on May 06, 2012, 09:41:21 AM
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.
Title: Re: [VXA] Message boxes in scenes other than map
Post by: mobychan on May 06, 2012, 09:46:26 AM
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
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Trihan on May 06, 2012, 09:47:04 AM
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.
Title: Re: [VXA] Message boxes in scenes other than map
Post by: mobychan on May 06, 2012, 09:51:48 AM
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...
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Trihan on May 06, 2012, 09:55:45 AM
Scene_Shop doesn't seem to have an update method.
Title: Re: [VXA] Message boxes in scenes other than map
Post by: mobychan on May 06, 2012, 10:00:36 AM
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
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Trihan on May 06, 2012, 10:03:53 AM
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.
Title: Re: [VXA] Message boxes in scenes other than map
Post by: mobychan on May 06, 2012, 10:11:24 AM
It's called automatically in Scene_Base:


  #--------------------------------------------------------------------------
  # * Main
  #--------------------------------------------------------------------------
  def main
    start
    post_start
    update until scene_changing?
    pre_terminate
    terminate
  end
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Trihan on May 06, 2012, 10:56:24 AM
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
Title: Re: [VXA] Message boxes in scenes other than map
Post by: mobychan on May 06, 2012, 10:58:43 AM
maybe an if clause inside the update method, that (de)activates the windows accordingly?
Can you find out where it gets activated again?
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Trihan on May 06, 2012, 11:29:16 AM
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.
Title: Re: [VXA] Message boxes in scenes other than map
Post by: Trihan on May 06, 2012, 11:33:29 AM
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
Title: Re: [VXA] Message boxes in scenes other than map
Post by: mobychan on May 06, 2012, 11:40:05 AM
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 ^^
Title: Re: [SOLVED] [VXA] Message boxes in scenes other than map
Post by: Trihan on May 06, 2012, 12:15:35 PM
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.
Title: Re: [SOLVED] [VXA] Message boxes in scenes other than map
Post by: Lethrface on May 06, 2012, 05:11:54 PM
Sweet :)  Sorry I couldn't help too much.  Looking forward to seeing the whole thing :)