本帖最后由 小强 于 2022-11-21 15:52 编辑
終於還是來履行我的承諾了… 之前說有空就來研究一下輪迴怎麼做,最近剛好閒下來就開搞,目前這個版本是使用消耗品召喚輪迴(怪物)將地圖上的怪物數量 *2倍。
新增輪迴碑石怪物首先用 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 設為 1
- type 設為 1
- mob 節點內容:
- 0 – id 設為輪迴怪物代碼 (像我就是 999026 )
- 0 – prob 設為 100
最後結構如下: 如果以上步驟都做完,在遊戲中下指令 !drop 2109013 獲取輪迴之後使用,地圖上應該就會出現輪迴,如果你的輪迴有被叫出來就可以繼續下面的步驟了。 順帶一提,String.wz 也要加上 2109013 的節點,不然你的輪迴消耗道具是不會有名字和描述的。 判斷地圖上有輪迴就加速怪物生長有了輪迴怪物和輪迴召喚包後,我們還需要修改 SRC 來判斷地圖上是否有輪迴,如果有就將該地圖的怪物數量乘以你指定的倍率,但如果是特殊地圖或者有 BOSS 的地圖就不會生效。 打開 SRC,在 server.maps 裡新增 MobConstants.java,內容如下: [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;
} 若地圖上有輪迴就不能再放
[Java] 纯文本查看 复制代码 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;
}
}
}
//.... 結語至此簡單的輪迴功能就實現了,還有很多種可以實現輪迴的方式,比如輪迴技能也是其中之一,大家可以自己多嘗試看看。這篇教學其實還有一些小問題沒有解決,就留給大家自己腦力激盪了!
|