TheoAllen

Theo - Crafting System (ENG)

Aug 22nd, 2013
586
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 19.54 KB | None | 0 0
  1. # =============================================================================
  2. # TheoAllen - (Fallout Like) Crafting System
  3. # Version : 1.1
  4. # Contact : www.rpgmakerid.com (or) http://theolized.blogspot.com
  5. # (English documentation)
  6. # =============================================================================
  7. ($imported ||= {})[:Theo_Crafting] = true
  8. # =============================================================================
  9. # CHANGE LOGS:
  10. # -----------------------------------------------------------------------------
  11. # 2013.08.25 - Bugfix disable req text isn't working
  12. # 2013.08.22 - Bugfix at amount of item crafting
  13. #            - Added show condition
  14. #            - Added custom name
  15. # 2013.08.20 - Finished script
  16. # 2013.08.19 - Started script
  17. # =============================================================================
  18. =begin
  19.  
  20.   ---------------------------------------------------------------------------
  21.   Introduction :
  22.   This script allow you to craft the item based on its recipes
  23.  
  24.   ---------------------------------------------------------------------------
  25.   How to use :
  26.   ---------------------------------------------------------------------------
  27.   Put this script below material but above main
  28.   To call crafting menu, write down this following line to your script call :
  29.  
  30.   enter_crafting
  31.  
  32.   ---------------------------------------------------------------------------
  33.   Notetags (For Items/Armors/Weapons):
  34.   ---------------------------------------------------------------------------
  35.   -----------------------------------
  36.   Level : Easy
  37.   -----------------------------------
  38.   <add item recipe: id,amount>
  39.   <add armor recipe: id,amount>
  40.   <add weapon recipe: id,amount>
  41.   ^
  42.   These notetags used to determine the recipes of the item/armor/weapon. Id is
  43.   the recipe id in database. Amount is the minimum item number in player
  44.   inventory
  45.  
  46.   <craft name: text>
  47.   ^
  48.   This notetag is to change item name temporary. For example, in your crafting
  49.   list, potion will be drawn in "Craft potions". But, after you got the potion,
  50.   the name back to original.
  51.  
  52.   -----------------------------------
  53.   Level : Medium - Hard
  54.   (Do not try to use if you don't know)
  55.   -----------------------------------
  56.   <craft require>
  57.   script
  58.   </craft require>
  59.   ^
  60.   These notetags are to determine if the item is can be crafted or not. It's
  61.   determined by script. If you're using many lines, it will count as a part of
  62.   one line. I wrote the scripts call instruction elsewhere. Too bad, it is in
  63.   Indonesian
  64.  
  65.   The writing error may causes the game to crash. So. it's better to ask me
  66.   first or make a RGSSx support thread in RPG Maker Forum. They may help you (if
  67.   you're lucky)
  68.  
  69.   <craft req text>
  70.   some text here
  71.   </craft req text>
  72.   ^
  73.   These notetags is for representation of script call above. For example, to
  74.   make a certain item is require at least a silver hammer. You could write it
  75.   like this
  76.  
  77.   <craft req text>
  78.   This items need a silver hammer
  79.   </craft req text>
  80.  
  81.   <craft show eval>
  82.   script
  83.   </craft show eval>
  84.   ^
  85.   These notetags is to determine item whether is shown in the list or not. For
  86.   example, to craft an elixir, you need to learn high level alchemy. So, it
  87.   won't show until you (the player) learn a certain skill
  88.  
  89.   The writing error may causes the game to crash. So. it's better to ask me
  90.   first or make a RGSSx support thread in RPG Maker Forum. They may help you (if
  91.   you're lucky)
  92.  
  93.   ---------------------------------------------------------------------------
  94.   Terms of Use :
  95.   ---------------------------------------------------------------------------
  96.   Credit me, TheoAllen. You are free to edit this script by your own. As long
  97.   as you don't claim it yours. For commercial purpose, don't forget to give me
  98.   a free copy of the game.
  99.  
  100. =end
  101. # =============================================================================
  102. # Configurations :
  103. # =============================================================================
  104. module THEO
  105.   module Craft
  106.  
  107.   # --------------------------------------------------------------------------
  108.   # General Settings (true/false)
  109.   # --------------------------------------------------------------------------
  110.     MainMenu        = true
  111.   # Set true if the crafting menu can be accessed in main menu
  112.  
  113.     DisplayReqText  = true
  114.   # For you who do not need the requirement text. You could disable it here
  115.  
  116.   # --------------------------------------------------------------------------
  117.   # Vocab Settings (Text/String)
  118.   # --------------------------------------------------------------------------
  119.     VocabMenu      = "Craft"          # Main Menu crafting command
  120.     VocabNoReq     = "- None -"       # If there's no special requirement
  121.     VocabRequire   = "Requirement :"  # Requirement Vocab
  122.     VocabRecipes   = "Recipes : "     # Recipe Vocab
  123.     VocabInventory = "Inventory: "    # Vokab for inventory
  124.    
  125.   # --------------------------------------------------------------------------
  126.   # Miscs (Numeric / 0123456789)
  127.   # --------------------------------------------------------------------------
  128.     Text_Buffer_x = 12
  129.   # Additional text distance from left side
  130.  
  131.     AmountSize = 250
  132.   # Width of amount window
  133.  
  134.   end
  135. end
  136. # =============================================================================
  137. # End of config. Do not try to touch my private material pass this line
  138. # =============================================================================
  139. module THEO
  140.   module Craft
  141.     def self.items
  142.       items = $data_items + $data_armors + $data_weapons
  143.       items.compact!
  144.       items.select {|item| item.can_be_crafted? }
  145.     end
  146.   end
  147. end
  148.  
  149. class RPG::BaseItem
  150.   attr_accessor :item_recipes
  151.   attr_accessor :armor_recipes
  152.   attr_accessor :weapon_recipes
  153.   attr_accessor :enable_cond
  154.   attr_accessor :enable_text
  155.   attr_accessor :show_cond
  156.   attr_accessor :craft_name
  157.   attr_accessor :craft_key  # For future planned feature
  158.  
  159.   def load_recipes
  160.     @item_recipes = {}
  161.     @armor_recipes = {}
  162.     @weapon_recipes = {}
  163.     @show_cond = @enable_cond = "true"
  164.     @enable_text = []
  165.     @craft_name = ""
  166.     @craft_key = ""
  167.     read_craft_cond = read_craft_txt = read_craft_show = false
  168.     self.note.split(/[\r\n]+/).each do |line|
  169.       case line
  170.       when /<(?:ADD_ITEM_RECIPE|add item recipe): (.*)>/i
  171.         str = $1.scan(/\d+/)
  172.         @item_recipes[str[0].to_i] = str[1].to_i
  173.       when /<(?:ADD_ARMOR_RECIPE|add armor recipe): (.*)>/i
  174.         str = $1.scan(/\d+/)
  175.         @armor_recipes[str[0].to_i] = str[1].to_i
  176.       when /<(?:ADD_WEAPON_RECIPE|add WEAPON recipe): (.*)>/i
  177.         str = $1.scan(/\d+/)
  178.         @weapon_recipes[str[0].to_i] = str[1].to_i
  179.       when /<(?:CRAFT_REQUIRE|craft require)>/i
  180.         read_craft_cond = true
  181.         @enable_cond = ""
  182.       when /<\/(?:CRAFT_REQUIRE|craft require)>/i
  183.         read_craft_cond = false
  184.       when /<(?:CRAFT_REQ_TEXT|craft req text)>/i
  185.         read_craft_txt = true
  186.       when /<\/(?:CRAFT_REQ_TEXT|craft req text)>/i
  187.         read_craft_txt = false
  188.       when /<(?:CRAFT_SHOW_EVAL|craft show eval)>/i
  189.         read_craft_show = true
  190.         @show_cond = ""
  191.       when /<\/(?:CRAFT_SHOW_EVAL|craft show eval)>/i
  192.         read_craft_show = false
  193.       when /<(?:CRAFT_NAME|craft name): (.*)>/i
  194.         @craft_name = $1.to_s
  195.       when /<(?:CRAFT_KEY|craft key): [ ]*(.*)>/i
  196.         @craft_key = $1.to_s
  197.       else
  198.         if read_craft_cond
  199.           @enable_cond += line
  200.         end
  201.         if read_craft_txt
  202.           @enable_text.push(line)
  203.         end
  204.         if read_craft_show
  205.           @show_cond += line
  206.         end
  207.       end
  208.     end
  209.   end
  210.  
  211.   def recipes
  212.     [@item_recipes, @armor_recipes, @weapon_recipes]
  213.   end
  214.  
  215.   # ---------------------------------------------------------------------------
  216.   # If the error is directed you to this line. It's possible that you wrote
  217.   # craft requirement formula in a wrong way. Not this script mistake
  218.   # ---------------------------------------------------------------------------
  219.   def craft_possible?
  220.     return eval(@enable_cond) && can_be_crafted?
  221.   end
  222.  
  223.   def show_possible?
  224.     return eval(@show_cond)
  225.   end
  226.   # ---------------------------------------------------------------------------
  227.   # Determine if item can be crafted
  228.   # ---------------------------------------------------------------------------
  229.   def can_be_crafted?
  230.     recipes.any? {|recipe| !recipe.empty?} && show_possible?
  231.   end
  232.  
  233. end
  234.  
  235. class << DataManager
  236.  
  237.   alias theo_recipe_craft_load_db load_database
  238.   def load_database
  239.     theo_recipe_craft_load_db
  240.     load_item_recipes
  241.   end
  242.  
  243.   def load_item_recipes
  244.     ($data_items+$data_armors+$data_weapons).compact.each do |db|
  245.       db.load_recipes
  246.     end
  247.   end
  248.  
  249. end
  250.  
  251. class Window_CraftList < Window_ItemList
  252.  
  253.   def initialize(x,y,w,h,key)
  254.     @key = key
  255.     super(x,y,w,h)
  256.     refresh
  257.   end
  258.  
  259.   def col_max
  260.     return 1
  261.   end
  262.  
  263.   def status_window=(window)
  264.     @status_window = window
  265.     update_help
  266.   end
  267.  
  268.   def item_number_window=(window)
  269.     @inum_window = window
  270.     update_help
  271.   end
  272.  
  273.   def update_help
  274.     super
  275.     @status_window.set_item(item) if @status_window
  276.     @inum_window.set_item(item) if @inum_window
  277.   end
  278.  
  279.   def make_item_list
  280.     @data = []
  281.     items = THEO::Craft.items
  282.     items.each do |item|
  283.       @data.push(item) if @key.empty? || item.craft_key == @key
  284.     end
  285.   end
  286.  
  287.   def enable?(item)
  288.     item.craft_possible? && has_recipes?(item) && has_free_slot?(item)
  289.   end
  290.  
  291.   def has_free_slot?(item)
  292.     $game_party.item_number(item) < $game_party.max_item_number(item)
  293.   end
  294.  
  295.   def has_recipes?(item)
  296.     result1 = check_recipe(item.recipes[0], $data_items)
  297.     result2 = check_recipe(item.recipes[1], $data_armors)
  298.     result3 = check_recipe(item.recipes[2], $data_weapons)
  299.     return result1 && result2 && result3
  300.   end
  301.  
  302.   def check_recipe(recipes, data)
  303.     return true if recipes.empty?
  304.     return recipes.all? {|recipe|
  305.       $game_party.item_number(data[recipe[0]]) >= recipe[1]}
  306.   end
  307.  
  308.   def draw_item_name(item, x, y, enabled = true, width = 172)
  309.     return unless item
  310.     draw_icon(item.icon_index, x, y, enabled)
  311.     change_color(normal_color, enabled)
  312.     name = item.craft_name.empty? ? item.name : item.craft_name
  313.     draw_text(x + 24, y, width, line_height, name)
  314.   end
  315.  
  316.   def draw_item_number(rect, item)
  317.     return unless $imported[:Theo_LimInventory]
  318.     return unless THEO::LimInv::Display_ItemSize
  319.     draw_text(rect, sprintf(":%2d", item.inv_size), 2)
  320.   end
  321.  
  322. end
  323.  
  324. class Window_CraftStatus < Window_Base
  325.  
  326.   def set_item(item)
  327.     @item = item
  328.     refresh
  329.   end
  330.  
  331.   def refresh
  332.     contents.clear
  333.     return unless @item
  334.     @line_count = 0
  335.     draw_requirement
  336.     draw_recipes
  337.   end
  338.  
  339.   def draw_requirement
  340.     return unless THEO::Craft::DisplayReqText
  341.     change_color(system_color)
  342.     draw_text(line_rect(4),THEO::Craft::VocabRequire)
  343.     increase_line_count
  344.     if !@item.enable_text.empty?
  345.       change_color(normal_color, @item.craft_possible?)
  346.       @item.enable_text.each do |text|
  347.         draw_text(line_rect(buff_x),text)
  348.         increase_line_count
  349.       end
  350.       increase_line_count
  351.     else
  352.       change_color(normal_color)
  353.       draw_text(line_rect(buff_x),THEO::Craft::VocabNoReq)
  354.       2.times { increase_line_count }
  355.     end
  356.   end
  357.  
  358.   def draw_recipes
  359.     change_color(system_color)
  360.     draw_text(line_rect(4),THEO::Craft::VocabRecipes)
  361.     change_color(normal_color)
  362.     increase_line_count
  363.     draw_recipe(@item.recipes[0], $data_items)
  364.     draw_recipe(@item.recipes[1], $data_armors)
  365.     draw_recipe(@item.recipes[2], $data_weapons)
  366.   end
  367.  
  368.   def draw_recipe(hash, items)
  369.     hash.each do |id,amount|
  370.       item_num = $game_party.item_number(items[id])
  371.       enable = item_num >= amount
  372.       change_color(normal_color, enable)
  373.       rect = line_rect(buff_x + 24)
  374.       text = sprintf("%s (%d/%d)",items[id].name, item_num, amount)
  375.       draw_text(rect, text)
  376.       draw_icon(items[id].icon_index, buff_x, @line_count, enable)
  377.       increase_line_count
  378.     end
  379.   end  
  380.  
  381.   def line_rect(xpos = 0)
  382.     Rect.new(xpos,@line_count,contents.width-xpos,line_height)
  383.   end
  384.  
  385.   def increase_line_count
  386.     @line_count += line_height
  387.   end
  388.  
  389.   def buff_x
  390.     THEO::Craft::Text_Buffer_x
  391.   end
  392.  
  393. end
  394.  
  395. class Window_CraftAmount < Window_Base
  396.   attr_accessor :inv_window
  397.   attr_accessor :ok_handler
  398.   attr_accessor :cancel_handler
  399.   attr_reader :amount
  400.  
  401.   def initialize
  402.     super(0,0,window_width,fitting_height(1))
  403.     self.openness = 0
  404.     to_center
  405.     @amount = 0
  406.     @max = 0
  407.     @item = nil
  408.   end
  409.  
  410.   def window_width
  411.     return THEO::Craft::AmountSize
  412.   end
  413.  
  414.   def to_center
  415.     self.x = (Graphics.width - width)/2
  416.     self.y = (Graphics.height - height)/2
  417.   end
  418.  
  419.   def set(item, max)
  420.     change_amount(0,true)
  421.     @item = item
  422.     @max = max
  423.     open
  424.     refresh
  425.   end
  426.  
  427.   def refresh
  428.     contents.clear
  429.     return unless @item
  430.     draw_item_name(@item,0,0,true,contents.width)
  431.     draw_amount
  432.   end
  433.  
  434.   def draw_amount
  435.     text = sprintf("%d/%d",@amount,@max)
  436.     draw_text(0,0,contents.width,line_height,text,2)
  437.   end
  438.  
  439.   def update
  440.     super
  441.     if open?
  442.       change_amount(1) if Input.repeat?(:RIGHT)
  443.       change_amount(-1) if Input.repeat?(:LEFT)
  444.       change_amount(10) if Input.repeat?(:UP)
  445.       change_amount(-10) if Input.repeat?(:DOWN)
  446.       call_ok if Input.trigger?(:C)
  447.       call_cancel if Input.trigger?(:B)
  448.     end
  449.   end
  450.  
  451.   def change_amount(number, instant = false)
  452.     if instant
  453.       @amount = number
  454.     else
  455.       Sound.play_cursor
  456.       @amount = [[@amount + number,0].max,@max].min
  457.     end
  458.     refresh
  459.     @inv_window.amount = @amount if @inv_window
  460.   end
  461.  
  462.   def call_ok
  463.     Sound.play_ok
  464.     ok_handler.call
  465.     change_amount(0,true)
  466.     close
  467.   end
  468.  
  469.   def call_cancel
  470.     Sound.play_cancel
  471.     cancel_handler.call
  472.     change_amount(0,true)
  473.     close
  474.   end
  475.  
  476. end
  477.  
  478. class Window_CraftFooter < Window_Base
  479.  
  480.   def initialize
  481.     super(0,0,Graphics.width,fitting_height(1))
  482.     self.y = Graphics.height - height
  483.     @amount = 0
  484.     @item = nil
  485.     refresh
  486.   end
  487.  
  488.   def amount=(amount)
  489.     @amount = amount
  490.     refresh
  491.   end
  492.  
  493.   def refresh
  494.     contents.clear
  495.     change_color(system_color)
  496.     draw_text(0,0,contents.width,line_height,THEO::Craft::VocabInventory)
  497.     change_color(normal_color)
  498.     return unless @item
  499.     if $imported[:Theo_LimInventory]
  500.       draw_inv_slot(0,0)
  501.     else
  502.       draw_item_number
  503.     end
  504.   end
  505.  
  506.   def draw_inv_slot(x,y,width = contents.width,align = 2)
  507.     total = $game_party.total_inv_size + @amount*@item.inv_size
  508.     total -= calculate_lose_item
  509.     txt = sprintf("%d/%d", total, $game_party.inv_max)
  510.     color = THEO::LimInv::NearMaxed_Color
  511.     near_max = total.to_f/$game_party.inv_max >=
  512.       (100 - THEO::LimInv::NearMaxed_Percent).to_f / 100
  513.     if near_max
  514.       change_color(text_color(color))
  515.     else
  516.       change_color(normal_color)
  517.     end
  518.     draw_text(x,y,width,line_height,txt,align)
  519.     change_color(normal_color)
  520.   end
  521.  
  522.   def draw_item_number
  523.     txt = sprintf("%d/%d",@amount + $game_party.item_number(@item),
  524.       $game_party.max_item_number(@item))
  525.     draw_text(0,0,contents.width,line_height,txt,2)
  526.   end
  527.  
  528.   def set_item(item)
  529.     @item = item
  530.     refresh
  531.   end
  532.  
  533.   def calculate_lose_item
  534.     result = 0
  535.     @item.recipes[0].each do |id,amount|
  536.       data = $data_items[id]
  537.       amount *= @amount
  538.       result += amount
  539.     end
  540.     @item.recipes[1].each do |id,amount|
  541.       data = $data_armors[id]
  542.       amount *= @amount
  543.       result += amount
  544.     end
  545.     @item.recipes[2].each do |id,amount|
  546.       data = $data_weapons[id]
  547.       amount *= @amount
  548.       result += amount
  549.     end
  550.     return result
  551.   end
  552.  
  553. end
  554.  
  555. class Game_Interpreter
  556.  
  557.   # ----------------------------------------------
  558.   # key is just for my future planned feature
  559.   # ----------------------------------------------
  560.   def enter_crafting(key = "")
  561.     SceneManager.call(Scene_ItemCrafting)
  562.     SceneManager.scene.prepare(key)
  563.     Fiber.yield
  564.   end
  565.  
  566. end
  567.  
  568. class Window_MenuCommand < Window_Command
  569.  
  570.   alias theo_craft_ori_cmd add_original_commands
  571.   def add_original_commands
  572.     theo_craft_ori_cmd
  573.     return unless THEO::Craft::MainMenu
  574.     add_command(THEO::Craft::VocabMenu, :craft)
  575.   end
  576.  
  577. end
  578.  
  579. class Scene_Menu < Scene_MenuBase
  580.  
  581.   alias theo_craft_cmnd_window create_command_window
  582.   def create_command_window
  583.     theo_craft_cmnd_window
  584.     @command_window.set_handler(:craft, method(:enter_crafting))
  585.   end
  586.  
  587.   def enter_crafting
  588.     SceneManager.call(Scene_ItemCrafting)
  589.     SceneManager.scene.prepare("")
  590.   end
  591.  
  592. end
  593.  
  594. class Scene_ItemCrafting < Scene_MenuBase
  595.  
  596.   def prepare(key)
  597.     @key = key
  598.   end
  599.  
  600.   def start
  601.     super
  602.     create_help_window
  603.     create_craftfooter_window
  604.     create_craftlist_window
  605.     create_craftstatus_window
  606.     create_craftamount_window
  607.   end
  608.  
  609.   def create_craftfooter_window
  610.     @craft_footer = Window_CraftFooter.new
  611.   end
  612.  
  613.   def create_craftlist_window
  614.     wy = @help_window.height
  615.     ww = Graphics.width/2
  616.     wh = Graphics.height - wy - @craft_footer.height
  617.     @craft_list = Window_CraftList.new(0,wy,ww,wh,@key)
  618.     @craft_list.set_handler(:ok, method(:on_craft_ok))
  619.     @craft_list.set_handler(:cancel, method(:return_scene))
  620.     @craft_list.help_window = @help_window
  621.     @craft_list.item_number_window = @craft_footer
  622.     @craft_list.activate
  623.     @craft_list.select(0)
  624.   end
  625.  
  626.   def create_craftstatus_window
  627.     wx = @craft_list.width
  628.     wy = @craft_list.y
  629.     ww = @craft_list.width
  630.     wh = @craft_list.height
  631.     @craft_status = Window_CraftStatus.new(wx,wy,ww,wh)
  632.     @craft_list.status_window = @craft_status
  633.   end
  634.  
  635.   def create_craftamount_window
  636.     @craft_amount = Window_CraftAmount.new
  637.     @craft_amount.ok_handler = method(:on_amount_ok)
  638.     @craft_amount.cancel_handler = method(:on_amount_cancel)
  639.     @craft_amount.inv_window = @craft_footer
  640.   end
  641.  
  642.   def on_craft_ok
  643.     @craft_amount.set(item, item_max)
  644.   end
  645.  
  646.   def on_amount_ok
  647.     $game_party.gain_item(item, @craft_amount.amount)
  648.     lose_recipes
  649.     @craft_status.refresh
  650.     @craft_list.refresh
  651.     @craft_list.activate
  652.   end
  653.  
  654.   def on_amount_cancel
  655.     @craft_list.activate
  656.   end
  657.  
  658.   def item
  659.     @craft_list.item
  660.   end
  661.  
  662.   def item_max
  663.     ary = []
  664.     item.recipes[0].each do |id,amount|
  665.       data = $data_items[id]
  666.       ary.push($game_party.item_number(data)/amount)
  667.     end
  668.     item.recipes[1].each do |id,amount|
  669.       data = $data_armors[id]
  670.       ary.push($game_party.item_number(data)/amount)
  671.     end
  672.     item.recipes[2].each do |id,amount|
  673.       data = $data_weapons[id]
  674.       ary.push($game_party.item_number(data)/amount)
  675.     end
  676.     max_item = $game_party.max_item_number(item)
  677.     inum = $game_party.item_number(item)
  678.     return [ary.min , max_item - inum].min
  679.   end
  680.  
  681.   def lose_recipes
  682.     item.recipes[0].each do |id,amount|
  683.       data = $data_items[id]
  684.       amount *= @craft_amount.amount
  685.       $game_party.lose_item(data,amount)
  686.     end
  687.     item.recipes[1].each do |id,amount|
  688.       data = $data_armors[id]
  689.       amount *= @craft_amount.amount
  690.       $game_party.lose_item(data,amount)
  691.     end
  692.     item.recipes[2].each do |id,amount|
  693.       data = $data_weapons[id]
  694.       amount *= @craft_amount.amount
  695.       $game_party.lose_item(data,amount)
  696.     end
  697.   end
  698.  
  699. end
Advertisement
Add Comment
Please, Sign In to add comment