查看: 816|回复: 1

[原创发布] 仿《泰拉瑞亚》装备重铸系统

[复制链接]
梦石
1
星屑
1184
在线时间
59 小时
注册时间
2023-9-8
回帖
19
发表于 2026-4-8 00:12:01 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
本帖最后由 Ruigi 于 2026-4-17 01:02 编辑

[pre lang="ruby"]#==============================================================================
# ■ 泰拉瑞亚风格重铸系统 v3.0
#==============================================================================
# 作者:MrRuigi
# 功能:为武器/防具随机附加前缀,改变名称、属性、价格、稀有度
# 兼容:RPG Maker VX Ace,使用别名链避免冲突
#==============================================================================

#==============================================================================
# ■ 配置模块
#==============================================================================
module Reroll_Config
  REROLL_COST_RATE = 1.6          # 重铸费用倍率(基于物品原价)
  DISCOUNT_VARIABLE_ID = 10       # 打折变量ID(>0时8折)
  DISCOUNT_RATE = 0.8
  MAX_RARITY_FOR_REROLL = 0       # 0 = 无限制

  HELP_TEXT = "选择一件武器或防具进行重铸"
  COST_TEXT = "重铸费用:"
  DISCOUNT_TEXT = " (已打折)"
  NO_ITEM_TEXT = "请选择装备"
  SUCCESS_TEXT = "重铸成功!获得前缀:「%s」"
  NO_REROLL_TEXT = "这件装备无法重铸(稀有度过高)"
  NO_MONEY_TEXT = "金钱不足!需要 %d G"
end

#==============================================================================
# ■ 前缀数据模块
#==============================================================================
module Prefix_Data
  # 前缀ID => [名称, 攻击, 防御, 魔防, 敏捷, 价格倍率, 稀有度变化]
  PREFIX_LIST = {
    1 => ["碎裂的",  -10, 0,  -5, 0, 0.69, -2],
    2 => ["破损的",   -8, 0,  -3, 0, 0.74, -2],
    3 => ["糟糕的",   -6, 0,  -2, 0, 0.79, -1],
    4 => ["恶毒的",    5, 0,   2, 0, 1.05,  0],
    5 => ["精良的",    8, 0,   3, 0, 1.10,  1],
    6 => ["强力的",   10, 0,   0, 0, 1.12,  1],
    7 => ["超神的",   15, 0,   5, 0, 1.20,  2],
    8 => ["神级的",   15, 0,   4, 0, 1.20,  2],
    9 => ["恶魔的",   15, 0,   0, 0, 1.15,  2],
    10=> ["传说的",   18, 0,   5, 5, 1.25,  2],
    11=> ["坚固的",    0, 5,   0, 0, 1.05,  1],
    12=> ["保护的",    0, 8,   0, 0, 1.10,  1],
    13=> ["守卫的",    0, 3,   0, 0, 1.02,  0],
    14=> ["幸运的",    0, 0,   5, 5, 1.08,  1],
    15=> ["快速的",    0, 0,   0, 8, 1.05,  1],
    16=> ["耐心的",    0, 0,   0, 0, 1.00,  0],
    17=> ["凶猛的",    7, 0,   0, 0, 1.08,  1],
    18=> ["致命的",   10, 0,   3, 0, 1.12,  1],
    19=> ["灵活的",    5, 0,   2, 3, 1.05,  1],
    20=> ["熟练的",    6, 0,   4, 0, 1.06,  1],
  }

  def self.random_prefix_id
    PREFIX_LIST.keys.sample
  end

  def self.prefix_data(prefix_id)
    PREFIX_LIST[prefix_id] || PREFIX_LIST[1]
  end

  def self.prefix_name(prefix_id)
    prefix_data(prefix_id)[0]
  end

  # param_id 对应 params 数组索引:0=MHP,1=MMP,2=ATK,3=DEF,4=MAT,5=MDF,6=AGI,7=LUK
  def self.get_param_bonus(prefix_id, param_id)
    data = prefix_data(prefix_id)
    return 0 unless data
    case param_id
    when 2 then data[1]  # ATK
    when 3 then data[2]  # DEF
    when 5 then data[3]  # MDF
    when 6 then data[4]  # AGI
    else 0
    end
  end

  def self.price_rate(prefix_id)
    prefix_data(prefix_id)[5]
  end

  def self.rarity_change(prefix_id)
    prefix_data(prefix_id)[6]
  end
end

#==============================================================================
# ■ 前缀存储模块(基于类型+ID,支持存档)
#==============================================================================
module PrefixStorage
  @prefix_map = {}

  def self.key(item)
    "#{item.class.name}_#{item.id}"
  end

  def self.get_prefix(item)
    @prefix_map[key(item)] || 0
  end

  def self.set_prefix(item, prefix_id)
    @prefix_map[key(item)] = prefix_id.to_i
  end

  def self.remove_prefix(item)
    @prefix_map.delete(key(item))
  end

  def self.save_data
    @prefix_map
  end

  def self.load_data(data)
    @prefix_map = data.is_a?(Hash) ? data : {}
  end
end

#==============================================================================
# ■ 扩展 RPG::BaseItem(定义基础稀有度)
#==============================================================================
class RPG::BaseItem
  # 默认稀有度,可从备注中解析(如 <rarity: 2>)
  def rarity
    # 示例:self.note =~ /<rarity:\s*(\d+)>/i ? $1.to_i : 0
    0
  end
end

#==============================================================================
# ■ 扩展 RPG::Weapon(名称、价格、稀有度)
#==============================================================================
class RPG::Weapon
  alias reroll_original_name name

  def name
    prefix_id = PrefixStorage.get_prefix(self)
    if prefix_id > 0
      "#{Prefix_Data.prefix_name(prefix_id)}#{reroll_original_name}"
    else
      reroll_original_name
    end
  end

  def display_name
    name
  end

  alias reroll_price price
  def real_price
    prefix_id = PrefixStorage.get_prefix(self)
    (reroll_price * (prefix_id > 0 ? Prefix_Data.price_rate(prefix_id) : 1.0)).to_i
  end

  def rarity
    base = super
    prefix_id = PrefixStorage.get_prefix(self)
    base + (prefix_id > 0 ? Prefix_Data.rarity_change(prefix_id) : 0)
  end
end

#==============================================================================
# ■ 扩展 RPG::Armor(同上)
#==============================================================================
class RPG::Armor
  alias reroll_original_name name

  def name
    prefix_id = PrefixStorage.get_prefix(self)
    if prefix_id > 0
      "#{Prefix_Data.prefix_name(prefix_id)}#{reroll_original_name}"
    else
      reroll_original_name
    end
  end

  def display_name
    name
  end

  alias reroll_price price
  def real_price
    prefix_id = PrefixStorage.get_prefix(self)
    (reroll_price * (prefix_id > 0 ? Prefix_Data.price_rate(prefix_id) : 1.0)).to_i
  end

  def rarity
    base = super
    prefix_id = PrefixStorage.get_prefix(self)
    base + (prefix_id > 0 ? Prefix_Data.rarity_change(prefix_id) : 0)
  end
end

#==============================================================================
# ■ 核心:在 Game_BattlerBase 中注入前缀属性加成(仅角色)
#==============================================================================
class Game_BattlerBase
  alias reroll_param_plus param_plus
  def param_plus(param_id)
    base = reroll_param_plus(param_id)
    base + (is_a?(Game_Actor) ? equip_prefix_bonus(param_id) : 0)
  end

  def equip_prefix_bonus(param_id)
    return 0 unless is_a?(Game_Actor)
    equips.compact.inject(0) do |sum, item|
      if item.is_a?(RPG::Weapon) || item.is_a?(RPG::Armor)
        prefix_id = PrefixStorage.get_prefix(item)
        sum + Prefix_Data.get_param_bonus(prefix_id, param_id)
      else
        sum
      end
    end
  end
end

#==============================================================================
# ■ 修正 Game_Party 的装备列表方法
#==============================================================================
class Game_Party
  def all_weapons
    result = []
    @weapons.each do |item_id, count|
      weapon = $data_weapons[item_id]
      next unless weapon
      count.times { result << weapon }
    end
    result
  end

  def all_armors
    result = []
    @armors.each do |item_id, count|
      armor = $data_armors[item_id]
      next unless armor
      count.times { result << armor }
    end
    result
  end

  def all_reroll_items
    all_weapons + all_armors
  end
end

#==============================================================================
# ■ 重铸场景(已修复确认卡死)
#==============================================================================
class Scene_Reroll < Scene_Base
  def start
    super
    create_help_window
    create_item_window
    create_cost_window
    @last_item = nil
  end

  def create_help_window
    @help_window = Window_Help.new
    @help_window.set_text(Reroll_Config::HELP_TEXT)
  end

  def create_item_window
    wy = @help_window.height
    wh = Graphics.height - wy - 80
    wh = 0 if wh < 0
    @item_window = Window_RerollItem.new(0, wy, Graphics.width, wh)
    @item_window.set_handler(:ok, method(:on_reroll_ok))
    @item_window.set_handler(:cancel, method(:return_scene))
    @item_window.help_window = @help_window
    @item_window.activate
  end

  def create_cost_window
    y = Graphics.height - 80
    @cost_window = Window_Base.new(0, y, Graphics.width, 80)
    update_cost_display
  end

  def update_cost_display
    @cost_window.contents.clear
    item = @item_window.current_item
    if item && (item.is_a?(RPG::Weapon) || item.is_a?(RPG::Armor))
      cost = reroll_cost(item)
      discount_text = discount_active? ? Reroll_Config::DISCOUNT_TEXT : ""
      @cost_window.draw_text(0, 0, Graphics.width, 24,
        "#{Reroll_Config::COST_TEXT}#{cost} G#{discount_text}", 1)
    else
      @cost_window.draw_text(0, 0, Graphics.width, 24, Reroll_Config::NO_ITEM_TEXT, 1)
    end
  end

  def update
    super
    if @item_window.active && @item_window.current_item != @last_item
      update_cost_display
      @last_item = @item_window.current_item
    end
  end

  def on_reroll_ok
    item = @item_window.current_item
    unless item && (item.is_a?(RPG::Weapon) || item.is_a?(RPG::Armor))
      Sound.play_buzzer
      @item_window.activate
      return
    end

    unless can_reroll?(item)
      Sound.play_buzzer
      @help_window.set_text(Reroll_Config::NO_REROLL_TEXT)
      @item_window.activate
      return
    end

    cost = reroll_cost(item)
    if $game_party.gold < cost
      Sound.play_buzzer
      @help_window.set_text(sprintf(Reroll_Config::NO_MONEY_TEXT, cost))
      @item_window.activate
      return
    end

    $game_party.lose_gold(cost)
    new_prefix = Prefix_Data.random_prefix_id
    begin
      PrefixStorage.set_prefix(item, new_prefix)
      Sound.play_shop
      @help_window.set_text(sprintf(Reroll_Config::SUCCESS_TEXT, Prefix_Data.prefix_name(new_prefix)))
    rescue => e
      @help_window.set_text("重铸出现异常,请检查前缀配置")
      p "Reroll Error: #{e.message}"
    end

    @item_window.refresh
    update_cost_display
    @item_window.activate
    @item_window.update
    Graphics.frame_reset
  end

  def can_reroll?(item)
    return false unless item.is_a?(RPG::Weapon) || item.is_a?(RPG::Armor)
    return true if Reroll_Config::MAX_RARITY_FOR_REROLL == 0
    item.rarity <= Reroll_Config::MAX_RARITY_FOR_REROLL
  end

  def reroll_cost(item)
    base = (item.price * Reroll_Config::REROLL_COST_RATE).to_i
    discount_active? ? (base * Reroll_Config::DISCOUNT_RATE).to_i : base
  end

  def discount_active?
    $game_variables[Reroll_Config::DISCOUNT_VARIABLE_ID] > 0
  end

  def return_scene
    SceneManager.return
  end
end

#==============================================================================
# ■ 重铸物品选择窗口
#==============================================================================
class Window_RerollItem < Window_Selectable
  def initialize(x, y, width, height)
    super
    @data = []
    refresh
  end

  def current_item
    @data && @index >= 0 ? @data[@index] : nil
  end

  def item_max
    @data ? @data.size : 0
  end

  def refresh
    @data = $game_party.all_reroll_items
    create_contents
    draw_all_items
  end

  def draw_item(index)
    item = @data[index]
    return unless item
    rect = item_rect(index)
    change_color(normal_color)
    draw_text(rect.x, rect.y, rect.width - 60, line_height, item.display_name)
    draw_text(rect.x, rect.y, rect.width - 24, line_height, item.real_price, 2)
  end

  def update_help
    item = current_item
    if item
      text = "#{item.display_name}\n"
      text += "原价:#{item.price} G  现价:#{item.real_price} G\n"
      text += "稀有度:#{item.rarity}"
      @help_window.set_text(text)
    else
      @help_window.set_text("")
    end
  end
end

#==============================================================================
# ■ 存档/读档支持(前缀数据存入存档)
#==============================================================================
module DataManager
  class << self
    alias reroll_make_save_contents make_save_contents
    alias reroll_extract_save_contents extract_save_contents
  end

  def self.make_save_contents
    contents = reroll_make_save_contents
    contents[:prefixes] = PrefixStorage.save_data
    contents
  end

  def self.extract_save_contents(contents)
    reroll_extract_save_contents(contents)
    PrefixStorage.load_data(contents[:prefixes])
  end
end[/pre]
3_[L]8O4YLIA5HUD`E9R9V0.png
PULD6%_IFLAE{SJBX8R}V7R.png
JJ62`M`43ZUM8I7KZU2OWF8.png
@WG9%F}F]XTI3DW@2A8TAZB.png
梦石
1
星屑
1184
在线时间
59 小时
注册时间
2023-9-8
回帖
19
 楼主| 发表于 2026-4-8 00:14:30 | 显示全部楼层
进入重铸的指令
  1. SceneManager.call(Scene_Reroll)
复制代码
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部