📄 l1character.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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Logger;
import l1j.server.server.model.Instance.L1DollInstance;
import l1j.server.server.model.Instance.L1FollowerInstance;
import l1j.server.server.model.Instance.L1ItemInstance;
import l1j.server.server.model.Instance.L1NpcInstance;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.model.map.L1Map;
import l1j.server.server.model.poison.L1Poison;
import l1j.server.server.model.skill.L1SkillId;
import l1j.server.server.model.skill.L1SkillTimer;
import l1j.server.server.model.skill.L1SkillTimerCreator;
import l1j.server.server.serverpackets.S_Light;
import l1j.server.server.serverpackets.S_RemoveObject;
import l1j.server.server.serverpackets.S_Poison;
import l1j.server.server.serverpackets.ServerBasePacket;
import l1j.server.server.types.Point;
import l1j.server.server.utils.IntRange;
// Referenced classes of package l1j.server.server.model:
// L1Object, Die, L1PcInstance, L1MonsterInstance,
// L1World, ActionFailed
public class L1Character extends L1Object {
private static final long serialVersionUID = 1L;
private static final Logger _log = Logger.getLogger(L1Character.class
.getName());
private L1Poison _poison = null;
private boolean _paralyzed;
private boolean _sleeped;
private final Map<Integer, L1NpcInstance> _petlist = new HashMap<Integer, L1NpcInstance>();
private final Map<Integer, L1DollInstance> _dolllist = new HashMap<Integer, L1DollInstance>();
private final Map<Integer, L1SkillTimer> _skillEffect = new HashMap<Integer, L1SkillTimer>();
private final Map<Integer, L1ItemDelay.ItemDelayTimer> _itemdelay = new HashMap<Integer, L1ItemDelay.ItemDelayTimer>();
private final Map<Integer, L1FollowerInstance> _followerlist = new HashMap<Integer, L1FollowerInstance>();
public L1Character() {
_level = 1;
}
/**
* キャラクターを復活させる。
*
* @param hp
* 復活後のHP
*/
public void resurrect(int hp) {
if (!isDead()) {
return;
}
if (hp <= 0) {
hp = 1;
}
setCurrentHp(hp);
setDead(false);
setStatus(0);
L1PolyMorph.undoPoly(this);
for (L1PcInstance pc : L1World.getInstance().getRecognizePlayer(this)) {
pc.sendPackets(new S_RemoveObject(this));
pc.removeKnownObject(this);
pc.updateObject();
}
}
private int _currentHp;
/**
* キャラクターの現在のHPを返す。
*
* @return 現在のHP
*/
public int getCurrentHp() {
return _currentHp;
}
/**
* キャラクターのHPを設定する。
*
* @param i
* キャラクターの新しいHP
*/
// 特殊な処理がある場合はこっちをオーバライド(パケット送信等)
public void setCurrentHp(int i) {
_currentHp = i;
if (_currentHp >= getMaxHp()) {
_currentHp = getMaxHp();
}
}
/**
* キャラクターのHPを設定する。
*
* @param i
* キャラクターの新しいHP
*/
public void setCurrentHpDirect(int i) {
_currentHp = i;
}
private int _currentMp;
/**
* キャラクターの現在のMPを返す。
*
* @return 現在のMP
*/
public int getCurrentMp() {
return _currentMp;
}
/**
* キャラクターのMPを設定する。
*
* @param i
* キャラクターの新しいMP
*/
// 特殊な処理がある場合はこっちをオーバライド(パケット送信等)
public void setCurrentMp(int i) {
_currentMp = i;
if (_currentMp >= getMaxMp()) {
_currentMp = getMaxMp();
}
}
/**
* キャラクターのMPを設定する。
*
* @param i
* キャラクターの新しいMP
*/
public void setCurrentMpDirect(int i) {
_currentMp = i;
}
/**
* キャラクターの眠り状態を返す。
*
* @return 眠り状態を表す値。眠り状態であればtrue。
*/
public boolean isSleeped() {
return _sleeped;
}
/**
* キャラクターの眠り状態を設定する。
*
* @param sleeped
* 眠り状態を表す値。眠り状態であればtrue。
*/
public void setSleeped(boolean sleeped) {
_sleeped = sleeped;
}
/**
* キャラクターの麻痺状態を返す。
*
* @return 麻痺状態を表す値。麻痺状態であればtrue。
*/
public boolean isParalyzed() {
return _paralyzed;
}
/**
* キャラクターの麻痺状態を設定する。
*
* @param i
* 麻痺状態を表す値。麻痺状態であればtrue。
*/
public void setParalyzed(boolean paralyzed) {
_paralyzed = paralyzed;
}
L1Paralysis _paralysis;
public L1Paralysis getParalysis() {
return _paralysis;
}
public void setParalaysis(L1Paralysis p) {
_paralysis = p;
}
public void cureParalaysis() {
if (_paralysis != null) {
_paralysis.cure();
}
}
/**
* キャラクターの可視範囲に居るプレイヤーへ、パケットを送信する。
*
* @param packet
* 送信するパケットを表すServerBasePacketオブジェクト。
*/
public void broadcastPacket(ServerBasePacket packet) {
for (L1PcInstance pc : L1World.getInstance().getVisiblePlayer(this)) {
pc.sendPackets(packet);
}
}
/**
* キャラクターの可視範囲に居るプレイヤーへ、パケットを送信する。 ただしターゲットの画面内には送信しない。
*
* @param packet
* 送信するパケットを表すServerBasePacketオブジェクト。
*/
public void broadcastPacketExceptTargetSight(ServerBasePacket packet,
L1Character target) {
for (L1PcInstance pc : L1World.getInstance()
.getVisiblePlayerExceptTargetSight(this, target)) {
pc.sendPackets(packet);
}
}
/**
* キャラクターの50マス以内に居るプレイヤーへ、パケットを送信する。
*
* @param packet
* 送信するパケットを表すServerBasePacketオブジェクト。
*/
public void wideBroadcastPacket(ServerBasePacket packet) {
for (L1PcInstance pc : L1World.getInstance().getVisiblePlayer(this,
50)) {
pc.sendPackets(packet);
}
}
/**
* キャラクターの正面の座標を返す。
*
* @return 正面の座標
*/
public int[] getFrontLoc() {
int[] loc = new int[2];
int x = getX();
int y = getY();
int heading = getHeading();
if (heading == 0) {
y--;
} else if (heading == 1) {
x++;
y--;
} else if (heading == 2) {
x++;
} else if (heading == 3) {
x++;
y++;
} else if (heading == 4) {
y++;
} else if (heading == 5) {
x--;
y++;
} else if (heading == 6) {
x--;
} else if (heading == 7) {
x--;
y--;
}
loc[0] = x;
loc[1] = y;
return loc;
}
/**
* 指定された座標に対する方向を返す。
*
* @param tx
* 座標のX値
* @param ty
* 座標のY値
* @return 指定された座標に対する方向
*/
public int targetDirection(int tx, int ty) {
float dis_x = Math.abs(getX() - tx); // X方向のターゲットまでの距離
float dis_y = Math.abs(getY() - ty); // Y方向のターゲットまでの距離
float dis = Math.max(dis_x, dis_y); // ターゲットまでの距離
if (dis == 0) {
return getHeading(); // 同じ位置ならいま向いてる方向を返しとく
}
int avg_x = (int) Math.floor((dis_x / dis) + 0.59f); // 上下左右がちょっと優先な丸め
int avg_y = (int) Math.floor((dis_y / dis) + 0.59f); // 上下左右がちょっと優先な丸め
int dir_x = 0;
int dir_y = 0;
if (getX() < tx) {
dir_x = 1;
}
if (getX() > tx) {
dir_x = -1;
}
if (getY() < ty) {
dir_y = 1;
}
if (getY() > ty) {
dir_y = -1;
}
if (avg_x == 0) {
dir_x = 0;
}
if (avg_y == 0) {
dir_y = 0;
}
if (dir_x == 1 && dir_y == -1) {
return 1; // 上
}
if (dir_x == 1 && dir_y == 0) {
return 2; // 右上
}
if (dir_x == 1 && dir_y == 1) {
return 3; // 右
}
if (dir_x == 0 && dir_y == 1) {
return 4; // 右下
}
if (dir_x == -1 && dir_y == 1) {
return 5; // 下
}
if (dir_x == -1 && dir_y == 0) {
return 6; // 左下
}
if (dir_x == -1 && dir_y == -1) {
return 7; // 左
}
if (dir_x == 0 && dir_y == -1) {
return 0; // 左上
}
return getHeading(); // ここにはこない。はず
}
/**
* 指定された座標までの直線上に、障害物が存在*しないか*を返す。
*
* @param tx
* 座標のX値
* @param ty
* 座標のY値
* @return 障害物が無ければtrue、あればfalseを返す。
*/
public boolean glanceCheck(int tx, int ty) {
L1Map map = getMap();
int chx = getX();
int chy = getY();
int arw = 0;
for (int i = 0; i < 15; i++) {
if ((chx == tx && chy == ty) || (chx + 1 == tx && chy - 1 == ty)
|| (chx + 1 == tx && chy == ty)
|| (chx + 1 == tx && chy + 1 == ty)
|| (chx == tx && chy + 1 == ty)
|| (chx - 1 == tx && chy + 1 == ty)
|| (chx - 1 == tx && chy == ty)
|| (chx - 1 == tx && chy - 1 == ty)
|| (chx == tx && chy - 1 == ty)) {
break;
} else if (chx < tx && chy == ty) {
// if (!map.isArrowPassable(chx, chy, 2)) {
if (!map.isArrowPassable(chx, chy, targetDirection(tx, ty))) {
return false;
}
chx++;
} else if (chx == tx && chy < ty) {
// if (!map.isArrowPassable(chx, chy, 4)) {
if (!map.isArrowPassable(chx, chy, targetDirection(tx, ty))) {
return false;
}
chy++;
} else if (chx > tx && chy == ty) {
// if (!map.isArrowPassable(chx, chy, 6)) {
if (!map.isArrowPassable(chx, chy, targetDirection(tx, ty))) {
return false;
}
chx--;
} else if (chx == tx && chy > ty) {
// if (!map.isArrowPassable(chx, chy, 0)) {
if (!map.isArrowPassable(chx, chy, targetDirection(tx, ty))) {
return false;
}
chy--;
} else if (chx < tx && chy > ty) {
// if (!map.isArrowPassable(chx, chy, 1)) {
if (!map.isArrowPassable(chx, chy, targetDirection(tx, ty))) {
return false;
}
chx++;
chy--;
} else if (chx < tx && chy < ty) {
// if (!map.isArrowPassable(chx, chy, 3)) {
if (!map.isArrowPassable(chx, chy, targetDirection(tx, ty))) {
return false;
}
chx++;
chy++;
} else if (chx > tx && chy < ty) {
// if (!map.isArrowPassable(chx, chy, 5)) {
if (!map.isArrowPassable(chx, chy, targetDirection(tx, ty))) {
return false;
}
chx--;
chy++;
} else if (chx > tx && chy > ty) {
// if (!map.isArrowPassable(chx, chy, 7)) {
if (!map.isArrowPassable(chx, chy, targetDirection(tx, ty))) {
return false;
}
chx--;
chy--;
}
}
if (arw == 0) {
return true;
} else {
return false;
}
}
/**
* 指定された座標へ攻撃可能であるかを返す。
*
* @param x
* 座標のX値。
* @param y
* 座標のY値。
* @param range
* 攻撃可能な範囲(タイル数)
* @return 攻撃可能であればtrue,不可能であればfalse
*/
public boolean isAttackPosition(int x, int y, int range) {
if (range >= 7) // 遠隔武器(7以上の場合斜めを考慮すると画面外に出る)
{
if (getLocation().getTileDistance(new Point(x, y)) > range) {
return false;
}
} else // 近接武器
{
if (getLocation().getTileLineDistance(new Point(x, y)) > range) {
return false;
}
}
return glanceCheck(x, y);
}
/**
* キャラクターのインベントリを返す。
*
* @return キャラクターのインベントリを表す、L1Inventoryオブジェクト。
*/
public L1Inventory getInventory() {
return null;
}
/**
* キャラクターへ、新たにスキル效果を追加する。
*
* @param skillId
* 追加する效果のスキルID。
* @param timeMillis
* 追加する效果の持続時間。無限の場合は0。
*/
private void addSkillEffect(int skillId, int timeMillis) {
L1SkillTimer timer = null;
if (0 < timeMillis) {
timer = L1SkillTimerCreator.create(this, skillId, timeMillis);
timer.begin();
}
_skillEffect.put(skillId, timer);
}
/**
* キャラクターへ、スキル效果を設定する。<br>
* 重複するスキルがない場合は、新たにスキル效果を追加する。<br>
* 重複するスキルがある場合は、残り效果時間とパラメータの效果時間の長い方を優先して設定する。
*
* @param skillId
* 設定する效果のスキルID。
* @param timeMillis
* 設定する效果の持続時間。無限の場合は0。
*/
public void setSkillEffect(int skillId, int timeMillis) {
if (hasSkillEffect(skillId)) {
int remainingTimeMills = getSkillEffectTimeSec(skillId) * 1000;
// 残り時間が有限で、パラメータの效果時間の方が長いか無限の場合は上書きする。
if (remainingTimeMills >= 0
&& (remainingTimeMills < timeMillis || timeMillis == 0)) {
killSkillEffectTimer(skillId);
addSkillEffect(skillId, timeMillis);
}
} else {
addSkillEffect(skillId, timeMillis);
}
}
/**
* キャラクターから、スキル效果を削除する。
*
* @param skillId
* 削除する效果のスキルID
*/
public void removeSkillEffect(int skillId) {
L1SkillTimer timer = _skillEffect.remove(skillId);
if (timer != null) {
timer.end();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -