Mundo Maker
¡Bienvenid@ a Mundo Maker!

¿Quieres aprender todo sobre el RPG Maker?



Regístrate y forma parte de Mundo Maker.

[XP] Chest System

Ver el tema anterior Ver el tema siguiente Ir abajo

RPG Maker XP [XP] Chest System

Mensaje por Wecoc el 2017-11-20, 17:51

Chest System

Chest System es un sistema de cofres con obtención de items y dinero random.

Defines los tipos de cofre por ID. Cada uno tiene:

  • Lista de objetos disponible (items, weapons y armors) indicando cantidad
  • Número de objetos que se obtendrán de esa lista (con mínimo y máximo)
  • Oro (con mínimo y máximo)

Para usarlo hay que usar esta llamada de script:
call_chest(CHEST_ID)

Muestra:
El cofre en sí va como siempre, esa llamada irá donde normalmente se pondrían los items y dinero a obtener.



Saldrá una ventana directamente indicando lo que se ha obtenido.


La configuración de cada ID de cofre se hace al principio del script, tal como se indica en las instrucciones del mismo.
Veréis que no es demasiado complicado, además hay uno de ejemplo.
Óbviamente se pueden poner varios cofres en el juego con la misma ID si se quiere que tengan los mismos posibles objetos y dinero.

Script:
Código:
#==============================================================================
# ** [XP] Chest System v1.0
#------------------------------------------------------------------------------
# Autor: Wecoc (no requiere créditos)
#------------------------------------------------------------------------------
# Sistema de cofres con obtención de items y dinero random.
# Defines los tipos de cofre por ID. Cada uno tiene:
#   - Lista de objetos disponible (items, weapons y armors) indicando cantidad
#   - Número de objetos que se obtendrán de esa lista (con mínimo y máximo)
#   - Oro (con mínimo y máximo)
#
# Para usarlo hay que usar esta llamada de script:
#     call_chest(CHEST_ID)
#
# Los cambios de los cofres son guardados así que si se usa este script es
# probable que las partidas guardadas anteriormente ya no funcionen bien.
#------------------------------------------------------------------------------
# Configuración:
# Se hace en set_chest_data para cada ID de cofre, como indica el ejemplo.
#
# * Definir cierto item en cofre
#     chest_goods[[TYPE, ID]] = NUMBER
#         TYPE - 0: Item, 1: Weapon, 2: Armor
#         ID - Su id en la base de datos
#         NUMBER - Número máximo de ese item que se puede llegar a obtener
#
# * Definir el oro del cofre
#     set_gold(GOLD)
# * Definir oro mínimo y máximo del cofre
#     set_gold(MIN, MAX)
#
# * Definir el número de objetos que se obtendrán del cofre
#     set_number(NUMBER)
# * Definir el mínimo y máximo de objetos que se obtendrán del cofre
#     set_number(MIN, MAX)
#==============================================================================

module Chest_System
  # Sonido al encontrar objetos
  ITEM_FOUND_SE     = RPG::AudioFile.new("056-Right02", 100, 100)
  # Sonido al no encontrar objetos
  ITEM_NOT_FOUND_SE = RPG::AudioFile.new("057-Wrong01", 100, 100)
end

#==============================================================================
# ** Scene_Title
#==============================================================================

class Scene_Title
  def set_chest_data
    $game_chests = [nil]
    #--------------------------------------------------------------------------
    # Aquí se definen todas las tiendas tal como se hace con la de ejemplo:
    #--------------------------------------------------------------------------
    
    $game_chests[1] = RPG::Chest.new(1) # Tienda de ID 1
    $game_chests[1].chest_goods[[0, 1]] = 2   # Item de id 1 - cantidad 5
    $game_chests[1].chest_goods[[0, 2]] = 1   # Item de id 2 - cantidad 1
    $game_chests[1].chest_goods[[1, 1]] = 2   # Arma de id 1 - cantidad 2
    $game_chests[1].chest_goods[[2, 1]] = 1   # Protector de id 1 - cantidad 1
    $game_chests[1].set_gold(100)             # Obtener dinero: 100
    $game_chests[1].set_number(4)             # Objetos a obtener: 4
    
    #--------------------------------------------------------------------------
    for i in 1...$game_chests.size
      chest = $game_chests[i]
      chest.set_current_as_default
    end
  end
  
  alias ext_chest_update update
  def update
    set_chest_data if $game_chests.nil?
    ext_chest_update
  end
end

#==============================================================================
# ** Scene_Save
#==============================================================================

class Scene_Save < Scene_File
  alias ext_chest_write_data write_save_data
  def write_save_data(file)
    ext_chest_write_data(file)
    Marshal.dump($game_chests, file)
  end
end

#==============================================================================
# ** Scene_Load
#==============================================================================

class Scene_Load < Scene_File
  alias ext_chest_read_data read_save_data
  def read_save_data(file)
    ext_chest_read_data(file)
    $game_chests = Marshal.load(file)
  end
end

#==============================================================================
# ** RPG::Chest
#==============================================================================

module RPG
  class Chest
    #------------------------------------------------------------------------
    attr_accessor :chest_id         # ID del cofre
    attr_accessor :chest_goods      # Hash de items que se pueden comprar
    attr_accessor :min_gold         # Dinero mínimo
    attr_accessor :max_gold         # Dinero máximo
    attr_accessor :min_number       # Número de objetos mínimo
    attr_accessor :max_number       # Número de objetos máximo
    #------------------------------------------------------------------------
    # * Initialize
    #------------------------------------------------------------------------
    def initialize(chest_id)
      @chest_id = chest_id
      @chest_goods = {}
      @chest_goods.default = 0
      @min_gold = 0
      @max_gold = 0
      @min_number = 0
      @max_number = 0
    end
    #------------------------------------------------------------------------
    # * Obtener ID del cofre
    #------------------------------------------------------------------------
    def id
      @chest_id
    end
    #------------------------------------------------------------------------
    # * Definir dinero en el cofre
    #------------------------------------------------------------------------
    def set_gold(min, max=min)
      @min_gold = min
      @max_gold = [max, min].max
    end
    #------------------------------------------------------------------------
    # * Definir número de objetos en el cofre
    #------------------------------------------------------------------------
    def set_number(min, max=min)
      @min_number = [1, min].max
      @max_number = [max, min].max
    end
    #------------------------------------------------------------------------
    # * Definir un cofre como modo Dios (todos los items disponibles)
    #------------------------------------------------------------------------
    def set_god_chest
      for i in 1...$data_items.size
        @chest_goods[[0, i]] = 1
      end
      for i in 1...$data_weapons.size
        @chest_goods[[1, i]] = 1
      end
      for i in 1...$data_armors.size
        @chest_goods[[2, i]] = 1
      end
      @min_number = @chest_goods.keys.size
      @max_number = @min_number
    end
    #------------------------------------------------------------------------
    attr_accessor :default_chest_goods
    attr_accessor :default_min_gold, :default_max_gold
    attr_accessor :default_min_number, :default_max_number
    #------------------------------------------------------------------------
    # * Definir valores por defecto
    #------------------------------------------------------------------------
    def set_current_as_default
      @default_chest_goods = @chest_goods.clone
      @default_min_gold = @min_gold
      @default_max_gold = @max_gold
      @default_min_number = @min_number
      @default_max_number = @max_number
    end
    #------------------------------------------------------------------------
    # * Volver a los valores por defecto
    #------------------------------------------------------------------------
    def reset_default
      for i in @default_chest_goods.keys
        @chest_goods[i] = @default_chest_goods[i]
      end
      @min_gold = @default_min_gold
      @max_gold = @default_max_gold
      @min_number = @default_min_number
      @max_number = @default_max_number
    end
  end
end

#==============================================================================
# ** Window_ExtChestItems
#==============================================================================

class Window_ExtChestItems < Window_Base
  #--------------------------------------------------------------------------
  # * Initialize
  #--------------------------------------------------------------------------
  def initialize(items)
    super(160, 64, 320, 64)
    @items = {}
    for i in 0...items.size
      item = items[i]
      if @items.keys.include?(item)
        @items[item] = @items[item] + 1
      else
        @items[item] = 1
      end
    end
    self.visible = false if @items.keys.size == 0
    self.height = [@items.keys.size, 1].max * 32 + 32
    self.contents = Bitmap.new(self.width - 32, self.height - 32)
    self.back_opacity = 160
    refresh
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear
    for i in 0...@items.keys.size
      draw_item(i)
    end
  end
  #--------------------------------------------------------------------------
  # * Draw Item
  #--------------------------------------------------------------------------
  def draw_item(index)
    i = @items.keys.sort[index]
    x = 4
    y = index * 32
    case i[0]
    when 0 # Objeto
      item = $data_items[i[1]]
    when 1 # Arma
      item = $data_weapons[i[1]]
    when 2 # Protector
      item = $data_armors[i[1]]
    end
    number = @items[i]
    bitmap = RPG::Cache.icon(item.icon_name)
    self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24))
    self.contents.draw_text(x + 28, y, 212, 32, item.name, 0)
    self.contents.draw_text(x + 240, y, 16, 32, ":", 1)
    self.contents.draw_text(x + 256, y, 24, 32, number.to_s, 2)
  end
end

#==============================================================================
# ** Window_ExtChestGold
#==============================================================================

class Window_ExtChestGold < Window_Base
  #--------------------------------------------------------------------------
  # * Initialize
  #--------------------------------------------------------------------------
  def initialize(gold)
    super(160, 64, 320, 64)
    @gold = gold
    self.visible = false if @gold == 0
    self.contents = Bitmap.new(self.width - 32, self.height - 32)
    self.back_opacity = 160
    refresh
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear
    cx = contents.text_size($data_system.words.gold).width
    dx = self.width - 36 - cx
    self.contents.font.color = normal_color
    self.contents.draw_text(4, 0, dx - 6, 32, @gold.to_s, 2)
    self.contents.font.color = system_color
    self.contents.draw_text(dx, 0, cx, 32, $data_system.words.gold, 2)
  end
end

#==============================================================================
# ** Scene_ExtChest
#==============================================================================

class Scene_ExtChest
  #--------------------------------------------------------------------------
  # * Initialize
  #--------------------------------------------------------------------------
  def initialize(chest_id)
    @chest_id = chest_id
    @items = []
    @number = 0
    @gold = 0
  end
  #--------------------------------------------------------------------------
  # * Main
  #--------------------------------------------------------------------------
  def main
    # Obtener el contenido del cofre
    get_chest_number
    get_chest_items
    get_chest_gold
    # Añadir contenido al inventario
    add_contents
    # Reproducir sonido según si hay contenido o no
    if @number == 0 && @gold == 0
      $game_system.se_play(Chest_System::ITEM_NOT_FOUND_SE)
    else
      $game_system.se_play(Chest_System::ITEM_FOUND_SE)
    end
    # Crear ventanas
    @item_window = Window_ExtChestItems.new(@items)
    @gold_window = Window_ExtChestGold.new(@gold)
    height = (@item_window.visible ? @item_window.height : 0)
    @gold_window.y = @item_window.y + height
    # Crear mapa en el fondo
    @spriteset = Spriteset_Map.new
    Graphics.transition
    loop do
      Graphics.update
      Input.update
      update
      if $scene != self
        break
      end
    end
    Graphics.freeze
    @item_window.dispose
    @gold_window.dispose
    @spriteset.dispose
  end
  #--------------------------------------------------------------------------
  # * Get Chest Number
  #--------------------------------------------------------------------------
  def get_chest_number
    chest = $game_chests[@chest_id]
    return if chest.chest_goods.keys.size == 0
    @number = chest.min_number
    r = chest.max_number - @number
    @number += rand(r) if r > 0
  end
  #--------------------------------------------------------------------------
  # * Get Chest Items
  #--------------------------------------------------------------------------
  def get_chest_items
    chest = $game_chests[@chest_id]
    return if @number == 0
    array = []
    for k in chest.chest_goods.keys
      chest.chest_goods[k].times { array.push(k) }
    end
    @number.times do
      break if array.size == 0
      index = rand(array.size)
      item = array[index]
      array.delete_at(index)
      @items.push(item)
    end
  end
  #--------------------------------------------------------------------------
  # * Get Chest Gold
  #--------------------------------------------------------------------------
  def get_chest_gold
    chest = $game_chests[@chest_id]
    @gold = chest.min_gold
    r = chest.max_gold - @gold
    @gold += rand(r) if r > 0
  end
  #--------------------------------------------------------------------------
  # * Add all contents to the party
  #--------------------------------------------------------------------------
  def add_contents
    for i in @items
      case i[0]
      when 0 # Objeto
        $game_party.gain_item(i[1], 1)
      when 1 # Arma
        $game_party.gain_weapon(i[1], 1)
      when 2 # Protector
        $game_party.gain_armor(i[1], 1)
      end
    end
    $game_party.gain_gold(@gold)
  end
  #--------------------------------------------------------------------------
  # * Update
  #--------------------------------------------------------------------------
  def update
    @item_window.update
    @gold_window.update
    # Volver directamente si no hay contenido
    if @number == 0 && @gold == 0
      $scene = Scene_Map.new
      return
    end
    # Esperar a pulsar Aceptar si hay contenido
    if Input.trigger?(Input::C)
      $game_system.se_play($data_system.decision_se)
      $scene = Scene_Map.new
      return
    end
  end
end

#==============================================================================
# ** Interpreter
#==============================================================================

class Interpreter
  def call_chest(chest_id)
    $scene = Scene_ExtChest.new(chest_id)
  end
end

Chest Rarity Addon

Este script es un añadido al anterior. Requiere tanto el Chest System como el Data File Save.

Lo que hace es añadir un nuevo parámetro llamado rarity en objetos, armas y protectores. Ese parámetro indica lo difícil que es obtenerlos de un cofre, de 0 a 100 (por defecto vale 50). Se define al principio del script.

No solo eso sino que el script añade la posibilidad de darle mejor uso al parámetro INT (a veces llamado parámetro Suerte)
Según la suerte de la party dependiendo de ese parámetro de cada actor (alterado por items, skills, estados o equipo si se quiere) se puede hacer que:
- Sea más o menos fácil obtener items raros
- Se obtenga más o menos oro (dentro del mínimo y máximo definidos para el cofre)
- Se obtenga más o menos cantidad de items (dentro del mínimo y máximo definidos para el cofre)

Spoiler:
Código:
#==============================================================================
# ** [XP] Chest Rarity Addon v1.0
#------------------------------------------------------------------------------
# Autor: Wecoc (no requiere créditos)
#------------------------------------------------------------------------------
# Requiere:
# - Chest System
# - Data File Save
#------------------------------------------------------------------------------
# Addons:
# - Cada item, weapon y armor tiene una variable :rarity que indica la rareza
#  (dificultad para encontrarlo en un cofre), de 0 a 100
# - Nueva opción: Hacer que el parámetro INT actúe como parámetro de suerte.
#  Eso afecta al oro obtenido (entre el mínimo y máximo) y a la probabilidad
#  de obtener items raros.
#==============================================================================

module Chest_System
  # Int afecta a la posibilidad de obtener items raros
  INT_RARITY_EFFECT = true
  # Int afecta a la posibilidad de obtener más items
  INT_NUMBER_EFFECT = true
  # Int afecta a la posibilidad de obtener más dinero
  INT_GOLD_EFFECT = true
  # Fuerza del parámetro Int
  INT_POWER = 50
end

for Klass in [RPG::Item, RPG::Weapon, RPG::Armor]
  class Klass
    define_method(:rarity) { @rarity ||= 50 } # Por defecto vale 50
  end
end

class Scene_Title
  alias rarity_set_chestdata set_chest_data unless $@
  def set_chest_data
    rarity_set_chestdata
    # Define aquí la rarity de los objetos, armas y protectores que lo requieran
    $data_items[1].rarity = 80
    $data_items[2].rarity = 20
  end
end

class Game_Party
  #--------------------------------------------------------------------------
  # * Obtener la suerte del grupo según INT
  #--------------------------------------------------------------------------
  def chest_luck
    int = 0
    for i in 0...@actors.size
      actor = @actors[i]
      int += actor.int
    end
    int /= @actors.size
    return [(int / 5), 100].min
  end
end

class Scene_ExtChest
  #--------------------------------------------------------------------------
  # * Get Chest Number
  #--------------------------------------------------------------------------
  alias luck_get_chest_number get_chest_number unless $@
  def get_chest_number
    chest = $game_chests[@chest_id]
    return if chest.chest_goods.keys.size == 0
    if Chest_System::INT_NUMBER_EFFECT == false
      luck_get_chest_number
      return
    end
    if chest.min_number == chest.max_number
      luck_get_chest_number
      return
    end
    distance = chest.max_number - chest.min_number
    number_array = []
    for d in 0...distance
      luck = $game_party.chest_luck
      power = [[100 - Chest_System::INT_POWER, 1].max, 100].min
      n = 10 + (luck * power * d) / 400
      n.times { number_array.push(d) }
    end
    @number = chest.min_number + number_array[rand(number_array.size)]
  end
  #--------------------------------------------------------------------------
  # * Get Chest Gold
  #--------------------------------------------------------------------------
  alias luck_get_chest_gold get_chest_gold unless $@
  def get_chest_gold
    chest = $game_chests[@chest_id]
    if Chest_System::INT_GOLD_EFFECT == false
      luck_get_chest_gold
      return
    end
    if chest.min_gold == chest.max_gold
      luck_get_chest_gold
      return
    end
    min = chest.min_gold
    max = chest.max_gold
    d = max / min
    luck = $game_party.chest_luck
    power = [[100 - Chest_System::INT_POWER, 1].max, 100].min
    min = min + (luck * power * d) / 100
    min = [max, min].min
    @gold = min + rand(max - min)
  end
  #--------------------------------------------------------------------------
  # * Get Chest Items
  #--------------------------------------------------------------------------
  def get_chest_items
    chest = $game_chests[@chest_id]
    return if @number == 0
    @array = []
    for k in chest.chest_goods.keys
      item_array = []
      case k[0]
      when 0 # Objeto
        item = $data_items[k[1]]
      when 1 # Arma
        item = $data_weapons[k[1]]
      when 2 # Protector
        item = $data_armors[k[1]]
      end
      rarity = item.rarity
      if Chest_System::INT_RARITY_EFFECT
        luck = $game_party.chest_luck
        power = [[100 - Chest_System::INT_POWER, 1].max, 100].min
        if rarity > 50
          # Objeto raro pasa a ser más común
          rarity = rarity - (luck * rarity) / (power * 10)
        else
          # Objeto común pasa a ser menos común
          rarity = rarity + (luck * (100 - rarity)) / (power * 10)
        end
      end
      item_array = [k, (100 - rarity)]
      number = chest.chest_goods[k]
      number.times { @array.push(item_array) }
    end
    @number.times do
      break if @array.size == 0
      item = get_next_item
      @items.push(item)
    end
  end
  #--------------------------------------------------------------------------
  # * Get Next Item
  #--------------------------------------------------------------------------
  def get_next_item
    a = []
    for i in 0...@array.size
      @array[i][1].times { a.push(@array[i][0]) }
    end
    item = a[rand(a.size)]
    for i in 0...@array.size
      if @array[i][0] == item
        @array.delete_at(i)
        break
      end
    end
    return item
  end
end

Eso es todo, espero que os sirva. Podéis hacer las modificaciones que queráis al sistema, por ejemplo en la interface, que sé que es bastante simple xD
avatar
Wecoc
Administrador
Administrador



Créditos 12284

Gracias : 645

Volver arriba Ir abajo

RPG Maker XP Re: [XP] Chest System

Mensaje por xXIsrael0499Xx el 2017-11-20, 23:44

Oh madre mia, muy buena idea ya no se necesitara hacer Engines para hacer sistemas de cofres, muy buena iniciativa wecoc, así que gracias y eso,
avatar
xXIsrael0499Xx
Veterano
Veterano

0/3

Créditos 2047

Gracias : 113

Volver arriba Ir abajo

Ver el tema anterior Ver el tema siguiente Volver arriba


Permisos de este foro:
No puedes responder a temas en este foro.