📄 l1spawn.java
字号:
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* http://www.gnu.org/copyleft/gpl.html
*/
package l1j.server.server.model;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import l1j.server.Config;
import l1j.server.server.ActionCodes;
import l1j.server.server.GeneralThreadPool;
import l1j.server.server.IdFactory;
import l1j.server.server.datatables.NpcTable;
import l1j.server.server.model.Instance.L1MonsterInstance;
import l1j.server.server.model.Instance.L1NpcInstance;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.model.gametime.L1GameTime;
import l1j.server.server.model.gametime.L1GameTimeAdapter;
import l1j.server.server.model.gametime.L1GameTimeClock;
import l1j.server.server.templates.L1Npc;
import l1j.server.server.templates.L1SpawnTime;
import l1j.server.server.types.Point;
public class L1Spawn extends L1GameTimeAdapter {
private static l1j.eric.EricLogger _log = l1j.eric.EricLogger.getLogger2(L1Spawn.class.getName());
private final L1Npc _template;
private int _id; // just to find this in the spawn table
private String _location;
private int _maximumCount;
private int _npcid;
private int _groupId;
private int _locx;
private int _locy;
private int _randomx;
private int _randomy;
private int _locx1;
private int _locy1;
private int _locx2;
private int _locy2;
private int _heading;
private int _minRespawnDelay;
private int _maxRespawnDelay;
private short _mapid;
private boolean _respaenScreen;
private int _movementDistance;
private boolean _rest;
private int _spawnType;
private int _delayInterval;
private L1SpawnTime _time;
private HashMap<Integer, Point> _homePoint = null; // initでspawnした個々のオブジェクトのホームポイント
private List<L1NpcInstance> _mobs = new ArrayList<L1NpcInstance>();
private static Random _random = new Random();
private String _name;
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 L1Spawn(L1Npc mobTemplate) {
_template = mobTemplate;
}
public String getName() {
return _name;
}
public void setName(String name) {
_name = name;
}
public short getMapId() {
return _mapid;
}
public void setMapId(short _mapid) {
this._mapid = _mapid;
}
public boolean isRespawnScreen() {
return _respaenScreen;
}
public void setRespawnScreen(boolean flag) {
_respaenScreen = flag;
}
public int getMovementDistance() {
return _movementDistance;
}
public void setMovementDistance(int i) {
_movementDistance = i;
}
public int getAmount() {
return _maximumCount;
}
public int getGroupId() {
return _groupId;
}
public int getId() {
return _id;
}
public String getLocation() {
return _location;
}
public int getLocX() {
return _locx;
}
public int getLocY() {
return _locy;
}
public int getNpcId() {
return _npcid;
}
public int getHeading() {
return _heading;
}
public int getRandomx() {
return _randomx;
}
public int getRandomy() {
return _randomy;
}
public int getLocX1() {
return _locx1;
}
public int getLocY1() {
return _locy1;
}
public int getLocX2() {
return _locx2;
}
public int getLocY2() {
return _locy2;
}
public int getMinRespawnDelay() {
return _minRespawnDelay;
}
public int getMaxRespawnDelay() {
return _maxRespawnDelay;
}
public void setAmount(int amount) {
_maximumCount = amount;
}
public void setId(int id) {
_id = id;
}
public void setGroupId(int i) {
_groupId = i;
}
public void setLocation(String location) {
_location = location;
}
public void setLocX(int locx) {
_locx = locx;
}
public void setLocY(int locy) {
_locy = locy;
}
public void setNpcid(int npcid) {
_npcid = npcid;
}
public void setHeading(int heading) {
_heading = heading;
}
public void setRandomx(int randomx) {
_randomx = randomx;
}
public void setRandomy(int randomy) {
_randomy = randomy;
}
public void setLocX1(int locx1) {
_locx1 = locx1;
}
public void setLocY1(int locy1) {
_locy1 = locy1;
}
public void setLocX2(int locx2) {
_locx2 = locx2;
}
public void setLocY2(int locy2) {
_locy2 = locy2;
}
public void setMinRespawnDelay(int i) {
_minRespawnDelay = i;
}
public void setMaxRespawnDelay(int i) {
_maxRespawnDelay = i;
}
private int calcRespawnDelay() {
int respawnDelay = _minRespawnDelay * 1000;
if (_delayInterval > 0) {
respawnDelay += _random.nextInt(_delayInterval) * 1000;
}
L1GameTime currentTime = L1GameTimeClock.getInstance().currentTime();
if (_time != null && !_time.getTimePeriod().includes(currentTime)) { // 指定時間外なら指定時間までの時間を足す
long diff = (_time.getTimeStart().getTime() - currentTime.toTime()
.getTime());
if (diff < 0) {
diff += 24 * 1000L * 3600L;
}
diff /= 6; // real time to game time
respawnDelay = (int) diff;
}
return respawnDelay;
}
/**
* SpawnTaskを起動する。
*
* @param spawnNumber
* L1Spawnで管理されている番号。ホームポイントが無ければ何を指定しても良い。
*/
public void executeSpawnTask(int spawnNumber, int objectId) {
SpawnTask task = new SpawnTask(spawnNumber, objectId);
GeneralThreadPool.getInstance().schedule(task, calcRespawnDelay());
}
private boolean _initSpawn = false;
private boolean _spawnHomePoint;
public void init() {
if (_time != null && _time.isDeleteAtEndTime()) {
// 時間外削除が指定されているなら、時間経過の通知を受ける。
L1GameTimeClock.getInstance().addListener(this);
}
_delayInterval = _maxRespawnDelay - _minRespawnDelay;
_initSpawn = true;
// ホームポイントを持たせるか
if (Config.SPAWN_HOME_POINT
&& Config.SPAWN_HOME_POINT_COUNT <= getAmount()
&& Config.SPAWN_HOME_POINT_DELAY >= getMinRespawnDelay()
&& isAreaSpawn()) {
_spawnHomePoint = true;
_homePoint = new HashMap<Integer, Point>();
}
int spawnNum = 0;
while (spawnNum < _maximumCount) {
// spawnNumは1~maxmumCountまで
doSpawn(++spawnNum);
}
_initSpawn = false;
}
/**
* ホームポイントがある場合は、spawnNumberを基にspawnする。 それ以外の場合は、spawnNumberは未使用。
*/
protected void doSpawn(int spawnNumber) { // 初期配置
// 指定時間外であれば、次spawnを予約して終わる。
if (_time != null
&& !_time.getTimePeriod().includes(
L1GameTimeClock.getInstance().currentTime())) {
executeSpawnTask(spawnNumber, 0);
return;
}
doSpawn(spawnNumber, 0);
}
protected void doSpawn(int spawnNumber, int objectId) { // 再出現
L1NpcInstance mob = null;
try {
int newlocx = getLocX();
int newlocy = getLocY();
int tryCount = 0;
mob = NpcTable.getInstance().newNpcInstance(_template);
synchronized (_mobs) {
_mobs.add(mob);
}
if (objectId == 0) {
mob.setId(IdFactory.getInstance().nextId());
} else {
mob.setId(objectId); // オブジェクトID再利用
}
if (0 <= getHeading() && getHeading() <= 7) {
mob.setHeading(getHeading());
} else {
// heading値が正しくない
mob.setHeading(5);
}
int npcId = mob.getNpcTemplate().get_npcId();
if (npcId == 45488 && getMapId() == 9) { // カスパー
mob.setMap((short) (getMapId() + _random.nextInt(2)));
} else if (npcId == 45601 && getMapId() == 11) { // デスナイト
mob.setMap((short) (getMapId() + _random.nextInt(3)));
} else {
mob.setMap(getMapId());
}
mob.setMovementDistance(getMovementDistance());
mob.setRest(isRest());
while (tryCount <= 50) {
switch (getSpawnType()) {
case SPAWN_TYPE_PC_AROUND: // PC周辺に湧くタイプ
if (!_initSpawn) { // 初期配置では無条件に通常spawn
ArrayList<L1PcInstance> players = new ArrayList<L1PcInstance>();
for (L1PcInstance pc : L1World.getInstance()
.getAllPlayers()) {
if (getMapId() == pc.getMapId()) {
players.add(pc);
}
}
if (players.size() > 0) {
L1PcInstance pc = players.get(_random
.nextInt(players.size()));
L1Location loc = pc.getLocation().randomLocation(
PC_AROUND_DISTANCE, false);
newlocx = loc.getX();
newlocy = loc.getY();
break;
}
}
// フロアにPCがいなければ通常の出現方法
default:
if (isAreaSpawn()) { // 座標が範囲指定されている場合
Point pt = null;
if (_spawnHomePoint
&& null != (pt = _homePoint.get(spawnNumber))) { // ホームポイントを元に再出現させる場合
L1Location loc = new L1Location(pt, getMapId())
.randomLocation(
Config.SPAWN_HOME_POINT_RANGE,
false);
newlocx = loc.getX();
newlocy = loc.getY();
} else {
int rangeX = getLocX2() - getLocX1();
int rangeY = getLocY2() - getLocY1();
newlocx = _random.nextInt(rangeX) + getLocX1();
newlocy = _random.nextInt(rangeY) + getLocY1();
}
if (tryCount > 49) { // 出現位置が決まらない時はlocx,locyの値
newlocx = getLocX();
newlocy = getLocY();
}
} else if (isRandomSpawn()) { // 座標のランダム値が指定されている場合
newlocx = (getLocX() + ((int) (Math.random() * getRandomx()) - (int) (Math
.random() * getRandomx())));
newlocy = (getLocY() + ((int) (Math.random() * getRandomy()) - (int) (Math
.random() * getRandomy())));
} else { // どちらも指定されていない場合
newlocx = getLocX();
newlocy = getLocY();
}
}
mob.setX(newlocx);
mob.setHomeX(newlocx);
mob.setY(newlocy);
mob.setHomeY(newlocy);
if (mob.getMap().isInMap(mob.getLocation())
&& mob.getMap().isPassable(mob.getLocation())) {
if (mob instanceof L1MonsterInstance) {
if (isRespawnScreen()) {
break;
}
L1MonsterInstance mobtemp = (L1MonsterInstance) mob;
if (L1World.getInstance().getVisiblePlayer(mobtemp)
.size() == 0) {
break;
}
// 画面内にPCが居て出現できない場合は、3秒後にスケジューリングしてやり直し
SpawnTask task = new SpawnTask(spawnNumber, mob.getId());
GeneralThreadPool.getInstance().schedule(task, 3000L);
return;
}
}
tryCount++;
}
if (mob instanceof L1MonsterInstance) {
((L1MonsterInstance) mob).initHide();
}
mob.setSpawn(this);
mob.setreSpawn(true);
mob.setSpawnNumber(spawnNumber); // L1Spawnでの管理番号(ホームポイントに使用)
if (_initSpawn && _spawnHomePoint) { // 初期配置でホームポイントを設定
Point pt = new Point(mob.getX(), mob.getY());
_homePoint.put(spawnNumber, pt); // ここで保存したpointを再出現時に使う
}
if (mob instanceof L1MonsterInstance) {
if (mob.getMapId() == 666) {
((L1MonsterInstance) mob).set_storeDroped(true);
}
}
if (npcId == 45573 && mob.getMapId() == 2) { // バフォメット
for (L1PcInstance pc : L1World.getInstance().getAllPlayers()) {
if (pc.getMapId() == 2) {
L1Teleport.teleport(pc, 32664, 32797, (short) 2, 0,
true);
}
}
}
L1World.getInstance().storeObject(mob);
L1World.getInstance().addVisibleObject(mob);
if (mob instanceof L1MonsterInstance) {
L1MonsterInstance mobtemp = (L1MonsterInstance) mob;
if (!_initSpawn && mobtemp.getHiddenStatus() == 0) {
mobtemp.onNpcAI(); // モンスターのAIを開始
}
}
if (getGroupId() != 0) {
L1MobGroupSpawn.getInstance().doSpawn(mob, getGroupId(),
isRespawnScreen(), _initSpawn);
}
mob.turnOnOffLight();
mob.startChat(L1NpcInstance.CHAT_TIMING_APPEARANCE); // チャット開始
} catch (Exception e) {
_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
}
}
public void setRest(boolean flag) {
_rest = flag;
}
public boolean isRest() {
return _rest;
}
private static final int SPAWN_TYPE_NORMAL = 0;
private static final int SPAWN_TYPE_PC_AROUND = 1;
private static final int PC_AROUND_DISTANCE = 30;
private int getSpawnType() {
return _spawnType;
}
public void setSpawnType(int type) {
_spawnType = type;
}
private boolean isAreaSpawn() {
return getLocX1() != 0 && getLocY1() != 0 && getLocX2() != 0
&& getLocY2() != 0;
}
private boolean isRandomSpawn() {
return getRandomx() != 0 || getRandomy() != 0;
}
public L1SpawnTime getTime() {
return _time;
}
public void setTime(L1SpawnTime time) {
_time = time;
}
@Override
public void onMinuteChanged(L1GameTime time) {
if (_time.getTimePeriod().includes(time)) {
return;
}
synchronized (_mobs) {
if (_mobs.isEmpty()) {
return;
}
// 指定時間外になっていれば削除
for (L1NpcInstance mob : _mobs) {
mob.setCurrentHpDirect(0);
mob.setDead(true);
mob.setStatus(ActionCodes.ACTION_Die);
mob.deleteMe();
}
_mobs.clear();
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -