返回教學列表
JS教學

JS教學 副本篇1:基礎 Boss 副本架構

這篇使用的是事件副本腳本,不是一般 NPC 對話腳本。NPC 通常負責把玩家送進副本,而這支副本腳本負責管理副本地圖、怪物、時間與玩家狀態。

副本腳本的核心概念是「每一組隊伍建立一個獨立空間」。玩家進入後,系統會複製一張副本地圖、生成指定 Boss,並在時間到、Boss 死亡、玩家死亡或離隊時做對應處理。

一、基礎參數設定

腳本最上方通常會先放可調整的參數。日後要換地圖、換 Boss、改血量或改副本名稱,只需要改這一段。

var eventmapid = 910000001; // BOSS出現地圖 var returnmap = 910000000; // 回到的地圖 var boss = 100100; var bosshp = 2000000; var bossmp = 1000000; var pos = [494, 213]; var eventname = "測試副本";

參數用途

eventmapid 是副本內使用的地圖,returnmap 是離開副本後回去的地圖。boss 是要生成的怪物代碼,bosshpbossmp 則用來覆蓋怪物原本的血量和魔量。

二、建立副本 setup()

setup(partyid) 是副本被開啟時的重要入口。它會用隊伍 ID 組出副本名稱,建立一個新的 Event Instance,並複製副本地圖。

function setup(partyid) { var instanceName = eventname + partyid; var eim = em.newInstance(instanceName); var map = eim.createInstanceMapS(eventmapid); beginQuest(eim); eim.startEventTimer(10 * 60 * 1000); return eim; }

eim.createInstanceMapS(eventmapid) 代表建立這個副本專用的地圖實體。這樣不同隊伍進入時,不會互相看到對方的怪物與進度。

三、開始副本與生成 Boss

beginQuest(eim) 在這份範例裡只做一件事:確認副本存在後,呼叫 monsterSpawn(eim) 生成 Boss。

function beginQuest(eim) { if (eim != null) { monsterSpawn(eim); } } function monsterSpawn(eim) { var map2 = eim.getMapInstance(0); map2.resetFully(); var mob = em.getMonster(boss); var modified = em.newMonsterStats(); modified.setOHp(bosshp); modified.setOMp(bossmp); mob.setOverrideStats(modified); eim.registerMonster(mob); map2.spawnMonsterOnGroundBelow(mob, new java.awt.Point(pos[0], pos[1])); }

為什麼要 registerMonster?

eim.registerMonster(mob) 會把這隻怪登記到副本管理器裡。這樣怪物死亡時,副本才知道是否已經清光怪物,並觸發 allMonstersDead(eim)

四、玩家進場與離場

玩家進入副本時,playerEntry(eim, player) 會把玩家傳送到副本地圖的 0 號傳點。玩家如果離開副本地圖,changedMap 會取消玩家在副本中的登記。

function playerEntry(eim, player) { var map = eim.getMapInstance(0); player.changeMap(map, map.getPortal(0)); eim.setProperty("isSquadPlayerID_" + player.getId(), "1"); } function changedMap(eim, player, mapid) { if (mapid != eventmapid) { eim.unregisterPlayer(player); eim.disposeIfPlayerBelow(0, 0); } }

disposeIfPlayerBelow(0, 0) 的意思是副本內玩家人數低於或等於指定條件時,清理副本。這能避免玩家都離開後,副本實體還一直留在伺服器裡。

五、副本結束條件

這份範例有兩個主要結束方式:時間到,或副本內怪物全數死亡。

function scheduledTimeout(eim) { if (eim == null) { return; } else { eim.disposeIfPlayerBelow(100, returnmap); } } function allMonstersDead(eim) { eim.disposeIfPlayerBelow(100, returnmap); eim.broadcastPlayerMsg(5, "恭喜挑戰通過。"); }

scheduledTimeout 會在 startEventTimer 設定的時間結束後觸發。範例中設定為 10 * 60 * 1000,也就是 10 分鐘。

六、常見事件函數整理

playerDead

玩家死亡時觸發。注意:如果玩家身上有原地復活,可能不會走這個函數。

playerRevive

玩家復活時觸發。範例中會補 50 HP,並把玩家傳回離場地圖。

playerDisconnected

玩家斷線時觸發。會取消玩家副本登記,並設定回到地圖。

leftParty

玩家離開隊伍時觸發。範例會把玩家踢回返回地圖。

disbandParty

隊伍解散時觸發。通常會直接結束整個副本。

monsterValue

擊殺怪物時觸發,可用來做擊殺計數、階段推進或額外判斷。

七、可延伸功能

範例裡有幾行被註解掉的功能,之後可以依副本需求打開使用:

// map.toggleDrops(); // 拿掉註解後,地圖不會掉落任何原本會掉的東西 // map.spawnNpc(9209101, new java.awt.Point(x, y)); // 在副本地圖上召喚 NPC // map.addMapDrop(物品代碼, 掉落機率, 最小掉落數量, 最大掉落數量); // 新增此副本地圖的掉落物 // map.addDrop(怪物代碼, 物品代碼, 掉落機率, 最小掉落數量, 最大掉落數量); // 新增指定怪物的掉落物

八、完整流程總結

這支副本腳本的流程可以整理成:

setup() 建立副本 → createInstanceMapS() 複製副本地圖 → beginQuest() 開始挑戰 → monsterSpawn() 生成 Boss → playerEntry() 玩家進入副本 → allMonstersDead() 或 scheduledTimeout() 結束副本 → disposeIfPlayerBelow() 清理副本並送玩家回城

副本篇1先掌握這個最小架構就好:建立副本、生成怪物、處理玩家進出、處理結束條件。後續如果要做多階段 Boss、通關獎勵、限制每日次數、排名紀錄,就可以從這個架構往上加。