【楓之谷私服】v120 輪迴碑石

【楓之谷私服】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 設為 1
  • type 設為 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.handlerInventoryHandler.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());
    }
guest

1 評論
最舊
最新 最多投票
內聯回饋
查看全部評論