Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Alchemy Script - Development and Support Topic

Today, I bring to you a script in progress. I will be posting my code for public review so hopefully somebody with a trained eye will be able to detect any possible error in judgement or conduct on my part, or give me advice on what I am trying to do. Although there maybe no questions at the moment, I will later be posting questions and asking for comments, so I can learn how to better script.

Although this will be first public script here at .org, I have made a few little things here and there, this is my first 'real' full scene script, so I will need some help later on with... whatever the hell I get stumped on, but I'm rockin' steady for the time being. For now, I am pasting the script as-is, meaning it is unfinished and subject to change. Matter of fact, the Window_ stuff isn't even done, so this script is currently useless.

Keep in mind this is a script in progress, and will later be a part of my custom CMS in the (not so...) near future. When I am finally done with this, with all of your help and support, I want this to be my first 'REAL' script to post in the submitted scripts forum :D

So, what does it do?
It is an "Alchemy" script. You will be able to set up Items (with special 'elemental' attributes), and fuse and bind them together to create better, or even rare items. It was inspired by Deke's crafting script, and the Materia Fusion system from Crisis Core. With it you can fuse items, weapons, and different 'armor' types to create new ones. For anybody familiar with Deke's script, it will come with a seperate "Recipe" class which is a public class for you to write your recipes. Each recipe has a Fusion Point cost to it, but you can also Convert your items into FP and... you'll just have to see when its done.

Code:
class Recipe
  def initialize
    #[Attribute Readers]--------------------------------------------------------
    attr_reader :id               # Recipe's ID name
    attr_reader :ingredients      # Different Items used in fusion.
    attr_reader :quantity         # How Many of Each Item used, required.
    attr_reader :fusion_item      # New Item created with Alchemy.
    attr_reader :fusion_quant     # How Many of Each new Item is created.
    attr_reader :fp_cost          # Fusion Points required to Alchemize.
    #---------------------------------------------------------------------------
    def initialize
      @id = nil
      @ingredients = []
      @quantity = []
      @fusion_item = []
      @fusion_quant = []
      @fp_cost = 0
    end
    #--------------------
    # * Define Recipe ID
    #--------------------
    def @id
      if id <= -1
        id = 0
      end
    end
    #---------------------
    # * Define Ingredients
    #---------------------
    def ingredients
      @ingredients = []
    end
    #----------------------
    # * Define Quantity Req
    #----------------------
    def quantity
      @quantity = $data_items[i].quantity
    end
    #blah
  end
end
      
#===============================================================================
# * Scene_Alchemy
#===============================================================================
# Written by: Kain Nobel
# Version: 0.1
# Last Update: 5/6/2008
# Date Created: 5/6/2008
#===============================================================================
class Scene_Alchemy
  #[Attribute Accessors]--------------------------------------------------------
  attr_accessor :recipe           # ID of recipe on lista
  attr_accessor :description      # Description of recipe
  attr_accessor :ingredients      # Items to be used in recipe
  attr_accessor :quantities       # Number of each ingredient to be used
  attr_accessor :result           # Item made from alchemy
  attr_accessor :result_quant     # Quantity of item made
  attr_accessor :fp_cost          # How much it costs to fuse items
  #-----------------------------------------------------------------------------
  # * Initialization Method
  #------------------------
  def initialize#[recipe_index, alchemy_index]
    # Recipe and Alchemy index are set to default position
    @recipe_index = 0
    @alchemy_index = -1
    # Gets learned Game Party recipies
    @recipes = $game_party.recipes
    # Determines your Fusion Points
    @fp = $game_party.fusion_points
    # Access the 'main' method
    main
  end
  #--------------
  # * Main Method
  #--------------
  def main
    # Create Window_Recipe
    @window_recipe = Window_Recipe.new
    @window_recipe.x = 0
    # Create Window Alchemy
    @window_alchemy = Window_Alchemy.new
    @window_alchemy.x = 321
    # Execute transition
    Graphics.transition
    # Main loop
    loop do
      # Update game screen
      Graphics.update
      # Update input information
      Input.update
      # Frame update
      update
      # Abort loop if screen is changed
      if $scene != self
        break
      end
    end
    # Prepare for transition
    Graphics.freeze
    # Dispose of windows
    @window_recipe.dispose
    @window_alchemy.dispose
    update
  end
  #----------------
  # * Update Method
  #----------------
  def update
    # Update Window_Recipe
    if @window_recipe.active
      update_recipe
      return
    end
    # Update Window_Alchemy
    if @window_alchemy.active
      update_alchemy
      return
    end
  end
  #----------------
  # * Update Recipe
  #----------------
  def update_recipe
    # Selection: Activates Window_Alchemy
    if Input.press?(Input::C)
      $game_system.play_se($game_system.decision_se)
      @window_recipe.active = false
      @window_alchemy.active = true
      @window_alchemy.index = 0
    end
    # Cancel: Exits the menu
    if Input.press?(Input::B)
      $game_system.play_se($game_system.cancel_se)
      @window_recipe.active = false
      @window_recipe.index = 0
      @window_alchemy.active = false
      @window_alchemy.index = 0
      $scene = Scene_Map.new
    end
  end
  #-----------------
  # * Update Alchemy
  #-----------------
  def update_alchemy
    # Selection: Pick first item
    if Input.press?(Input::C) & @alchemy_index >= 0
      # If no items exist
      if $data_items.index = nil
        # Play Buzzer SE
        $game_system.se_play($game_system.buzzer_se)
      else # If items DO exist
        #Play Decision SE
        $game_system.se_play($game_system.decision_se)
        # If Fuse01 Item hasn't been selected
        if @fuse01 == nil
          @fuse01 = fusion01.item
        elsif @fuse02 == nil
          @fuse02 = fusion02.item
        else
          fuse_items
        end #fusion process
      end #detecting items
    end #picking item
  end #of method
  #-----------------
  # * Update Recipe
  #-----------------
  def update_recipe
    # Selection: Pick a recipe
    if Input.press?(Input::C) && @recipe_index >= 0
      # If no recipes exist
      if $game_party.learned_recipes == nil
        # Play Buzzer SE
        $game_system.se_play($game_system.buzzer_se)
      else
        @recipe_index = recipe_index
        @fusion01 = @recipe_index.fusion01
        @fusion02 = @recipe_index.fusion02
        if @recipe_index.fuse01 == @fusion01 && @recipe_index.fuse02 == @fusion02
          # Play Decision SE
          $game_system.se_play($game_system.decision_se)
          # Creates new item
          create_new_item
          return
        else
          # Play Buzzer SE
          $game_system.se_play($game_system.buzzer_se)
          # Print Text String
          fusion_invalid_string
          return
        end
      end
    end
  end
  #------------------
  # * Create New Item
  #------------------
  def create_new_item
    $game_party.lose_item[@fusion01, @quantity01]
    $game_party.lose_item[@fusion02, @quantity02]
    $game_party.gain_item[@fusion_item, @fusion_quant]
    $game_party.sp_change -= $recipe[i].fp_cost
  end
end
 
I'm slightly confused as to why you even have a class called Recipe when most of the properties of it are repeated in Scene_Alchemy anyway. Interestingly enough, although you define accessors called "ingredients", "quantities" and the like, they never appear to actually be used. I know this is an unfinished script, but even when finished your dual declaration is redundant.

I'd also avoid, for the sake of clarity, using names for different variables that are almost identical. It can cause readability issues later on when the script gets more bloated.

I haven't read through the whole thing, but it looks like a fairly solid basis for this kind of system. I'll be able to give you a better rundown once I've had a chance to properly analyse it.
 

khmp

Sponsor

Most important thing overall is that when you call a method that takes in one more arguments don't use square brackets either use parenthesis or nothing but a comma between arguments.

Code:
def method1(a, b) ; end
  
method1(5,3) # No problem with this one
method1 5, 3 # No problem with this one
method1[5,3] # Oh no we are trying to pass an array as argument, a will be [5, 3] b = error

In your class Recipe you have an initialize method beginning its definition and then bam. You define all the attributes and methods of this class including another initialize within the first initialize. Meaning you are doing something like this:
Code:
class Toast
  def initialize
    def initialize ; end
    def duck_food ; end
    def croutons ; end
  end
end

Your id method inside Recipe is kind of confusing. It's neither a set(assignment) or a get(retrieval). You create a local variable assign it to zero and do nothing with it. Seeing as you already have a defined method for retrieving @id via attr_reader I assume you want it to be a set. To do those:
Code:
def id=(id)
  @id = [id, 0].max
end

That also conveniently incorporates a test for a positive integer. If the id is negative the recipe is assigned 0 automatically. I believe you want to do something similar with ingredients and and quantity. With the current ingredients method you are just reseting the array. So if anything was in it it'll be empty after that method call.

Alright moving on to Scene_Alchemy. At the bottom of your initialize you have a call to main. The method main is automatically called after the Scene's initialization. Then at the bottom of your main you have an update call. I don't know why but I don't think its supposed to be there. Do you want the layout to be recipes on the left or right in a command window? Then on the opposite side another window containing the resultant and a description?

In the update_recipe method when you are switching scenes there's no reason to deactivate and reset the indexes of both windows because they will be disposed of in a little bit. I assume the purpose of this update is to determine which recipe?

Code:
# Cancel: Exits the menu
if Input.press?(Input::B)
  $game_system.play_se($game_system.cancel_se)
  $scene = Scene_Map.new
end

Moving onto update_alchemy method. Here it seems you want to pick the items involved? You can determine what recipe is involved again I can only assume here, by using @window_recipe.index. Thats making the assumption that your recipe window derives from Window_Command somewhere. To get the recipe of whatever recipe the user selected would be something like this:
Code:
recipe = $game_party.recipes[@window_recipe.index]

Any who your very first check is for an alchemy index greater than or equal to 0? Why the user shouldn't have the ability to have selected a negative indexed recipe yes? Or am I thinking about it wrong. Than you have a check to make sure the database items are not nil. I think what you want to check is if it is empty as well as nil. But I would be very surprised if there was ever a game with an empty item database. However you're thinking like a thorough programmer with that check so I won't knock it that much. Where this check should instead be is inside Main. Because you're not going to want to do anything with this scene if you haven't an items defined in your database. So the check in Scene_Alchemy.main would do this:
Code:
$scene = Scene_Map.new if $data_items.nil? || $data_items.empty?
What is "fusion01.item/fusion02.item"? I think you have a clever idea for picking items one at a time with the structure of that if statement but you have no way of backing out or deselecting an item.

update_recipe. Again you have a check for something not existing that if it doesn't render this scene useless. If the party knows no recipes why would I be able to get to this scene in the first place. It's not truly a problem more than an expectation. You save the recipe index and the items selected to instance variables? Do you use them in other methods? Could you not simply pass them as arguments to your create_new_item method? You also have no apparent check for item quantity validity. There's nothing there that says if you meet or fail the quantity check for a recipe to do something. The same for the items and the fp cost. I suggest a check as they select the recipe to buzzer them return if they fail the ingredient check. And if you want to take it a step further and if the recipe window is a command window. Disabling those recipes so the user has the impression that those recipes are unavailable.

Ok create_new_item. The square brackets replace with parenthesis. Recipe sub i? "i" is a local variable that isn't defined in that method. Remember if the recipe window is a command window you can use:
Code:
$game_party.fp -= $game_party.recipes[@window_recipe.index].fp_cost

There's actually a ton of things I missed but I think I covered the majority of the code you posted.

Good luck with your script Kain Nobel! :thumb:

Don't give up if you have any questions feel free to ask.
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top