查看: 1142|回复: 0

[原创发布] VA冒险者公会任务交互系统/任务悬赏系统脚本

[复制链接]
梦石
0
星屑
260
在线时间
38 小时
注册时间
2023-11-3
回帖
2
发表于 2025-8-1 08:48:37 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 Adelina 于 2025-8-1 08:48 编辑

站内找到的任务系统似乎都是用来查看任务的,没有交互选项……
于是作为ruby萌新的自己只好结合ds的帮助写了一点,分享出来希望可以帮到有类似想法的人。虽然但是都25年了真的还有人在玩VA吗
这个任务系统有接受任务和提交、放弃的选项,比较类似于冒险者公会的悬赏面板。提交任务后可以根据需求打开开关,方便其他事件。比如想要在提交任务后,根据任务的完成情况来发放奖励的话,就可以用开关继续开启一个公共事件。
每用一次添加任务描述都会换行,同时文本内容也支持使用转义符,需要使用双反斜杠。效果和VA文本框里面的一样,具体可以看事件里的脚本指令。其他指令在脚本开头的使用方法里。
脚本里的常量配置部分是可以自行更改的,其中任务与开关映射表也需要自己编辑。修改时请务必注意格式。

新人第一次发帖,可能有bug或者其他各种问题,欢迎积极反馈,只要我看到了消息并且有空的话就会改。如果能够帮到你,希望可以评论一下~

游戏内效果如下:
屏幕截图 2025-08-01 081921.png    屏幕截图 2025-08-01 081936.png

事件范例:
屏幕截图 2025-08-01 081849.png

脚本代码:
[pre lang="ruby" line="1"]#===============================================================================
#
# ■ 公会任务系统 - By Adelina
#
#===============================================================================

#===============================================================================
# ● 事件指令使用方法
#===============================================================================
# 1. 打开公会面板: open_quest_board
# 2. 创建任务:     $game_party.create_quest(任务id, "任务标题")
# 3. 添加任务描述: $game_party.add_quest_text(任务id, "描述文本")
# 4. 设置任务可见: $game_party.set_quest_visible(任务id, true/false)
# 5. 接取任务:     $game_party.accept_quest(任务id)  # 可在事件中使用
# 6. 完成任务:     $game_party.finish_quest(任务id)  # 可在事件中使用

#===============================================================================
# ● 常量配置
#===============================================================================
module QuestConfig
  # 窗口尺寸比例
  LEFT_WINDOW_WIDTH_RATIO  = 0.4     # 左侧窗口宽度比例
  RIGHT_WINDOW_HEIGHT_RATIO = 0.827  # 右侧窗口高度比例
  
  # 状态字体与文本设置
  STATUS_FONT_SIZE = 18                         # 状态文字大小
  AVAILABLE_STATUS  = "可接取 - 按Enter接取任务" # 可接取状态提示
  ACCEPTED_STATUS   = "进行中 - 按Enter管理任务" # 进行中状态提示
  ACCEPTED_COLOR   = Color.new(255, 255, 0)     # 进行中状态文本颜色

  # 无任务时显示的文本内容
  NO_QUEST_TEXT  = "暂无任务"  
  
  # 可接受任务选项文本
  ACCEPT_TEXT   = "接受任务"
  DECLINE_TEXT  = "取消"
  
  # 进行中任务选项文本
  SUBMIT_TEXT   = "提交任务"  # 打开对应开关后,从系统中删除任务
  ABANDON_TEXT  = "放弃任务"  # 直接从系统中删除任务
end


# 任务ID与开关映射表
# 提交任务后会打开对应的开关,可以接各种事件
QUEST_SWITCH_MAP = {
  # 格式:任务ID => 开关ID
  1 => 10,   # 任务1完成时打开开关10
  2 => 11,   # 同理,任务2完成时打开开关11
  3 => 12
}



#===============================================================================
#===============================================================================
#
# ★ 请尽量不要修改以下内容
#
#===============================================================================
#===============================================================================

class Quest
  attr_reader :id
  attr_reader :name
  attr_accessor :accepted
  attr_accessor :visible
  attr_reader :content
  
  def initialize(id, name)
    @id = id
    @name = name
    @accepted = false
    @visible = true  # 默认可见
    @content = []
  end
  
  def add_text(text)
    @content << text
  end

  def available?
    !accepted && visible
  end
end


class Game_Party < Game_Unit
  alias quest_init initialize
  def initialize
    quest_init
    @quests = {}
  end

  def create_quest(id, name)
    @quests[id] = Quest.new(id, name)
  end
  
  def add_quest_text(id, text)
    quest = @quests[id]
    quest.add_text(text) if quest
  end
  
  def set_quest_visible(id, visible)
    quest = @quests[id]
    quest.visible = visible if quest
  end
  
  def accept_quest(id)
    quest = @quests[id]
    return unless quest && quest.available?
    quest.accepted = true
  end
  
  def finish_quest(id)
    @quests.delete(id)
  end
  
  def abandon_quest(id)
    @quests.delete(id)
  end
  
  def all_quests
    accepted_quests = @quests.values.select(&:accepted)
    available_quests = @quests.values.select(&:available?)
    accepted_quests + available_quests
  end
  
  def quest(id)
    @quests[id]
  end
end


class Window_QuestLeft < Window_Selectable
  include QuestConfig
  
  def initialize
    width = (Graphics.width * LEFT_WINDOW_WIDTH_RATIO).to_i
    height = Graphics.height
    super(0, 0, width, height)
    refresh
    activate
  end
  
  def item_max
    $game_party.all_quests.size
  end
  
  def quest
    $game_party.all_quests[@index]
  end
  
  def refresh
    make_item_list
    create_contents
    draw_all_items
  end
  
  def make_item_list
    @data = $game_party.all_quests
  end
  
  def draw_item(index)
    quest = @data[index]
    return unless quest
    rect = item_rect(index)
   
    if quest.accepted
      contents.font.color = ACCEPTED_COLOR
    else
      contents.font.color = normal_color
    end
   
    draw_text(rect, quest.name)
    contents.font.color = normal_color
  end
  
  def ok_enabled?
    item_max > 0
  end
  
end


class Window_QuestRight < Window_Base
  include QuestConfig
  
  def initialize
    left_width = (Graphics.width * LEFT_WINDOW_WIDTH_RATIO).to_i
    width = Graphics.width - left_width
    height = (Graphics.height * RIGHT_WINDOW_HEIGHT_RATIO).to_i
    super(left_width, 0, width, height)
    @quest = nil
  end
  
  def set_quest(quest)
    @quest = quest
    refresh
  end
  
  def refresh
    return if disposed? || contents.disposed?

    contents.clear
   
    if @quest.nil?
      contents.font.color = system_color
      rect = Rect.new(0, 0, contents_width, contents_height)
      draw_text(rect, NO_QUEST_TEXT, 1)
      contents.font.color = normal_color
      return
    end

    original_size = contents.font.size
   
    draw_text(0, 0, contents_width, line_height, @quest.name, 1)
    y = line_height + 10
   
    @quest.content.each do |text|
      draw_text_ex(0, y, text)
      y += line_height * 1.2
    end
   
    contents.font.size = STATUS_FONT_SIZE
   
    status_text = @quest.accepted ? ACCEPTED_STATUS : AVAILABLE_STATUS
    status_color = @quest.accepted ? ACCEPTED_COLOR : normal_color
   
    contents.font.color = status_color
    draw_text(0, contents_height - line_height, contents_width,
              line_height, status_text, 1)
   
    contents.font.color = normal_color
    contents.font.size = original_size
  end
end


class Window_QuestOption < Window_Command
  include QuestConfig
  
  attr_reader :closed
  
  def initialize(quest)
    @quest = quest
    @closed = false
    super(0, 0)
    update_placement
    self.openness = 255
    activate
  end
  
  def window_width
    return Graphics.width - (Graphics.width * LEFT_WINDOW_WIDTH_RATIO).to_i
  end
  
  def update_placement
    left_width = (Graphics.width * LEFT_WINDOW_WIDTH_RATIO).to_i
    self.x = left_width
    self.y = (Graphics.height * RIGHT_WINDOW_HEIGHT_RATIO).to_i
    self.width = Graphics.width - left_width
  end
  
  def make_command_list
    if @quest.accepted
      add_command(SUBMIT_TEXT, :submit)
      add_command(ABANDON_TEXT, :abandon)
    else
      add_command(ACCEPT_TEXT, :accept)
      add_command(DECLINE_TEXT, :decline)
    end
  end
  
  def close_window
    @closed = true
    deactivate
    self
  end
end


class Scene_QuestBoard < Scene_Base
  include QuestConfig
  
  def start
    super
    create_left_window
    create_right_window
    @option_window = nil
    select_first_quest
  end
  
  def select_first_quest
    if @left_window.item_max > 0
      @left_window.select(0)
      update_right_window
    else
      @right_window.set_quest(nil)
    end
  end
  
  def create_left_window
    @left_window = Window_QuestLeft.new
    @left_window.set_handler(:ok, method(:on_quest_ok))
    @left_window.set_handler(:cancel, method(:return_scene))
    @left_window.set_handler(:up, method(:on_selection_change))
    @left_window.set_handler(:down, method(:on_selection_change))
  end
  
  def create_right_window
    left_width = (Graphics.width * LEFT_WINDOW_WIDTH_RATIO).to_i
    width = Graphics.width - left_width
    height = (Graphics.height * RIGHT_WINDOW_HEIGHT_RATIO).to_i
    @right_window = Window_QuestRight.new
  end
  
  def on_selection_change
    update_right_window
    close_option_window if @option_window
  end
  
  def update_right_window
    quest = @left_window.quest
    @right_window.set_quest(quest) if quest
  end
  
  def on_quest_ok
    close_option_window if @option_window
    @quest = @left_window.quest
    return unless @quest
    return unless $game_party.quest(@quest.id)
    create_option_window
  end
  
  def update
    super
    return if @left_window.disposed?
    if !@option_window && @left_window.active
      @right_window.set_quest(@left_window.quest)
      update_right_window
    end
   
    if @option_window && @option_window.closed
      @option_window.dispose
      @option_window = nil
      @left_window.activate if @left_window && !@left_window.disposed?
    end
  end
  
  def create_option_window
    return unless @quest && $game_party.quest(@quest.id)
   
    @option_window = Window_QuestOption.new(@quest)
    if @quest.accepted
      @option_window.set_handler(:submit, method(:submit_quest))
      @option_window.set_handler(:abandon, method(:abandon_quest))
    else
      @option_window.set_handler(:accept, method(:accept_quest))
      @option_window.set_handler(:decline, method(:close_option_window))
    end
    @option_window.set_handler(:cancel, method(:close_option_window))
    @left_window.deactivate
  end
  
  def accept_quest
    $game_party.accept_quest(@quest.id)
    Sound.play_ok
    @left_window.refresh
    update_right_window
    @option_window.close_window if @option_window
  end
  
  def submit_quest
    switch_id = QUEST_SWITCH_MAP[@quest.id]
    if switch_id
      $game_switches[switch_id] = true
      $game_party.finish_quest(@quest.id)
      Sound.play_ok
      
      @left_window.refresh
      if @left_window.item_max > 0
        @left_window.select(0)
        quest = @left_window.quest
        @right_window.set_quest(quest)
      else
        @right_window.set_quest(nil)
      end
    else
      Sound.play_buzzer
      show_error_message("该任务尚未配置完成开关!" )
    end
    @option_window.close_window if @option_window
    update_right_window
  end
  
  def abandon_quest
    $game_party.abandon_quest(@quest.id)
    Sound.play_cancel

    @left_window.refresh
    if @left_window.item_max > 0
      @left_window.select(0)
      quest = @left_window.quest
      @right_window.set_quest(quest)
    else
      @right_window.set_quest(nil)
    end
    @option_window.close_window if @option_window
    update_right_window
  end
  
  def show_error_message(text)
    $game_message.add(text)
    SceneManager.call(Scene_Message)
  end
  
  def safe_close_option_window
    return unless @option_window
   
    @option_window.close_window
    @option_window.dispose
    @option_window = nil
   
    @left_window.activate if @left_window && !@left_window.disposed?
  end
  
  def close_option_window
    @option_window.close_window if @option_window
    update_right_window
  end
  
  def terminate
    super
    close_option_window
    @option_window.dispose if @option_window
  end
end

def open_quest_board
  SceneManager.call(Scene_QuestBoard)
end[/pre]

评分

参与人数 3赞 +3 收起 理由
HBOCYK + 1 精品文章
林洛liro + 1 精品文章
涅炎 + 1 精品文章

查看全部评分

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

本版积分规则

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

在本版发帖返回顶部