Class CharacterQuestManager

java.lang.Object
client.CharacterQuestManager

public final class CharacterQuestManager extends Object
角色「任務(quest)」子系統的協作者(核心任務 + 組隊任務 party quest),由 P5 God class 拆分自 MapleCharacter

本類別封裝對角色任務狀態表 questsMapleQuestMapleQuestStatus) 與任務附帶資料表 questinfo(questid → 自訂字串,亦供組隊任務使用)的核心存取,涵蓋:

MapleCharacter 以**逐字搬移**的方式把這些方法移入此處,並對每個對外公開方法保留 **簽名完全相同**的委派(delegate),因此所有 Java 呼叫端與 ~2,700 支腳本(皆透過 cmpiqm 等腳本 API 轉呼)完全不受影響。協作者僅持有對所屬角色的回參考,透過同 package 存取其 questsquestinfochanged_questinfopqStartTimeclient 等成員;questsquestinfo 這兩個欄位本身仍宣告並初始化於 MapleCharacter(載入/存檔/跨頻道搬移會直接存取),僅放寬為 package-private 供本協作者存取。 組隊任務方法建立在核心任務方法之上:在本類別內部以**裸名稱**互相呼叫(如 startPartyQuest 內呼叫 getQuestNAddupdateQuestupdateInfoQuest),與搬移前在 MapleCharacter 內的裸呼叫逐位元組一致。

  • Method Details

    • QuestInfoPacket

      public final void QuestInfoPacket(MaplePacketLittleEndianWriter mplew)
      將角色的任務附帶資料表 questinfo(主要供組隊任務使用)序列化寫入指定封包寫入器。

      先寫入項目數量(short),再逐筆寫入 questid(short)與其對應字串; 值為 null 時改寫空字串。註:對應的 quest 須另行加入 quests 清單。

      Parameters:
      mplew - 目標封包寫入器,呼叫後其緩衝區會被附加上述資料
    • updateInfoQuest

      public final void updateInfoQuest(int questid, String data)
      設定指定任務的附帶資料字串,並即時同步至客戶端。

      副作用:寫入 questinfo、將 changed_questinfo 標記為待存檔(true), 並向客戶端送出 InfoPacket.updateInfoQuest(int, String) 封包。

      Parameters:
      questid - 任務 ID
      data - 要儲存的附帶資料字串
    • getInfoQuest

      public final String getInfoQuest(int questid)
      取得指定任務的附帶資料字串。
      Parameters:
      questid - 任務 ID
      Returns:
      對應的附帶資料字串;若該任務尚無附帶資料則回傳空字串(不會回傳 null
    • getNumQuest

      public final int getNumQuest()
      計算角色已完成的(非自訂)任務數量。

      僅計入狀態為已完成(status == 2)且非自訂(!isCustom())的任務。

      Returns:
      已完成的一般任務數量
    • getQuestStatus

      public final byte getQuestStatus(int quest)
      取得指定任務(以 ID 指定)的狀態值。

      採非新增(no-add)語意:若角色尚無此任務則回傳 0(未開始),不會在 quests 表中建立新項目。

      Parameters:
      quest - 任務 ID
      Returns:
      任務狀態(0=未開始、1=進行中、2=已完成);任務不存在時為 0
    • getQuest

      public final MapleQuestStatus getQuest(MapleQuest quest)
      取得指定任務的狀態物件,必要時回傳一個全新的「未開始」狀態。

      若角色 quests 表中沒有此任務,回傳一個 status == 0 的全新 MapleQuestStatus,但**不**將其放入 quests(與 getQuestNAdd(MapleQuest) 不同—— 後者會放入;亦與 getQuestNoAdd(MapleQuest) 不同——後者直接回傳表中值、缺少時為 null)。

      Parameters:
      quest - 任務定義
      Returns:
      對應的任務狀態;缺少時為新建的未開始狀態(永不為 null
    • setQuestAdd

      public final void setQuestAdd(MapleQuest quest, byte status, String customData)
      在角色尚無此任務時,以指定狀態與自訂資料新增一筆任務狀態。

      具「不覆寫」語意:僅當 quests 表中尚不含此任務時才建立並放入新項目; 若已存在則不做任何更動。新項目的自訂資料會設為 customData

      Parameters:
      quest - 任務定義
      status - 初始狀態值(0=未開始、1=進行中、2=已完成)
      customData - 要附加的自訂資料字串
    • getQuestNAdd

      public final MapleQuestStatus getQuestNAdd(MapleQuest quest)
      取得指定任務的狀態物件,缺少時建立一筆「未開始」狀態並放入 quests 表。

      getQuest(MapleQuest) 的差異在於:本方法在缺少時會把新建的狀態**寫入** quests (產生狀態變更副作用),而 getQuest(MapleQuest) 只回傳暫時物件、不寫入。

      Parameters:
      quest - 任務定義
      Returns:
      對應的任務狀態;缺少時為新建並已放入表中的未開始狀態(永不為 null
    • getQuestNoAdd

      public final MapleQuestStatus getQuestNoAdd(MapleQuest quest)
      直接取得 quests 表中指定任務的狀態物件,缺少時不新增。

      採純查詢(no-add)語意:直接回傳表中對應值,不會建立任何新項目。

      Parameters:
      quest - 任務定義
      Returns:
      對應的任務狀態;若角色尚無此任務則為 null
    • getQuestRemove

      public final MapleQuestStatus getQuestRemove(MapleQuest quest)
      quests 表移除指定任務並回傳其原狀態物件。

      副作用:直接從角色的任務表移除該項目。

      Parameters:
      quest - 任務定義
      Returns:
      被移除的任務狀態;若原本就不存在則為 null
    • updateQuest

      public final void updateQuest(MapleQuestStatus quest)
      寫入/更新一筆任務狀態並同步至客戶端(非靜默模式)。

      等同呼叫 updateQuest(MapleQuestStatus, boolean) 並傳入 update == false, 因此進行中(status == 1)的任務會額外送出任務資訊更新封包。

      Parameters:
      quest - 要寫入的任務狀態
    • updateQuest

      public final void updateQuest(MapleQuestStatus quest, boolean update)
      寫入/更新一筆任務狀態,並(對非自訂任務)同步至客戶端。

      副作用:將狀態放入 quests(覆寫同 key)。若任務非自訂(!isCustom()), 送出 InfoPacket.updateQuest(MapleQuestStatus) 封包;當任務為進行中(status == 1)且 updatefalse 時,另送出 CField.updateQuestInfo(MapleCharacter, int, int, byte) 接受任務動畫封包。

      Parameters:
      quest - 要寫入的任務狀態
      update - true 表示僅更新(抑制進行中任務的接受動畫封包)
    • getInfoQuest_Map

      public final Map<Integer,String> getInfoQuest_Map()
      取得角色任務附帶資料表 questinfo 的底層參考。

      回傳的是**實際的底層 Map**(非複本,主要供載入/存檔直接存取),對其修改會直接影響角色狀態。

      Returns:
      questid → 附帶資料字串的底層 Map
    • getQuest_Map

      public final Map<MapleQuest, MapleQuestStatus> getQuest_Map()
      取得角色任務狀態表 quests 的底層參考。

      回傳的是**實際的底層 Map**(非複本,主要供載入/存檔直接存取),對其修改會直接影響角色狀態。

      Returns:
      MapleQuestMapleQuestStatus 的底層 Map
    • mobKilled

      public void mobKilled(int id, int skillID)
      將一次怪物擊殺回寫至所有相關的進行中任務的擊殺進度。

      逐一檢視角色的進行中(status == 1)且具擊殺需求(hasMobKills())的任務; 若該怪物使進度增加,送出 InfoPacket.updateQuestMobKills(MapleQuestStatus) 封包,並在任務已可完成時 另送出 CWvsContext.getShowQuestCompletion(int) 完成提示封包。

      Parameters:
      id - 被擊殺怪物的 ID
      skillID - 觸發擊殺的技能 ID(用於特定技能限定的任務計數)
    • getStartedQuests

      public final List<MapleQuestStatus> getStartedQuests()
      取得角色目前所有進行中的(非自訂、未被封鎖)任務。

      僅收錄狀態為進行中(status == 1)、非自訂(!isCustom())且任務未被封鎖 (!isBlocked())者。

      Returns:
      進行中任務狀態的新清單(可能為空)
    • getCompletedQuests

      public final List<MapleQuestStatus> getCompletedQuests()
      取得角色目前所有已完成的(非自訂、未被封鎖)任務。

      僅收錄狀態為已完成(status == 2)、非自訂(!isCustom())且任務未被封鎖 (!isBlocked())者。

      Returns:
      已完成任務狀態的新清單(可能為空)
    • getCompletedMedals

      public final List<Pair<Integer,Long>> getCompletedMedals()
      取得角色已完成且會頒發勳章(裝備類獎勵道具)的任務清單。

      getCompletedQuests() 的篩選條件之上,進一步要求任務具勳章道具 (getMedalItem() > 0)且該道具屬於裝備類(MapleInventoryType.EQUIP)。

      Returns:
      每筆為(任務 ID,完成時間戳)的配對清單(可能為空)
    • startPartyQuest

      public boolean startPartyQuest(int questid)
      開始一個組隊任務(party quest),必要時建立其任務狀態與初始附帶資料。

      僅當指定任務存在且為組隊任務(MapleQuest.isPartyQuest())時才處理。若角色尚未持有此任務 (questsquestinfo 缺少對應項目),則:透過 getQuestNAdd(MapleQuest) 取得狀態、設為 進行中(1)、updateQuest(MapleQuestStatus),並依 questid 以 updateInfoQuest(int, String) 寫入該 PQ 的初始 附帶資料字串(不同 PQ 的欄位格式不同,例如嘉年華/鬼屋/藥草鎮/精靈使用各自的模板,其餘走預設模板)。

      副作用:可能變更 questsquestinfo 並送出任務相關封包。本方法可重複呼叫; 若任務已開始則為無作用並回傳 false

      Parameters:
      questid - 組隊任務 ID
      Returns:
      true 表示本次呼叫實際開始了任務;false 表示任務無效、非組隊任務或已開始
    • getOneInfo

      public String getOneInfo(int questid, String key)
      從某組隊任務的附帶資料字串中,解析並取出單一欄位的值。

      附帶資料字串以 ";" 分隔多個 key=value 欄位;本方法依 key 比對回傳其值。

      Parameters:
      questid - 任務 ID
      key - 欲取出的欄位鍵
      Returns:
      對應欄位的值;若任務無附帶資料、keynull、任務不存在或查無此鍵,則為 null
    • updateOneInfo

      public void updateOneInfo(int questid, String key, String value)
      更新某組隊任務附帶資料字串中的單一欄位值,並同步至客戶端。

      解析既有的 key=value 欄位串,將符合 key 者的值改為 value(其餘原樣保留), 再透過 updateInfoQuest(int, String) 寫回(因而觸發其存檔標記與封包送出副作用)。若任務無附帶資料、 keyvaluenull、任務不存在或非組隊任務,則為無作用。

      Parameters:
      questid - 任務 ID
      key - 欲更新的欄位鍵
      value - 欄位的新值
    • recalcPartyQuestRank

      public void recalcPartyQuestRank(int questid)
      依某組隊任務目前的累計數據重新評定其等級(rank),達標時逐級晉升。

      僅處理有效的組隊任務。先呼叫 startPartyQuest(int)(確保任務已建立);唯有任務先前已開始 (該呼叫回傳 false)時才進行評定。將目前等級向上推進一階(F→D→C→B→A→S;已是 S 則不動), 並檢查新等級在任務定義中(MapleQuest.getInfoByRank(String))的所有門檻條件(lessmoreequal)。只有**全部**條件皆通過,才透過 updateOneInfo(int, String, String)rank 欄位寫為新等級。

      任一門檻欄位缺值或無法解析為整數時,會保守地中止本次評定(不晉升)。

      Parameters:
      questid - 組隊任務 ID
    • tryPartyQuest

      public void tryPartyQuest(int questid)
      記錄一次組隊任務的「嘗試」:開始任務、記下計時起點並累加嘗試次數。

      僅處理有效的組隊任務。呼叫 startPartyQuest(int) 後,將 pqStartTime 設為目前時間 (供 endPartyQuest(int) 計算耗時),並把 try 欄位 +1。整段流程包覆於 try/catch, 發生例外時記錄錯誤日誌而不向外拋出。

      Parameters:
      questid - 組隊任務 ID
    • endPartyQuest

      public void endPartyQuest(int questid)
      結算一次組隊任務的完成:記錄最佳耗時、累加完成次數與完成率,並重評等級。

      僅處理有效的組隊任務。呼叫 startPartyQuest(int) 後,若 pqStartTime > 0:依 目前時間與起點算出耗時(分、秒),當其優於既有最佳(min 欄位)時更新 minsecdate;接著把 cmp(完成次數)+1、重算 CR(完成率=cmp/try 取整),呼叫 recalcPartyQuestRank(int) 重評等級,最後把 pqStartTime 歸零。全程包覆於 try/catch, 發生例外時記錄錯誤日誌而不向外拋出。

      Parameters:
      questid - 組隊任務 ID
    • havePartyQuest

      public void havePartyQuest(int itemId)
      依持有的特定 PQ 道具標記對應組隊任務的「持有」欄位。

      將已知的 PQ 證明道具 ID 映射到其組隊任務 ID(部分道具還對應一個欄位索引 index, 例如藥草鎮、精靈、鬼屋的多件道具);不在映射表中的道具 ID 直接返回。確認任務有效且為組隊任務後, 呼叫 startPartyQuest(int),再以 updateOneInfo(int, String, String)have(或 have+索引) 欄位設為 "1"

      Parameters:
      itemId - 觸發的 PQ 道具 ID