最後更新於 2022 年 6 月 18 日
終於還是來履行我的承諾了… 之前說有空就來研究一下輪迴怎麼做,最近剛好閒下來就開搞,目前這個版本是使用消耗品召喚輪迴(怪物)將地圖上的怪物數量 *2倍。
本篇教學示範版本為 v120,應該大部分版本都適用。
效果演示
新增輪迴碑石怪物
首先用 HaRepacker 打開 Mob.wz
,並且隨意新增一個 Image,比如我是新增 999026.img
,內容節點請複製 9990013.img
的,然後將 hit1
整個節點刪除。
- 把
die1
改名為die
,並且將 0 ~ 5 節點圖片換成輪迴碑石圖包 die 資料夾的圖片。 - 把
stand
的 0 ~ 8 節點圖片換成輪迴碑石圖包 stand 資料夾的圖片。 - stand 圖片 origin X: 55, Y: 210
- die 圖片 1, 2 origin X: 55, Y: 210 ; 3 origin X: 85, Y: 210 ; 4 origin X: 80, Y: 65 ; 5 origin X: 85, Y: 51
info 節點的內容 :
bodyAttack: 0 elemAttr: S1H3 acc: 150 boss: 1 eva: 30 exp: 0 level: 200 MADamage: 0 maxHP: 5000000 maxMP: 5000 MDDamage: 0 PADamage: 0 PDDamage: 0 pushed: 3000 removeAfter: 300 (以秒為單位, 自行設定) speed: -20 summonType: 0 undead: 0
最後結構如下:
新增輪迴消耗道具
接著用 HaRepacker 打開 Item.wz
,進入 Consume (消耗) 節點,找到 0210.img
雙擊展開,隨意新增一個 sub 節點,我這邊以 02109013
作為示範,內容節點直接複製 02101081
就可以。
- icon 及 iconRaw 換成輪迴圖包中的
輪迴.png
,icon及 iconRaw 的 origin 為X:-2 , Y: 33
- info 節點內容:
- 新增
notSale
(int) 節點為 1 slotMax
設為 100 (一格欄位最多能堆疊多少個)timeLimited
設為 1type
設為 1
- 新增
- mob 節點內容:
- 0 – id 設為輪迴怪物代碼 (像我就是 999026 )
- 0 – prob 設為 100
最後結構如下:
如果以上步驟都做完,在遊戲中下指令 !drop 2109013
獲取輪迴之後使用,地圖上應該就會出現輪迴,如果你的輪迴有被叫出來就可以繼續下面的步驟了。
順帶一提,String.wz 也要加上 2109013 的節點,不然你的輪迴消耗道具是不會有名字和描述的。
判斷地圖上有輪迴就加速怪物生長
有了輪迴怪物和輪迴召喚包後,我們還需要修改 SRC 來判斷地圖上是否有輪迴,如果有就將該地圖的怪物數量乘以你指定的倍率,但如果是特殊地圖或者有 BOSS 的地圖就不會生效。
打開 SRC,在 server.maps 裡新增 MobConstants.java
,內容如下:
/* * 輪迴碑石 */ package server.maps; import server.maps.MapleMap; import server.maps.MapleMapObject; import server.life.MapleMonster; import constants.MapConstants; public class MobConstants { public static int[] REINCARNATION_MOB = new int[]{ 9990026, 2 }; // 輪迴怪物代碼, 生怪數量倍率 public static int isMonsterSpawn(MapleMap map) { int addition = 1; if (MapConstants.isBossMap(map.getId()) || MapConstants.isEventMap(map.getId())) { // 判斷是否為特殊地圖, 輪迴不會在特殊地圖生效 return 1; } for (MapleMapObject obj : map.getAllMonstersThreadsafe()) { // 判斷地圖有boss, 回傳倍率1 final MapleMonster mob = (MapleMonster) obj; if (mob.getStats().isBoss() && !isReincarnationMob(mob.getId())) { return 1; } } if (map.getMonsterById(REINCARNATION_MOB[0]) != null) { // 判斷是否有輪迴 addition *= REINCARNATION_MOB[1]; // 乘以倍率 } return addition; } public static boolean isReincarnationMob(int mobid) { // 判斷是否為輪迴怪物 if (REINCARNATION_MOB[0] == mobid) { return true; } return false; } public static boolean isSpawnSpeed(MapleMap map) { if (map.getMonsterById(REINCARNATION_MOB[0]) != null) { return true; } return false; } }
接著打開 server.maps.MapleMap.java,在最上方引入 MobConstants:
import server.maps.MobConstants;
接著在 MapleMap.java
中 ctrl + f 搜尋「public void respawn
」,將 numShouldSpawn 改為以下程式碼:
final int numShouldSpawn = monsterSpawn.size() * MobConstants.isMonsterSpawn(this) - spawnedMonstersOnMap.get(); // 輪迴倍率 // final int numShouldSpawn = monsterSpawn.size() - spawnedMonstersOnMap.get();
完整的 respawn 函式程式碼為:
public void respawn(final boolean force) { lastSpawnTime = System.currentTimeMillis(); if (force) { //cpq quick hack final int numShouldSpawn = monsterSpawn.size() * MobConstants.isMonsterSpawn(this) - spawnedMonstersOnMap.get(); // 輪迴倍率 // final int numShouldSpawn = monsterSpawn.size() - spawnedMonstersOnMap.get(); if (numShouldSpawn > 0) { int spawned = 0; for (Spawns spawnPoint : monsterSpawn) { spawnPoint.spawnMonster(this); spawned++; if (spawned >= numShouldSpawn) { break; } } } } else { final int numShouldSpawn = maxRegularSpawn * MobConstants.isMonsterSpawn(this) - spawnedMonstersOnMap.get(); // 輪迴倍率 // final int numShouldSpawn = maxRegularSpawn - spawnedMonstersOnMap.get(); if (numShouldSpawn > 0) { int spawned = 0; final List<Spawns> randomSpawn = new ArrayList<Spawns>(monsterSpawn); Collections.shuffle(randomSpawn); for (Spawns spawnPoint : randomSpawn) { if (spawnPoint.shouldSpawn() || GameConstants.isForceRespawn(mapid)) { spawnPoint.spawnMonster(this); spawned++; } if (spawned >= numShouldSpawn) { break; } } } } }
繼續在 MapleMap.java 中搜索 canSpawn
,將 function 內容改為:
public final boolean canSpawn() { createMobInterval = (short) (MobConstants.isSpawnSpeed(this) ? 0 : 9000); // 有輪迴時怪物重生時間間隔為 0 return lastSpawnTime > 0 && isSpawns && lastSpawnTime + createMobInterval < System.currentTimeMillis(); // return true; }
若地圖上有輪迴就不能再放
1.打開 server.life.MapleMonsterStats.java
最上面 private int 處加上 ,SpawnChrId
接著在最下面加上:
public int getSpawnChrId() { return SpawnChrId; }
2.打開 server.life.MapleMonster.java
最下面加上:
public final int getSpawnChrid(){ return stats.getSpawnChrId(); }
3.在 client.MapleCharacter.java
最下方加上:(這個函式是用來判斷地圖上是否有輪迴)
public boolean isReincarnationMob() { for (MapleMonster monster : getMap().getAllMonster()) { if (monster.getId() == 9990026 && monster.getSpawnChrid() != this.getId()) { // 輪迴 mob id return true; } } return false; }
4.打開 handling.channel.handler
的 InventoryHandler.java
,加上 UseSummonBagNotCSP 函式:
public static int UseSummonBagNotCSP(int itemId) { int result = 0; switch (itemId) { case 2109013: // 輪迴道具 ID result = 1; break; } return result; }
5.接著搜索 UseSummonBag
,在這段程式碼下方加上:
if (c.getPlayer().isGM() || !FieldLimitType.SummoningBag.check(chr.getMap().getFieldLimit())) { final List<Pair<Integer, Integer>> toSpawn = MapleItemInformationProvider.getInstance().getSummonMobs(itemId); if (toSpawn == null) { c.getSession().write(MaplePacketCreator.enableActions()); return; } /* 加上下方這段 */ if (UseSummonBagNotCSP(toUse.getItemId()) > 0) { int result = UseSummonBagNotCSP(toUse.getItemId()); if (result > 0) { if (chr.isReincarnationMob()) { switch (result) { case 1: { chr.dropMessage("地圖上有人施放了輪迴"); break; } } c.getSession().write(MaplePacketCreator.enableActions()); return; } } } //....
結語
至此簡單的輪迴功能就實現了,還有很多種可以實現輪迴的方式,比如輪迴技能也是其中之一,大家可以自己多嘗試看看。這篇教學其實還有一些小問題沒有解決,就留給大家自己腦力激盪了!
- React 那些好看、有趣、實用的函式庫、組件庫推薦(2) - 2022 年 6 月 26 日
- 解決 preact-router 資源請求路徑錯誤的問題 - 2022 年 6 月 24 日
- [楓之谷私服] 潮流轉蛋機 NPC 腳本優化 - 2022 年 6 月 19 日
請問這是用在自己架設私服單人上,還是可以用在別人開的私服上呢
只有自己架設的才能改喔!要有這個服端口的源碼才能改。
佛 我是直接全地圖改數量跟重生,沒有另外弄東西去觸發,感恩分享輪迴效果的做法
我也是各個端口”借鑒”來的 XD 就是看自己需求再把一些不用的東西拔了然後改一改
我想請問一下 按照上面的修改法 會造成無法刷出怪物的問題 v113
問題好像是在respawn 用原本語法 正常刷怪
改了respawn 之後 變成無法正常刷怪出來
方便提供一下你的 respawn 的截圖嗎?我想確認一下是什麼問題。正常來說只需要改 numShouldSpawn 這個變數就可以了。確認一下用到的變數都有存在,該 import 的也有 import。
不會上傳圖片
有//的地方 是原本要修改的部分
我目前適用原版語法 把改的部分目前先標記調
還是看不懂的話我的DC 鬼魅魍魎#5079
public void respawn(final boolean force) {
lastSpawnTime = System.currentTimeMillis();
if (force) { //cpq quick hack
//final int numShouldSpawn = monsterSpawn.size() * MobConstants.isMonsterSpawn(this) – spawnedMonstersOnMap.get(); // 輪迴倍率
final int numShouldSpawn = monsterSpawn.size() – spawnedMonstersOnMap.get();
if (numShouldSpawn > 0) {
int spawned = 0;
for (Spawns spawnPoint : monsterSpawn) {
spawnPoint.spawnMonster(this);
spawned++;
if (spawned >= numShouldSpawn) {
break;
}
}
}
} else {
//final int numShouldSpawn = maxRegularSpawn * MobConstants.isMonsterSpawn(this) – spawnedMonstersOnMap.get(); // 輪迴倍率
final int numShouldSpawn = maxRegularSpawn – spawnedMonstersOnMap.get();
if (numShouldSpawn > 0 && monsterSpawn.size() > 0) {
final List<Spawns> randomSpawn = new ArrayList<>(monsterSpawn);
Collections.shuffle(randomSpawn);
for (Spawns spawnPoint : randomSpawn) {
if (spawnPoint.shouldSpawn() || GameConstants.isForceRespawn(mapid)) {
spawnPoint.spawnMonster(this);
}
}
}
}
}
你 else 之後的內容照著我文章中給的程式碼試試呢?還有 canSpawn 那邊也要改
我是用113的端口 忘了說
補充說明 我自己改寫語法 完成設定 感謝版大耐心教學
語法設定上有點小錯誤
作者你好 請問前面第一階段新增輪迴怪物做完後 進去遊戲輸入!drop 2109013後成功丟出輪迴 但是點擊輪迴後並沒有輪迴出現 而且後台還跑出了下面的錯誤訊息 請問是什麼原因造成的?
檢查一下輪迴怪物跟消耗品的wz節點有沒有跟我文中列的一樣