📄 l1monsterinstance.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.Instance;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.Random;
import l1j.server.Config;
import l1j.server.server.ActionCodes;
import l1j.server.server.GeneralThreadPool;
import l1j.server.server.datatables.DropTable;
import l1j.server.server.datatables.UBTable;
import l1j.server.server.model.L1Attack;
import l1j.server.server.model.L1Character;
import l1j.server.server.model.L1Location;
import l1j.server.server.model.L1NpcTalkData;
import l1j.server.server.model.L1Teleport;
import l1j.server.server.model.L1UltimateBattle;
import l1j.server.server.model.L1World;
import l1j.server.server.model.skill.L1SkillId;
import l1j.server.server.serverpackets.S_DoActionGFX;
import l1j.server.server.serverpackets.S_RemoveObject;
import l1j.server.server.serverpackets.S_NPCPack;
import l1j.server.server.serverpackets.S_ServerMessage;
import l1j.server.server.serverpackets.S_SkillBrave;
import l1j.server.server.templates.L1Npc;
import l1j.server.server.utils.CalcExp;
import l1j.server.server.datatables.NPCTalkDataTable;
import l1j.server.server.serverpackets.S_NPCTalkReturn;
public class L1MonsterInstance extends L1NpcInstance {
/**
*
*/
private static final long serialVersionUID = 1L;
private static l1j.eric.EricLogger _log = l1j.eric.EricLogger.getLogger2(L1MonsterInstance.class
.getName());
private static Random _random = new Random();
private boolean _storeDroped; // ドロップアイテムの読込が完了したか
// アイテム使用処理
@Override
public void onItemUse() {
if (!isActived() && _target != null) {
useItem(USEITEM_HASTE, 40); // 40%の確率でヘイストポーション使用
// アイテムじゃないけどドッペル処理
if (getNpcTemplate().is_doppel() && _target instanceof L1PcInstance) {
L1PcInstance targetPc = (L1PcInstance) _target;
setName(_target.getName());
setNameId(_target.getName());
setTitle(_target.getTitle());
setTempLawful(_target.getLawful());
// 變怪可直接攻擊 by 0919162173
// 刪除setTempCharGfx(targetPc.getClassId());
// 刪除setGfxId(targetPc.getClassId());
switch(targetPc.getClassId()) {
case 0: {
setTempCharGfx(5853);
setGfxId(5853);
}
break;
case 1: {
setTempCharGfx(5854);
setGfxId(5854);
}
break;
case 61: {
setTempCharGfx(5855);
setGfxId(5855);
}
break;
case 48: {
setTempCharGfx(5856);
setGfxId(5856);
}
break;
case 138: {
setTempCharGfx(5857);
setGfxId(5857);
}
break;
case 37: {
setTempCharGfx(5858);
setGfxId(5858);
}
break;
case 734: {
setTempCharGfx(5859);
setGfxId(5859);
}
break;
case 1186: {
setTempCharGfx(5860);
setGfxId(5860);
}
break;
case 2786: {
setTempCharGfx(5861);
setGfxId(5861);
}
break;
case 2796: {
setTempCharGfx(5862);
setGfxId(5862);
}
break;
}
//~變怪可直接攻擊 by 0919162173
setPassispeed(640);
setAtkspeed(900); // 正確な値がわからん
for (L1PcInstance pc : L1World.getInstance()
.getRecognizePlayer(this)) {
pc.sendPackets(new S_RemoveObject(this));
pc.removeKnownObject(this);
pc.updateObject();
}
}
}
if (getCurrentHp() * 100 / getMaxHp() < 40) { // HPが40%きったら
useItem(USEITEM_HEAL, 50); // 50%の確率で回復ポーション使用
}
}
@Override
public void onPerceive(L1PcInstance perceivedFrom) {
perceivedFrom.addKnownObject(this);
if (0 < getCurrentHp()) {
if (getHiddenStatus() == HIDDEN_STATUS_SINK) {
perceivedFrom.sendPackets(new S_DoActionGFX(getId(),
ActionCodes.ACTION_Hide));
} else if (getHiddenStatus() == HIDDEN_STATUS_FLY) {
perceivedFrom.sendPackets(new S_DoActionGFX(getId(),
ActionCodes.ACTION_Moveup));
}
perceivedFrom.sendPackets(new S_NPCPack(this));
onNpcAI(); // モンスターのAIを開始
if (getBraveSpeed() == 1) { // ちゃんとした方法がわからない
perceivedFrom.sendPackets(new S_SkillBrave(getId(), 1, 600000));
}
} else {
perceivedFrom.sendPackets(new S_NPCPack(this));
}
}
// ターゲットを探す
public static int[][] _classGfxId = { { 0, 1 }, { 48, 61 }, { 37, 138 },
{ 734, 1186 }, { 2786, 2796 } };
@Override
public void searchTarget() {
// ターゲット捜索
L1PcInstance targetPlayer = null;
for (L1PcInstance pc : L1World.getInstance().getVisiblePlayer(this)) {
if (pc.getCurrentHp() <= 0 || pc.isDead() || pc.isGm()
|| pc.isMonitor() || pc.isGhost()) {
continue;
}
// 闘技場内は変身/未変身に限らず全てアクティブ
int mapId = getMapId();
if (mapId == 88 || mapId == 98 || mapId == 92 || mapId == 91
|| mapId == 95) {
if (!pc.isInvisble() || getNpcTemplate().is_agrocoi()) { // インビジチェック
targetPlayer = pc;
break;
}
}
// どちらかの条件を満たす場合、友好と見なされ先制攻撃されない。
// モンスターのカルマがマイナス値(バルログ側モンスター)でPCのカルマレベルが1以上(バルログ友好)
// モンスターのカルマがプラス値(ヤヒ側モンスター)でPCのカルマレベルが-1以下(ヤヒ友好)
if ((getNpcTemplate().getKarma() < 0 && pc.getKarmaLevel() >= 1)
|| (getNpcTemplate().getKarma() > 0 && pc.getKarmaLevel() <= -1)) {
continue;
}
// 見棄てられた者たちの地 カルマクエストの変身中は、各陣営のモンスターから先制攻撃されない
if (pc.getTempCharGfx() == 6034 && getNpcTemplate().getKarma() < 0
|| pc.getTempCharGfx() == 6035 && getNpcTemplate().getKarma() > 0
|| pc.getTempCharGfx() == 6035 && getNpcTemplate().get_npcId() == 46070
|| pc.getTempCharGfx() == 6035 && getNpcTemplate().get_npcId() == 46072) {
continue;
}
if (!getNpcTemplate().is_agro() && !getNpcTemplate().is_agrososc()
&& getNpcTemplate().is_agrogfxid1() < 0
&& getNpcTemplate().is_agrogfxid2() < 0) { // 完全なノンアクティブモンスター
if (pc.getLawful() < -1000) { // プレイヤーがカオティック
targetPlayer = pc;
break;
}
continue;
}
if (!pc.isInvisble() || getNpcTemplate().is_agrocoi()) { // インビジチェック
if (pc.hasSkillEffect(67)) { // 変身してる
if (getNpcTemplate().is_agrososc()) { // 変身に対してアクティブ
targetPlayer = pc;
break;
}
} else if (getNpcTemplate().is_agro()) { // アクティブモンスター
targetPlayer = pc;
break;
}
// 特定のクラスorグラフィックIDにアクティブ
if (getNpcTemplate().is_agrogfxid1() >= 0
&& getNpcTemplate().is_agrogfxid1() <= 4) { // クラス指定
if (_classGfxId[getNpcTemplate().is_agrogfxid1()][0] == pc
.getTempCharGfx()
|| _classGfxId[getNpcTemplate().is_agrogfxid1()][1] == pc
.getTempCharGfx()) {
targetPlayer = pc;
break;
}
} else if (pc.getTempCharGfx() == getNpcTemplate()
.is_agrogfxid1()) { // グラフィックID指定
targetPlayer = pc;
break;
}
if (getNpcTemplate().is_agrogfxid2() >= 0
&& getNpcTemplate().is_agrogfxid2() <= 4) { // クラス指定
if (_classGfxId[getNpcTemplate().is_agrogfxid2()][0] == pc
.getTempCharGfx()
|| _classGfxId[getNpcTemplate().is_agrogfxid2()][1] == pc
.getTempCharGfx()) {
targetPlayer = pc;
break;
}
} else if (pc.getTempCharGfx() == getNpcTemplate()
.is_agrogfxid2()) { // グラフィックID指定
targetPlayer = pc;
break;
}
}
}
if (targetPlayer != null) {
_hateList.add(targetPlayer, 0);
_target = targetPlayer;
}
}
// リンクの設定
@Override
public void setLink(L1Character cha) {
if (cha != null && _hateList.isEmpty()) { // ターゲットがいない場合のみ追加
_hateList.add(cha, 0);
checkTarget();
}
}
public L1MonsterInstance(L1Npc template) {
super(template);
_storeDroped = false;
}
@Override
public void onNpcAI() {
if (isAiRunning()) {
return;
}
if (!_storeDroped) // 無駄なオブジェクトIDを発行しないようにここでセット
{
DropTable.getInstance().setDrop(this, getInventory());
getInventory().shuffle();
_storeDroped = true;
}
setActived(false);
startAI();
}
@Override
public void onTalkAction(L1PcInstance pc) {
int objid = getId();
L1NpcTalkData talking = NPCTalkDataTable.getInstance().getTemplate(
getNpcTemplate().get_npcId());
String htmlid = null;
String[] htmldata = null;
// html表示パケット送信
if (htmlid != null) { // htmlidが指定されている場合
if (htmldata != null) { // html指定がある場合は表示
pc.sendPackets(new S_NPCTalkReturn(objid, htmlid,
htmldata));
} else {
pc.sendPackets(new S_NPCTalkReturn(objid, htmlid));
}
} else {
if (pc.getLawful() < -1000) { // プレイヤーがカオティック
pc.sendPackets(new S_NPCTalkReturn(talking, objid, 2));
} else {
pc.sendPackets(new S_NPCTalkReturn(talking, objid, 1));
}
}
}
@Override
public void onAction(L1PcInstance pc) {
if (getCurrentHp() > 0 && !isDead()) {
L1Attack attack = new L1Attack(pc, this);
if (attack.calcHit()) {
attack.calcDamage();
attack.calcStaffOfMana();
attack.addPcPoisonAttack(pc, this);
}
attack.action();
attack.commit();
}
}
@Override
public void ReceiveManaDamage(L1Character attacker, int mpDamage) { // 攻撃でMPを減らすときはここを使用
if (mpDamage > 0 && !isDead()) {
// int Hate = mpDamage / 10 + 10; // 注意!計算適当 ダメージの10分の1+ヒットヘイト10
// setHate(attacker, Hate);
setHate(attacker, mpDamage);
onNpcAI();
if (attacker instanceof L1PcInstance) { // 仲間意識をもつモンスターのターゲットに設定
serchLink((L1PcInstance) attacker, getNpcTemplate()
.get_family());
}
int newMp = getCurrentMp() - mpDamage;
if (newMp < 0) {
newMp = 0;
}
setCurrentMp(newMp);
}
}
@Override
public void receiveDamage(L1Character attacker, int damage) { // 攻撃でHPを減らすときはここを使用
if (getCurrentHp() > 0 && !isDead()) {
if (getHiddenStatus() != HIDDEN_STATUS_NONE) {
return;
}
if (damage >= 0) {
if (!(attacker instanceof L1EffectInstance)) { // FWはヘイトなし
setHate(attacker, damage);
}
}
if (damage > 0) {
removeSkillEffect(L1SkillId.FOG_OF_SLEEPING);
}
onNpcAI();
if (attacker instanceof L1PcInstance) { // 仲間意識をもつモンスターのターゲットに設定
serchLink((L1PcInstance) attacker, getNpcTemplate()
.get_family());
}
if (attacker instanceof L1PcInstance && damage > 0) {
L1PcInstance player = (L1PcInstance) attacker;
player.setPetTarget(this);
if (getNpcTemplate().get_npcId() == 45681 // リンドビオル
|| getNpcTemplate().get_npcId() == 45682 // アンタラス
|| getNpcTemplate().get_npcId() == 45683 // パプリオン
|| getNpcTemplate().get_npcId() == 45684) // ヴァラカス
{
recall(player);
}
}
int newHp = getCurrentHp() - damage;
if (newHp <= 0 && !isDead()) {
int transformId = getNpcTemplate().getTransformId();
// 変身しないモンスター
if (transformId == -1) {
setCurrentHpDirect(0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -