package javastory.channel.packet; import java.awt.Point; import java.util.Collection; import java.util.List; import java.util.Map; import javastory.channel.client.MonsterStatus; import javastory.channel.client.MonsterStatusEffect; import javastory.channel.life.Monster; import javastory.channel.movement.LifeMovementFragment; import javastory.io.GamePacket; import javastory.io.PacketBuilder; import javastory.server.handling.ServerPacketOpcode; public class MobPacket { public static GamePacket damageMonster(final int oid, final int damage) { final PacketBuilder builder = new PacketBuilder(); builder.writeAsShort(ServerPacketOpcode.DAMAGE_MONSTER.getValue()); builder.writeInt(oid); builder.writeAsByte(0); builder.writeInt(damage); return builder.getPacket(); } public static GamePacket damageFriendlyMob(final Monster mob, final int damage) { final PacketBuilder builder = new PacketBuilder(); builder.writeAsShort(ServerPacketOpcode.DAMAGE_MONSTER.getValue()); builder.writeInt(mob.getObjectId()); builder.writeAsByte(1); builder.writeInt(damage); builder.writeInt(mob.getHp()); builder.writeInt(mob.getMobMaxHp()); return builder.getPacket(); } public static GamePacket killMonster(final int oid, final int animation) { final PacketBuilder builder = new PacketBuilder(); builder.writeAsShort(ServerPacketOpcode.KILL_MONSTER.getValue()); builder.writeInt(oid); builder.writeAsByte(animation); // 0 = dissapear, 1 = fade out, 2+ = // special return builder.getPacket(); } public static GamePacket healMonster(final int oid, final int heal) { final PacketBuilder builder = new PacketBuilder(); builder.writeAsShort(ServerPacketOpcode.DAMAGE_MONSTER.getValue()); builder.writeInt(oid); builder.writeAsByte(1); builder.writeInt(-heal); return builder.getPacket(); } public static GamePacket showMonsterHP(final int oid, final int remhppercentage) { final PacketBuilder builder = new PacketBuilder(); builder.writeAsShort(ServerPacketOpcode.SHOW_MONSTER_HP.getValue()); builder.writeInt(oid); builder.writeAsByte(remhppercentage); return builder.getPacket(); } public static GamePacket showBossHP(final Monster mob) { final PacketBuilder builder = new PacketBuilder(); builder.writeAsShort(ServerPacketOpcode.BOSS_ENV.getValue()); builder.writeAsByte(5); builder.writeInt(mob.getId()); builder.writeInt(mob.getHp()); builder.writeInt(mob.getMobMaxHp()); builder.writeByte(mob.getStats().getTagColor()); builder.writeByte(mob.getStats().getTagBgColor()); return builder.getPacket(); } public static GamePacket moveMonster(final boolean useskill, final int skill, final int skill1, final int skill2, final int skill3, final int skill4, final int oid, final Point startPos, final List<LifeMovementFragment> moves) { final PacketBuilder builder = new PacketBuilder(); builder.writeAsShort(ServerPacketOpcode.MOVE_MONSTER.getValue()); builder.writeInt(oid); builder.writeAsShort(0); builder.writeAsByte(useskill ? 1 : 0); builder.writeAsByte(skill); builder.writeAsByte(skill1); builder.writeAsByte(skill2); builder.writeAsByte(skill3); builder.writeAsByte(skill4); builder.writeZeroBytes(8); builder.writeVector(startPos); builder.writeInt(4275593); serializeMovementList(builder, moves); return builder.getPacket(); } private static void serializeMovementList(final PacketBuilder builder, final List<LifeMovementFragment> moves) { builder.writeAsByte(moves.size()); for (final LifeMovementFragment move : moves) { move.serialize(builder); } } public static GamePacket spawnMonster(final Monster life, final int spawnType, final int effect, final int link) { final PacketBuilder builder = new PacketBuilder(); builder.writeAsShort(ServerPacketOpcode.SPAWN_MONSTER.getValue()); builder.writeInt(life.getObjectId()); builder.writeAsByte(1); // 1 = Control normal, 5 = Control none builder.writeInt(life.getId()); builder.writeZeroBytes(15); builder.writeAsByte(0x88); builder.writeZeroBytes(6); builder.writeAsShort(life.getPosition().x); builder.writeAsShort(life.getPosition().y); builder.writeAsByte(life.getStance()); builder.writeAsShort(0); // FH builder.writeAsShort(life.getFoothold()); // Origin FH if (effect != 0 || link != 0) { builder.writeAsByte(effect != 0 ? effect : -3); builder.writeInt(link); } else { if (spawnType == 0) { builder.writeAsByte(effect); builder.writeAsByte(0); builder.writeAsShort(0); } builder.writeAsByte(spawnType); // newSpawn ? -2 : -1 } builder.writeByte(life.getCarnivalTeam()); builder.writeInt(0); return builder.getPacket(); } public static GamePacket controlMonster(final Monster life, final boolean newSpawn, final boolean aggro) { final PacketBuilder builder = new PacketBuilder(); builder.writeAsShort(ServerPacketOpcode.SPAWN_MONSTER_CONTROL.getValue()); builder.writeAsByte(aggro ? 2 : 1); builder.writeInt(life.getObjectId()); builder.writeAsByte(1); // 1 = Control normal, 5 = Control none builder.writeInt(life.getId()); builder.writeZeroBytes(15); builder.writeAsByte(0x88); builder.writeZeroBytes(6); builder.writeAsShort(life.getPosition().x); builder.writeAsShort(life.getPosition().y); builder.writeAsByte(life.getStance()); // Bitfield builder.writeAsShort(0); // FH builder.writeAsShort(life.getFoothold()); // Origin FH builder.writeAsByte(life.isFake() ? 0xfc : newSpawn ? -2 : -1); builder.writeByte(life.getCarnivalTeam()); builder.writeInt(0); return builder.getPacket(); } public static GamePacket stopControllingMonster(final int oid) { final PacketBuilder builder = new PacketBuilder(); builder.writeAsShort(ServerPacketOpcode.SPAWN_MONSTER_CONTROL.getValue()); builder.writeAsByte(0); builder.writeInt(oid); return builder.getPacket(); } public static GamePacket makeMonsterInvisible(final Monster life) { final PacketBuilder builder = new PacketBuilder(); builder.writeAsShort(ServerPacketOpcode.SPAWN_MONSTER_CONTROL.getValue()); builder.writeAsByte(0); builder.writeInt(life.getObjectId()); return builder.getPacket(); } public static GamePacket makeMonsterReal(final Monster life) { final PacketBuilder builder = new PacketBuilder(); builder.writeAsShort(ServerPacketOpcode.SPAWN_MONSTER.getValue()); builder.writeInt(life.getObjectId()); builder.writeAsByte(1); // 1 = Control normal, 5 = Control none builder.writeInt(life.getId()); builder.writeZeroBytes(15); // Added on v.82 MSEA builder.writeAsByte(0x88); builder.writeZeroBytes(6); builder.writeAsShort(life.getPosition().x); builder.writeAsShort(life.getPosition().y); builder.writeAsByte(life.getStance()); builder.writeAsShort(0); // FH builder.writeAsShort(life.getFoothold()); // Origin FH builder.writeAsShort(-1); builder.writeInt(0); return builder.getPacket(); } public static GamePacket moveMonsterResponse(final int objectid, final short moveid, final int currentMp, final boolean useSkills, final int skillId, final int skillLevel) { final PacketBuilder builder = new PacketBuilder(); builder.writeAsShort(ServerPacketOpcode.MOVE_MONSTER_RESPONSE.getValue()); builder.writeInt(objectid); builder.writeAsShort(moveid); builder.writeAsByte(useSkills ? 1 : 0); builder.writeAsShort(currentMp); builder.writeAsByte(skillId); builder.writeAsByte(skillLevel); return builder.getPacket(); } private static long getSpecialLongMask(final Collection<MonsterStatus> statups) { long mask = 0; for (final MonsterStatus statup : statups) { if (statup.isFirst()) { mask |= statup.getValue(); } } return mask; } private static long getLongMask(final Collection<MonsterStatus> statups) { long mask = 0; for (final MonsterStatus statup : statups) { if (!statup.isFirst()) { mask |= statup.getValue(); } } return mask; } private static void writeIntMask(final PacketBuilder builder, final Map<MonsterStatus, Integer> stats) { builder.writeLong(getSpecialLongMask(stats.keySet())); builder.writeLong(getLongMask(stats.keySet())); } public static GamePacket applyMonsterStatus(final int oid, final MonsterStatusEffect mse) { final PacketBuilder builder = new PacketBuilder(); builder.writeAsShort(ServerPacketOpcode.APPLY_MONSTER_STATUS.getValue()); builder.writeInt(oid); writeIntMask(builder, mse.getEffects()); for (final Map.Entry<MonsterStatus, Integer> stat : mse.getEffects().entrySet()) { builder.writeAsShort(stat.getValue()); if (mse.isMonsterSkill()) { builder.writeAsShort(mse.getMobSkill().getSkillId()); builder.writeAsShort(mse.getMobSkill().getSkillLevel()); } else { builder.writeInt(mse.getSkill().getId()); } builder.writeAsShort(0); // might actually be the buffTime but it's // not displayed anywhere } builder.writeAsShort(0); // delay in ms builder.writeAsByte(mse.getEffects().size()); // size builder.writeAsByte(1); return builder.getPacket(); } public static GamePacket applyMonsterStatus(final int oid, final MonsterStatusEffect mse, final List<Integer> reflection) { final PacketBuilder builder = new PacketBuilder(); builder.writeAsShort(ServerPacketOpcode.APPLY_MONSTER_STATUS.getValue()); builder.writeInt(oid); writeIntMask(builder, mse.getEffects()); for (final Map.Entry<MonsterStatus, Integer> stat : mse.getEffects().entrySet()) { builder.writeAsShort(stat.getValue()); if (mse.isMonsterSkill()) { builder.writeAsShort(mse.getMobSkill().getSkillId()); builder.writeAsShort(mse.getMobSkill().getSkillLevel()); } else { builder.writeInt(mse.getSkill().getId()); } builder.writeAsShort(0); // might actually be the buffTime but it's // not displayed anywhere } for (final Integer ref : reflection) { builder.writeInt(ref); } builder.writeInt(0); builder.writeAsShort(0); // delay in ms int size = mse.getEffects().size(); // size if (reflection.size() > 0) { size /= 2; // This gives 2 buffs per reflection but it's really one // buff } builder.writeAsByte(size); // size builder.writeAsByte(1); return builder.getPacket(); } public static GamePacket cancelMonsterStatus(final int oid, final Map<MonsterStatus, Integer> stats) { final PacketBuilder builder = new PacketBuilder(); builder.writeAsShort(ServerPacketOpcode.CANCEL_MONSTER_STATUS.getValue()); builder.writeInt(oid); writeIntMask(builder, stats); builder.writeAsByte(1); // reflector is 3~!?? builder.writeAsByte(2); return builder.getPacket(); } }