/** * License * THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS * CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). * THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. * ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR * COPYRIGHT LAW IS PROHIBITED. * * BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND * AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE * MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED * HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. * */ package l1j.server.server.model; import java.util.logging.Level; import java.util.logging.Logger; import java.util.Calendar; import l1j.server.server.utils.Random; import l1j.server.Config; import l1j.server.server.GeneralThreadPool; import l1j.server.server.templates.L1Npc; public class L1BossSpawn extends L1Spawn { private static Logger _log = Logger.getLogger(L1BossSpawn.class.getName()); private class SpawnTask implements Runnable { private int _spawnNumber; private int _objectId; private SpawnTask(int spawnNumber, int objectId) { _spawnNumber = spawnNumber; _objectId = objectId; } @Override public void run() { doSpawn(_spawnNumber, _objectId); } } public L1BossSpawn(L1Npc mobTemplate) { super(mobTemplate); } /** * SpawnTaskを起動する。 * * @param spawnNumber * L1Spawnで管理されている番号。ホームポイントが無ければ何を指定しても良い。 */ @Override public void executeSpawnTask(int spawnNumber, int objectId) { // countをデクリメントして全部死んだかチェック if (subAndGetCount() != 0) { return; // 全部死んでいない } // 前回出現時間に対して、次の出現時間を算出 Calendar spawnTime; Calendar now = Calendar.getInstance(); // 現時刻 Calendar latestStart = _cycle.getLatestStartTime(now); // 現時刻に対する最近の周期の開始時間 Calendar activeStart = _cycle.getSpawnStartTime(_activeSpawnTime); // アクティブだった周期の開始時間 // アクティブだった周期の開始時間 >= 最近の周期開始時間の場合、次の出現 if (!activeStart.before(latestStart)) { spawnTime = calcNextSpawnTime(activeStart); } else { // アクティブだった周期の開始時間 < 最近の周期開始時間の場合は、最近の周期で出現 // わかりづらいが確率計算する為に、無理やりcalcNextSpawnTimeを通している。 latestStart.add(Calendar.SECOND, -1); spawnTime = calcNextSpawnTime(_cycle .getLatestStartTime(latestStart)); } spawnBoss(spawnTime, objectId); } private int _spawnCount; private synchronized int subAndGetCount() { return --_spawnCount; } private String _cycleType; public void setCycleType(String type) { _cycleType = type; } private int _percentage; public void setPercentage(int percentage) { _percentage = percentage; } private L1BossCycle _cycle; private Calendar _activeSpawnTime; @Override public void init() { if (_percentage <= 0) { return; } _cycle = L1BossCycle.getBossCycle(_cycleType); if (_cycle == null) { throw new RuntimeException(_cycleType + " not found"); } Calendar now = Calendar.getInstance(); // 出現時間 Calendar spawnTime; if (Config.INIT_BOSS_SPAWN && _percentage > Random.nextInt(100)) { spawnTime = _cycle.calcSpawnTime(now); } else { spawnTime = calcNextSpawnTime(now); } spawnBoss(spawnTime, 0); } // 確率計算して次の出現時間を算出 private Calendar calcNextSpawnTime(Calendar cal) { do { cal = _cycle.nextSpawnTime(cal); } while (!(_percentage > Random.nextInt(100))); return cal; } // 指定された時間でボス出現をスケジュール private void spawnBoss(Calendar spawnTime, int objectId) { // 今回の出現時間を保存しておく。再出現時に使用。 _activeSpawnTime = spawnTime; long delay = spawnTime.getTimeInMillis() - System.currentTimeMillis(); int cnt = _spawnCount; _spawnCount = getAmount(); while (cnt < getAmount()) { cnt++; GeneralThreadPool.getInstance().schedule( new SpawnTask(0, objectId), delay); } _log.log(Level.FINE, toString()); } /** * 現在アクティブなボスに対する周期と出現時間を表す。 */ @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("[MOB]npcid:" + getNpcId()); builder.append(" name:" + getName()); builder.append("[Type]" + _cycle.getName()); builder.append("[現在の周期]"); builder.append(_cycle.getSpawnStartTime(_activeSpawnTime).getTime()); builder.append(" - "); builder.append(_cycle.getSpawnEndTime(_activeSpawnTime).getTime()); builder.append("[出現時間]"); builder.append(_activeSpawnTime.getTime()); return builder.toString(); } }