package tools.packet;
import client.status.MonsterStatus;
import client.status.MonsterStatusEffect;
import constants.GameConstants;
import handling.SendPacketOpcode;
import java.awt.Point;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import server.ServerProperties;
import server.life.MapleMonster;
import server.life.MobSkill;
import server.maps.MapleMap;
import server.maps.MapleNodes;
import server.movement.LifeMovementFragment;
import server.skill.冒险家.祭司;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
import tools.data.output.MaplePacketLittleEndianWriter;
public class MobPacket {
private static final Logger log = Logger.getLogger(MobPacket.class);
public static byte[] damageMonster(int oid, long damage) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.DAMAGE_MONSTER.getValue());
mplew.writeInt(oid);
mplew.write(0);
mplew.writeInt((int) damage);
return mplew.getPacket();
}
public static byte[] damageFriendlyMob(MapleMonster mob, long damage, boolean display) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.DAMAGE_MONSTER.getValue());
mplew.writeInt(mob.getObjectId());
mplew.write(display ? 1 : 2);
if (damage > 2147483647L) {
mplew.writeInt(2147483647);
} else {
mplew.writeInt((int) damage);
}
if (mob.getHp() > 2147483647L) {
mplew.writeInt((int) (mob.getHp() / mob.getMobMaxHp() * 2147483647.0D));
} else {
mplew.writeInt((int) mob.getHp());
}
if (mob.getMobMaxHp() > 2147483647L) {
mplew.writeInt(2147483647);
} else {
mplew.writeInt((int) mob.getMobMaxHp());
}
return mplew.getPacket();
}
/**
* 杀死怪物
* @param oid
* @param animation
* @return
*/
public static byte[] killMonster(int oid, int animation) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.KILL_MONSTER.getValue());
mplew.writeInt(oid);
mplew.write(animation);
return mplew.getPacket();
}
public static byte[] suckMonster(int oid, int chr) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.KILL_MONSTER.getValue());
mplew.writeInt(oid);
mplew.write(4);
mplew.writeInt(chr);
return mplew.getPacket();
}
public static byte[] healMonster(int oid, int heal) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.DAMAGE_MONSTER.getValue());
mplew.writeInt(oid);
mplew.write(0);
mplew.writeInt(-heal);
return mplew.getPacket();
}
public static byte[] MobToMobDamage(int oid, int dmg, int mobid) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.MOB_TO_MOB_DAMAGE.getValue());
mplew.writeInt(oid);
mplew.write(0);
mplew.writeInt(dmg);
mplew.writeInt(mobid);
mplew.write(1);
return mplew.getPacket();
}
public static byte[] getMobSkillEffect(int oid, int skillid, int cid, int skilllevel) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.SKILL_EFFECT_MOB.getValue());
mplew.writeInt(oid);
mplew.writeInt(skillid);
mplew.writeInt(cid);
mplew.writeShort(skilllevel);
return mplew.getPacket();
}
public static byte[] getMobCoolEffect(int oid, int itemid) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.ITEM_EFFECT_MOB.getValue());
mplew.writeInt(oid);
mplew.writeInt(itemid);
return mplew.getPacket();
}
public static byte[] showMonsterHP(int oid, int remhppercentage) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.SHOW_MONSTER_HP.getValue());
mplew.writeInt(oid);
mplew.write(remhppercentage);
return mplew.getPacket();
}
public static byte[] showCygnusAttack(int oid) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.CYGNUS_ATTACK.getValue());
mplew.writeInt(oid);
return mplew.getPacket();
}
public static byte[] showMonsterResist(int oid) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.MONSTER_RESIST.getValue());
mplew.writeInt(oid);
mplew.writeInt(0);
mplew.writeShort(1);
mplew.writeInt(0);
return mplew.getPacket();
}
public static byte[] showBossHP(MapleMonster mob) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.BOSS_ENV.getValue());
mplew.write(6);
mplew.writeInt(mob.getId() == 9400589 ? 9300184 : mob.getId());
if (mob.getHp() > 2147483647L) {
mplew.writeInt((int) (mob.getHp() / mob.getMobMaxHp() * 2147483647.0D));
} else {
mplew.writeInt((int) mob.getHp());
}
if (mob.getMobMaxHp() > 2147483647L) {
mplew.writeInt(2147483647);
} else {
mplew.writeInt((int) mob.getMobMaxHp());
}
mplew.write(mob.getStats().getTagColor());
mplew.write(mob.getStats().getTagBgColor());
return mplew.getPacket();
}
public static byte[] showBossHP(int monsterId, long currentHp, long maxHp) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.BOSS_ENV.getValue());
mplew.write(6);
mplew.writeInt(monsterId);
if (currentHp > 2147483647L) {
mplew.writeInt((int) (currentHp / maxHp * 2147483647.0D));
} else {
mplew.writeInt((int) (currentHp <= 0L ? -1L : currentHp));
}
if (maxHp > 2147483647L) {
mplew.writeInt(2147483647);
} else {
mplew.writeInt((int) maxHp);
}
mplew.write(6);
mplew.write(5);
return mplew.getPacket();
}
public static byte[] moveMonster(boolean useskill, SeekableLittleEndianAccessor slea, int skillId, int skillLevel, int delay, int oid, Point startPos, List<LifeMovementFragment> moves) {
return moveMonster(useskill, slea, skillId, skillLevel, oid);
}
/**
* 广播怪物移动
* @param useskill
* @param skillId
* @param skillLevel
* @param oid
* @return
*/
public static byte[] moveMonster(boolean useskill, SeekableLittleEndianAccessor slea,int skillId, int skillLevel, int oid) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.MOVE_MONSTER.getValue());
mplew.writeInt(oid);
mplew.write(useskill ? 1 : 0);
mplew.write(skillId);
mplew.writeInt(skillLevel);
mplew.write(slea.read((int)slea.available()));
mplew.writeLong(0);
return mplew.getPacket();
}
/**
* 召唤怪物
* @param life
* @param spawnType
* @param link
* @return
*/
public static byte[] spawnMonster(MapleMonster life, int spawnType, int link) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.SPAWN_MONSTER.getValue());
mplew.writeInt(life.getObjectId());
mplew.writeInt(life.getId());
mplew.writePos(life.getTruePosition());
mplew.write((life.getController() != null ? 0x08 : 0x02));
mplew.writeShort(life.getFh());
mplew.write(life.getStance());
// if (effect > 0) {
// mplew.write(effect);
// mplew.writeInt(life.getObjectId());
// }
mplew.write(spawnType);
mplew.write(1); // 召唤的时候特效,在wz中有对应的值
mplew.writeLong(10);
return mplew.getPacket();
}
public static byte[] controlMonster(MapleMonster life, boolean newSpawn, boolean aggro) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.SPAWN_MONSTER_CONTROL.getValue());
mplew.write(aggro ? 2 : 1);
mplew.writeInt(life.getObjectId());
mplew.writeInt(life.getId());
mplew.writePos(life.getTruePosition());
mplew.write(2);
mplew.writeShort(life.getFh());
mplew.write(life.getStance());
mplew.write(newSpawn ? -2 : life.isFake() ? -4 : -1);
mplew.write(0);
mplew.writeLong(0);
return mplew.getPacket();
}
public static byte[] stopControllingMonster(int oid) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.SPAWN_MONSTER_CONTROL.getValue());
mplew.write(0);
mplew.writeInt(oid);
return mplew.getPacket();
}
public static byte[] makeMonsterReal(MapleMonster life) {
return spawnMonster(life, -1, 0);
}
public static byte[] makeMonsterFake(MapleMonster life) {
return spawnMonster(life, -4, 0);
}
public static byte[] makeMonsterEffect(MapleMonster life, int effect) {
return spawnMonster(life, effect, 0);
}
public static byte[] moveMonsterResponse(int objectid, short moveid, int currentMp, boolean useSkills, int skillId, int skillLevel) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.MOVE_MONSTER_RESPONSE.getValue());
mplew.writeInt(objectid);
mplew.writeShort(moveid);
mplew.write(useSkills ? 1 : 0);
mplew.writeShort(currentMp);
mplew.write(skillId);
mplew.write(skillLevel);
return mplew.getPacket();
}
private static void getLongMask_NoRef(MaplePacketLittleEndianWriter mplew, Collection<MonsterStatusEffect> ss, boolean ignore_imm) {
int[] mask = new int[GameConstants.MAX_MONSTERSTATUS];
for (MonsterStatusEffect statup : ss) {
if ((statup != null) && ((!ignore_imm))) {
mask[(statup.getStati().getPosition() - 1)] |= statup.getStati().getValue();
}
}
for (int i = mask.length; i >= 1; i--) {
mplew.writeInt(mask[(i - 1)]);
}
}
public static byte[] applyMonsterStatus(int oid, MonsterStatus mse, int x, MobSkill skil,long buffTime) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.APPLY_MONSTER_STATUS.getValue());
mplew.writeInt(oid);
PacketHelper.writeMonsterStatusMask(mplew, mse);
mplew.writeInt(x);
mplew.writeShort(skil.getSkillId());
mplew.writeShort(skil.getSkillLevel());
mplew.writeShort((int)buffTime);
mplew.writeShort(0);
mplew.write(1);
mplew.write(1);
return mplew.getPacket();
}
public static byte[] applyMonsterStatus(MapleMonster mons, MonsterStatusEffect ms,long buffTime) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.APPLY_MONSTER_STATUS.getValue());
mplew.writeInt(mons.getObjectId());
PacketHelper.writeMonsterStatusMask(mplew, ms.getStati());
mplew.writeShort(ms.getX());
if (ms.isMonsterSkill()) {
mplew.writeShort(ms.getMobSkill().getSkillId());
mplew.writeShort(ms.getMobSkill().getSkillLevel());
} else if (ms.getSkill() > 0) {
mplew.writeInt(ms.getSkill());
}
mplew.writeShort((int)(buffTime/100));
mplew.writeShort(1); // delay in ms
return mplew.getPacket();
}
public static byte[] applyMonsterPoisonStatus(MapleMonster mons, List<MonsterStatusEffect> mse,int buffTime) {
if ((mse.size() <= 0) || (mse.get(0) == null)) {
return MaplePacketCreator.enableActions();
}
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.APPLY_MONSTER_STATUS.getValue());
mplew.writeInt(mons.getObjectId());
PacketHelper.writeMonsterStatusMask(mplew, MonsterStatus.中毒);
for (MonsterStatusEffect m : mse) {
mplew.writeShort(((Integer) m.getX())); // 效果值,减速多少,中毒扣血多少等
mplew.writeInt(m.getSkill());
mplew.writeShort((int)(buffTime/100)); // buffTime, this needs to be coded properly -- as a workaround, we'll use 100.
}
mplew.writeShort(1); // delay in ms
/*
mplew.write(SendPacketOpcode.APPLY_MONSTER_STATUS.getValue());
mplew.writeInt(mons.getObjectId());
MonsterStatusEffect ms = (MonsterStatusEffect) mse.get(0);
if (ms.getStati() == MonsterStatus.中毒) {
PacketHelper.writeMonsterStatusMask(mplew, MonsterStatus.中毒);
mplew.write(mse.size());
for (MonsterStatusEffect m : mse) {
mplew.writeInt(m.getFromID());
if (m.isMonsterSkill()) {
mplew.writeShort(m.getMobSkill().getSkillId());
mplew.writeShort(m.getMobSkill().getSkillLevel());
} else if (m.getSkill() > 0) {
mplew.writeInt(m.getSkill());
}
mplew.writeInt(m.getX());
mplew.writeInt(1000);
mplew.writeInt(0);
mplew.writeInt(10000);
mplew.writeInt((int) (m.getDotTime() / 1000L));
mplew.writeInt(0);
}
mplew.writeShort(1000);
mplew.write(1);
} else {
PacketHelper.writeSingleMask(mplew, ms.getStati());
mplew.writeInt(ms.getX());
if (ms.isMonsterSkill()) {
mplew.writeShort(ms.getMobSkill().getSkillId());
mplew.writeShort(ms.getMobSkill().getSkillLevel());
} else if (ms.getSkill() > 0) {
mplew.writeInt(ms.getSkill());
}
mplew.writeShort(0);
mplew.writeShort(0);
mplew.write(1);
mplew.write(1);
}
*/
return mplew.getPacket();
}
/**
* 给怪物加buff
* @param oid
* @param stati
* @param reflection
* @param skil
* @return
*/
public static byte[] applyMonsterStatus(int oid, Map<MonsterStatus, Integer> stati, List<Integer> reflection, MobSkill skil,long buffTime) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.APPLY_MONSTER_STATUS.getValue());
mplew.writeInt(oid);
PacketHelper.writeMonsterStatusMask(mplew, stati.keySet());
for (Map.Entry mse : stati.entrySet()) {
mplew.writeShort(((Integer) mse.getValue())); // 效果值,减速多少,中毒扣血多少等
mplew.writeInt(skil.getSkillId());
mplew.writeShort((int)(buffTime/100)); // buffTime, this needs to be coded properly -- as a workaround, we'll use 100.
}
mplew.writeShort(1); // delay in ms
return mplew.getPacket();
}
/**
* 取消怪物buff
* @param oid
* @param stat
* @return
*/
public static byte[] cancelMonsterStatus(int oid, MonsterStatus stat) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.CANCEL_MONSTER_STATUS.getValue());
mplew.writeInt(oid);
PacketHelper.writeMonsterStatusMask(mplew, stat);
return mplew.getPacket();
}
public static byte[] cancelMonsterPoisonStatus(int oid, MonsterStatusEffect m) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.CANCEL_MONSTER_STATUS.getValue());
mplew.writeInt(oid);
PacketHelper.writeMonsterStatusMask(mplew, MonsterStatus.中毒);
return mplew.getPacket();
}
public static byte[] getNodeProperties(MapleMonster objectid, MapleMap map) {
if (objectid.getNodePacket() != null) {
return objectid.getNodePacket();
}
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.MONSTER_PROPERTIES.getValue());
mplew.writeInt(objectid.getObjectId());
mplew.writeInt(map.getNodes().size());
mplew.writeInt(objectid.getPosition().x);
mplew.writeInt(objectid.getPosition().y);
for (MapleNodes.MapleNodeInfo mni : map.getNodes()) {
mplew.writeInt(mni.x);
mplew.writeInt(mni.y);
mplew.writeInt(mni.attr);
if (mni.attr == 2) {
mplew.writeInt(500);
}
}
mplew.writeZero(6);
objectid.setNodePacket(mplew.getPacket());
return objectid.getNodePacket();
}
public static byte[] catchMonster(int mobid, int itemid, byte success) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.CATCH_MONSTER.getValue());
mplew.writeInt(mobid);
mplew.writeInt(itemid);
mplew.write(success);
return mplew.getPacket();
}
public static byte[] catchMob(int mobid, int itemid, byte success) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(SendPacketOpcode.CATCH_MOB.getValue());
mplew.write(success);
mplew.writeInt(itemid);
mplew.writeInt(mobid);
return mplew.getPacket();
}
}