#===============================================================================
#
# ■ 公会任务系统 - 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