新增輪迴碑石怪物
首先用 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
如果以上步驟都做完,在遊戲中下指令 !item 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;
}
}
}
//....完整的 UseSummonBag 為:
public static final void UseSummonBag(final SeekableLittleEndianAccessor slea, final MapleClient c, final MapleCharacter chr) {
if (!chr.isAlive()) {
c.getSession().write(MaplePacketCreator.enableActions());
return;
}
c.getPlayer().updateTick(slea.readInt());
final byte slot = (byte) slea.readShort();
final int itemId = slea.readInt();
final IItem toUse = chr.getInventory(MapleInventoryType.USE).getItem(slot);
if (toUse != null && toUse.getQuantity() >= 1 && toUse.getItemId() == itemId) {
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.USE, slot, (short) 1, false);
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;
}
}
}
MapleMonster ht;
int type = 0;
for (int i = 0; i < toSpawn.size(); i++) {
if (Randomizer.nextInt(99) <= toSpawn.get(i).getRight()) {
ht = MapleLifeFactory.getMonster(toSpawn.get(i).getLeft());
chr.getMap().spawnMonster_sSack(ht, chr.getPosition(), type);
}
}
}
}
c.getSession().write(MaplePacketCreator.enableActions());
}