Skillbook announcer update + Encoded temporary mob buffs + Slot gains patch

Encoded temporary mob buffs on mob control request/spawn packets.
Improved scroll generator NPC, now testing other bucket set possibilities.
Fixed slot gain method recently updated leading to a temporary visual glitch (inventory would show as normal after relogin).
Reviewed mobid check by name, no longer trying to generate a whole mob instance for info retrieval.
Added debuff purge when applying a buyback.
Reviewed skillbook announcer not informing properly storybooks, reactor or script loots.
Fixed autoaggro not working properly as soon as a player enters the field.
Fixed "fake" mobs disappearing as soon as its controller changes.
This commit is contained in:
ronancpl
2019-12-24 20:11:32 -03:00
parent 959d990ab8
commit 07fe495bfd
34 changed files with 211 additions and 143 deletions

View File

@@ -144,7 +144,6 @@ import client.processor.action.PetAutopotProcessor;
import constants.game.ExpTable;
import constants.game.GameConstants;
import constants.inventory.ItemConstants;
import constants.net.ServerConstants;
import constants.skills.Aran;
import constants.skills.Beginner;
import constants.skills.Bishop;
@@ -2819,7 +2818,14 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
dispelDebuff(MapleDisease.WEAKEN);
dispelDebuff(MapleDisease.SLOW); // thanks Conrad for noticing ZOMBIFY isn't dispellable
}
public void purgeDebuffs() {
dispelDebuff(MapleDisease.SEDUCE);
dispelDebuff(MapleDisease.ZOMBIFY);
dispelDebuff(MapleDisease.CONFUSE);
dispelDebuffs();
}
public void cancelAllDebuffs() {
chrLock.lock();
try {
@@ -9420,26 +9426,27 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
}
public boolean gainSlots(int type, int slots, boolean update) {
boolean ret = gainSlotsInternal(type, slots, update);
if (ret) {
int newLimit = gainSlotsInternal(type, slots);
if (newLimit != -1) {
this.saveCharToDB();
if (update) {
client.announce(MaplePacketCreator.updateInventorySlotLimit(type, slots));
client.announce(MaplePacketCreator.updateInventorySlotLimit(type, newLimit));
}
return true;
} else {
return false;
}
return ret;
}
private boolean gainSlotsInternal(int type, int slots, boolean update) {
private int gainSlotsInternal(int type, int slots) {
inventory[type].lockInventory();
try {
if (canGainSlots(type, slots)) {
slots += inventory[type].getSlotLimit();
inventory[type].setSlotLimit(slots);
return true;
int newLimit = inventory[type].getSlotLimit() + slots;
inventory[type].setSlotLimit(newLimit);
return newLimit;
} else {
return false;
return -1;
}
} finally {
inventory[type].unlockInventory();
@@ -10652,6 +10659,12 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
client = null; // clients still triggers handlers a few times after disconnecting
map = null;
setListener(null);
// thanks Shavit for noticing a memory leak with inventories holding owner object
for (int i = 0; i < inventory.length; i++) {
inventory[i].dispose();
}
inventory = null;
}
}, 5 * 60 * 1000);
}

View File

@@ -33,7 +33,7 @@ public class DisposeCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
NPCScriptManager.getInstance().dispose(c);
@@ -41,5 +41,5 @@ public class DisposeCommand extends Command {
c.announce(MaplePacketCreator.enableActions());
c.removeClickedNPC();
c.getPlayer().message("You've been disposed.");
}
}
}

View File

@@ -25,7 +25,6 @@ package client.command.commands.gm0;
import client.MapleClient;
import client.command.Command;
import constants.net.ServerConstants;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

View File

@@ -29,7 +29,6 @@ import client.MapleClient;
import server.MapleItemInformationProvider;
import server.life.MapleMonsterInformationProvider;
import server.life.MonsterDropEntry;
import tools.MaplePacketCreator;
import tools.Pair;
import java.util.Iterator;

View File

@@ -25,14 +25,12 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
@@ -672,4 +670,8 @@ public class MapleInventory implements Iterable<Item> {
public void unlockInventory() {
lock.unlock();
}
public void dispose() {
owner = null;
}
}

View File

@@ -70,6 +70,7 @@ public class BuybackProcessor {
}
chr.healHpMp();
chr.purgeDebuffs();
chr.broadcastStance(chr.isFacingLeft() ? 5 : 4);
MapleMap map = chr.getMap();

View File

@@ -179,6 +179,7 @@ public class ServerConfig {
public int MOB_STATUS_MONITOR_LIFE;
public int MOB_STATUS_AGGRO_PERSISTENCE;
public int MOB_STATUS_AGGRO_INTERVAL;
public boolean USE_AUTOAGGRO_NEARBY;
//Some Gameplay Enhancing Configurations
//Scroll Configuration

View File

@@ -12,6 +12,7 @@ public class ServerConstants {
public static int DEBUG_VALUES[] = new int[10]; // Field designed for packet testing purposes
// https://github.com/openstreetmap/josm/blob/a3a6e8a6b657cf4c5b4c64ea14d6e87be6280d65/src/org/openstreetmap/josm/tools/Utils.java#L1566-L1585
// Added by kolakcc (Familiar)
/**
* Returns the Java version as an int value.
* @return the Java version as an int value (8, 9, etc.)

View File

@@ -25,7 +25,6 @@ import config.YamlConfig;
import net.server.guild.MapleGuildResponse;
import net.server.guild.MapleGuild;
import constants.game.GameConstants;
import constants.net.ServerConstants;
import client.MapleClient;
import net.AbstractMaplePacketHandler;
import tools.data.input.SeekableLittleEndianAccessor;

View File

@@ -31,7 +31,6 @@ import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
import client.MapleCharacter;
import client.MapleClient;
import constants.net.ServerConstants;
import net.server.coordinator.world.MapleInviteCoordinator;
import net.server.coordinator.world.MapleInviteCoordinator.InviteResult;
import net.server.coordinator.world.MapleInviteCoordinator.InviteType;

View File

@@ -58,13 +58,13 @@ public final class PlayerMapTransitionHandler extends AbstractMaplePacketHandler
if (m.getController() == chr) {
c.announce(MaplePacketCreator.stopControllingMonster(m.getObjectId()));
m.sendDestroyData(c);
m.aggroRedirectController();
m.aggroRemoveController();
} else {
m.sendDestroyData(c);
}
m.aggroSwitchController(chr, false);
m.sendSpawnData(c);
m.aggroSwitchController(chr, false);
}
}
}

View File

@@ -354,7 +354,7 @@ public class MapleMatchCheckerCoordinator {
if (mmce != null) {
synchronized (mmce) {
if (!mmce.isMatchActive()) { // thanks Alex (CanIGetaPR) for noticing that exploiters could stall on match checking
if (!mmce.isMatchActive()) { // thanks Alex (Alex-0000) for noticing that exploiters could stall on match checking
matchEntries.remove(cid);
mmce = null;
} else {

View File

@@ -27,7 +27,7 @@ import net.server.PlayerStorage;
/**
* @author Ronan
*/
public class CharacterAutosaverTask extends BaseTask implements Runnable { // thanks Alex (Alex09) for noticing these runnable classes are tasks, "workers" runs them
public class CharacterAutosaverTask extends BaseTask implements Runnable { // thanks Alex09 (Alex-0000) for noticing these runnable classes are tasks, "workers" runs them
@Override
public void run() {

View File

@@ -28,7 +28,6 @@ import java.sql.SQLException;
import client.MapleJob;
import config.YamlConfig;
import tools.DatabaseConnection;
import constants.net.ServerConstants;
import net.server.Server;
/**

View File

@@ -60,7 +60,6 @@ import client.inventory.MaplePet;
import constants.game.GameConstants;
import constants.inventory.ItemConstants;
import constants.string.LanguageConstants;
import net.server.PlayerStorage;
import net.server.channel.Channel;
import net.server.coordinator.matchchecker.MatchCheckerListenerFactory.MatchCheckerType;
import server.MapleMarriage;
@@ -603,6 +602,12 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
switch (sbe) {
case UNAVAILABLE:
return "";
case REACTOR:
return " Obtainable through #rexploring#k (loot boxes).";
case SCRIPT:
return " Obtainable through #rexploring#k (field interaction).";
case QUEST_BOOK:
return " Obtainable through #rquestline#k (collecting book).";
@@ -633,7 +638,7 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
for (int i = 0; i < 6; i++) {
if (fieldTaken(i)) {
if (fieldLobbied(i)) {
msg += "#b#L" + i + "#Carnival Field " + (i + 1) + " (Level: " // "Carnival field" GMS-like improvement thanks to Jayd
msg += "#b#L" + i + "#Carnival Field " + (i + 1) + " (Level: " // "Carnival field" GMS-like improvement thanks to Jayd (jaydenseah)
+ cpqCalcAvgLvl(980000100 + i * 100) + " / "
+ getPlayerCount(980000100 + i * 100) + "x"
+ getPlayerCount(980000100 + i * 100) + ") #l\r\n";

View File

@@ -49,7 +49,6 @@ import client.inventory.ItemFactory;
import client.inventory.MapleInventoryType;
import client.inventory.MaplePet;
import constants.inventory.ItemConstants;
import constants.net.ServerConstants;
import java.util.Collections;
import net.server.audit.locks.MonitoredLockType;

View File

@@ -60,7 +60,6 @@ import client.inventory.Item;
import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType;
import client.inventory.MapleWeaponType;
import constants.net.ServerConstants;
import constants.inventory.EquipSlot;
import constants.inventory.ItemConstants;
import constants.skills.Assassin;
@@ -2117,7 +2116,7 @@ public class MapleItemInformationProvider {
ResultSet rs = ps.executeQuery();
while(rs.next()) {
String resultName = MapleMonsterInformationProvider.getInstance().getMobNameFromId(rs.getInt("dropperid"));
if (resultName != null) {
if (!resultName.isEmpty()) {
list.add(resultName);
}
}

View File

@@ -65,18 +65,11 @@ public class MapleSkillbookInformationProvider {
SCRIPT
}
private static String host = "jdbc:mysql://localhost:3306/heavenms";
private static String driver = "com.mysql.jdbc.Driver";
private static String username = "root";
private static String password = "";
private static String rootDirectory = ".";
private static int skillbookMinItemid = 2280000;
private static int skillbookMaxItemid = 2300000; // exclusively
private static Set<Integer> questSkills = new HashSet<>();
static {
loadSkillbooks();
}
@@ -156,7 +149,13 @@ public class MapleSkillbookInformationProvider {
int skillid = MapleDataTool.getInt("id", questSkillData, 0);
if (is4thJobSkill(skillid)) {
// negative itemids are skill rewards
foundSkillbooks.put(-skillid, SkillBookEntry.QUEST_REWARD);
int questbook = fetchQuestbook(checkData, questData.getName());
if (questbook < 0) {
foundSkillbooks.put(-skillid, SkillBookEntry.QUEST_REWARD);
} else {
foundSkillbooks.put(-skillid, SkillBookEntry.QUEST_BOOK);
}
}
}
}

View File

@@ -958,10 +958,7 @@ public class MapleStatEffect {
if (isDispel() && makeChanceResult()) {
applyto.dispelDebuffs();
} else if (isCureAllAbnormalStatus()) {
applyto.dispelDebuff(MapleDisease.SEDUCE);
applyto.dispelDebuff(MapleDisease.ZOMBIFY);
applyto.dispelDebuff(MapleDisease.CONFUSE);
applyto.dispelDebuffs();
applyto.purgeDebuffs();
} else if (isComboReset()) {
applyto.setCombo((short) 0);
}

View File

@@ -36,7 +36,6 @@ import client.inventory.MapleInventoryType;
import client.inventory.manipulator.MapleInventoryManipulator;
import client.inventory.manipulator.MapleKarmaManipulator;
import constants.game.GameConstants;
import constants.net.ServerConstants;
import net.server.coordinator.world.MapleInviteCoordinator;
import net.server.coordinator.world.MapleInviteCoordinator.InviteResult;
import net.server.coordinator.world.MapleInviteCoordinator.InviteType;

View File

@@ -1040,23 +1040,6 @@ public class MapleMonster extends AbstractLoadedMapleLife {
return isBoss() && getTagColor() > 0;
}
public void broadcastMonsterStatus() {
Collection<MonsterStatusEffect> mseList = this.getStati().values();
for (MapleCharacter chr : map.getAllPlayers()) {
announceMonsterStatusInternal(chr.getClient(), mseList);
}
}
public void announceMonsterStatus(MapleClient client) {
announceMonsterStatusInternal(client, this.getStati().values());
}
public void announceMonsterStatusInternal(MapleClient client, Collection<MonsterStatusEffect> mseList) {
for (MonsterStatusEffect mse : mseList) {
client.announce(MaplePacketCreator.applyMonsterStatus(getObjectId(), mse, null));
}
}
@Override
public void sendSpawnData(MapleClient client) {
if (hp.get() <= 0) { // mustn't monsterLock this function
@@ -1068,8 +1051,6 @@ public class MapleMonster extends AbstractLoadedMapleLife {
client.announce(MaplePacketCreator.spawnMonster(this, false));
}
announceMonsterStatus(client);
if (hasBossHPBar()) {
client.announceBossHpBar(this, this.hashCode(), makeBossHPBarPacket());
}
@@ -1934,7 +1915,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
* Removes controllability status from the current controller of this mob.
*
*/
private Pair<MapleCharacter, Boolean> aggroRemoveController() {
public Pair<MapleCharacter, Boolean> aggroRemoveController() {
MapleCharacter chrController;
boolean hadAggro;
@@ -1951,7 +1932,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
}
if (chrController != null) { // this can/should only happen when a hidden gm attacks the monster
chrController.announce(MaplePacketCreator.stopControllingMonster(this.getObjectId()));
if (!this.isFake()) chrController.announce(MaplePacketCreator.stopControllingMonster(this.getObjectId()));
chrController.stopControllingMonster(this);
}
@@ -2123,9 +2104,12 @@ public class MapleMonster extends AbstractLoadedMapleLife {
MapleCharacter chrController = this.getActiveController();
if (chrController == null) {
this.aggroSwitchController(player, true);
this.aggroSwitchController(player, true);
} else if (chrController.getId() == player.getId()) {
this.setControllerHasAggro(true);
if (!YamlConfig.config.server.USE_AUTOAGGRO_NEARBY) { // thanks Lichtmager for noticing autoaggro not updating the player properly
aggroMonsterControl(player.getClient(), this, true);
}
}
}
@@ -2164,9 +2148,6 @@ public class MapleMonster extends AbstractLoadedMapleLife {
private static void aggroMonsterControl(MapleClient c, MapleMonster mob, boolean immediateAggro) {
c.announce(MaplePacketCreator.controlMonster(mob, false, immediateAggro));
// thanks BHB for noticing puppets disrupting mobstatuses for bowmans
mob.announceMonsterStatus(c);
}
private void aggroRefreshPuppetVisibility(MapleCharacter chrController, MapleSummon puppet) {
@@ -2185,7 +2166,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
chrController.announce(MaplePacketCreator.removeSummon(puppet, false));
MapleClient c = chrController.getClient();
for (MapleMonster mob : puppetControlled) {
for (MapleMonster mob : puppetControlled) { // thanks BHB for noticing puppets disrupting mobstatuses for bowmans
aggroMonsterControl(c, mob, mob.isControllerKnowsAboutAggro());
}
chrController.announce(MaplePacketCreator.spawnSummon(puppet, false));

View File

@@ -316,16 +316,10 @@ public class MapleMonsterInformationProvider {
public String getMobNameFromId(int id) {
String mobName = mobNameCache.get(id);
if (mobName == null) {
try {
mobName = MapleLifeFactory.getMonster(id).getName();
} catch (NullPointerException npe) {
mobName = ""; //nonexistant mob
} catch (Exception e) {
e.printStackTrace();
System.err.println("Nonexistant mob id " + id);
mobName = ""; //nonexistant mob
}
MapleDataProvider dataProvider = MapleDataProviderFactory.getDataProvider(new File("wz/String.wz"));
MapleData mobData = dataProvider.getData("Mob.img");
mobName = MapleDataTool.getString(mobData.getChildByPath(id + "/name"), "");
mobNameCache.put(id, mobName);
}

View File

@@ -44,7 +44,6 @@ import client.MapleClient;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import constants.game.GameConstants;
import constants.net.ServerConstants;
import net.server.Server;
import net.server.channel.Channel;
import net.server.world.World;

View File

@@ -19,7 +19,6 @@
*/
package server.life;
import constants.net.ServerConstants;
import java.io.File;
import java.util.HashMap;
import java.util.Map;

View File

@@ -413,18 +413,6 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
this.removeOwner(c.getPlayer());
try {
MapleCharacter player = c.getWorldServer().getPlayerStorage().getCharacterById(ownerId);
if(player != null) {
player.setHasMerchant(false);
} else {
Connection con = DatabaseConnection.getConnection();
try (PreparedStatement ps = con.prepareStatement("UPDATE characters SET HasMerchant = 0 WHERE id = ?", Statement.RETURN_GENERATED_KEYS)) {
ps.setInt(1, ownerId);
ps.executeUpdate();
}
con.close();
}
List<MaplePlayerShopItem> copyItems = getItems();
if (check(c.getPlayer(), copyItems) && !timeout) {
for (MaplePlayerShopItem mpsi : copyItems) {
@@ -448,6 +436,19 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
e.printStackTrace();
}
// thanks Rohenn for noticing a possible dupe scenario on closing shop
MapleCharacter player = c.getWorldServer().getPlayerStorage().getCharacterById(ownerId);
if(player != null) {
player.setHasMerchant(false);
} else {
Connection con = DatabaseConnection.getConnection();
try (PreparedStatement ps = con.prepareStatement("UPDATE characters SET HasMerchant = 0 WHERE id = ?", Statement.RETURN_GENERATED_KEYS)) {
ps.setInt(1, ownerId);
ps.executeUpdate();
}
con.close();
}
if (YamlConfig.config.server.USE_ENFORCE_MERCHANT_SAVE) {
c.getPlayer().saveCharToDB(false);
}

View File

@@ -2017,7 +2017,7 @@ public class MapleMap {
if (getEventInstance() != null) {
getEventInstance().registerMonster(monster);
}
spawnAndAddRangedMapObject(monster, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
@@ -2108,7 +2108,7 @@ public class MapleMap {
c.announce(MaplePacketCreator.spawnFakeMonster(monster, 0));
}
});
spawnedMonstersOnMap.incrementAndGet();
addSelfDestructive(monster);
}
@@ -2116,7 +2116,6 @@ public class MapleMap {
public void makeMonsterReal(final MapleMonster monster) {
monster.setFake(false);
broadcastMessage(MaplePacketCreator.makeMonsterReal(monster));
monster.broadcastMonsterStatus();
monster.aggroUpdateController();
updateBossSpawn(monster);
}
@@ -3081,8 +3080,6 @@ public class MapleMap {
for (MapleMapObject o : objects) {
if (isNonRangedType(o.getType())) {
o.sendSpawnData(c);
} else if (o.getType() == MapleMapObjectType.MONSTER) {
((MapleMonster) o).aggroUpdateController();
} else if (o.getType() == MapleMapObjectType.SUMMON) {
MapleSummon summon = (MapleSummon) o;
if (summon.getOwner() == chr) {
@@ -3110,6 +3107,10 @@ public class MapleMap {
} else {
o.sendSpawnData(chr.getClient());
chr.addVisibleMapObject(o);
if (o.getType() == MapleMapObjectType.MONSTER) {
((MapleMonster) o).aggroUpdateController();
}
}
}
}

View File

@@ -1486,6 +1486,43 @@ public class MaplePacketCreator {
mplew.write(newSpawn ? -2 : -1);
}
private static void encodeTemporary(MaplePacketLittleEndianWriter mplew, Map<MonsterStatus, MonsterStatusEffect> stati) {
int pCounter = -1, mCounter = -1;
writeLongEncodeTemporaryMask(mplew, stati.keySet()); // packet structure mapped thanks to Eric
for (Entry<MonsterStatus, MonsterStatusEffect> s : stati.entrySet()) {
MonsterStatusEffect mse = s.getValue();
mplew.writeShort(mse.getStati().get(s.getKey()));
MobSkill mobSkill = mse.getMobSkill();
if (mobSkill != null) {
mplew.writeShort(mobSkill.getSkillId());
mplew.writeShort(mobSkill.getSkillLevel());
switch(s.getKey()) {
case WEAPON_REFLECT:
pCounter = mobSkill.getX();
break;
case MAGIC_REFLECT:
mCounter = mobSkill.getY();
break;
}
} else {
Skill skill = mse.getSkill();
mplew.writeInt(skill != null ? skill.getId() : 0);
}
mplew.writeShort(-1); // duration
}
// reflect packet structure found thanks to Arnah (Vertisy)
if(pCounter != -1) mplew.writeInt(pCounter);// wPCounter_
if(mCounter != -1) mplew.writeInt(mCounter);// wMCounter_
if(pCounter != -1 || mCounter != -1) mplew.writeInt(100);// nCounterProb_
}
/**
* Internal function to handler monster spawning and controlling.
*
@@ -1513,9 +1550,13 @@ public class MaplePacketCreator {
mplew.writeInt(life.getObjectId());
mplew.write(life.getController() == null ? 5 : 1);
mplew.writeInt(life.getId());
mplew.skip(15);
mplew.write(0x88);
mplew.skip(6);
if (requestController) {
encodeTemporary(mplew, life.getStati()); // thanks shot for noticing encode temporary buffs missing
} else {
mplew.skip(16);
}
mplew.writePos(life.getPosition());
mplew.write(life.getStance());
mplew.writeShort(0); //Origin FH //life.getStartFh()
@@ -1561,9 +1602,7 @@ public class MaplePacketCreator {
mplew.writeInt(life.getObjectId());
mplew.write(5);
mplew.writeInt(life.getId());
mplew.skip(15);
mplew.write(0x88);
mplew.skip(6);
encodeTemporary(mplew, life.getStati());
mplew.writePos(life.getPosition());
mplew.write(life.getStance());
mplew.writeShort(0);//life.getStartFh()
@@ -1591,9 +1630,7 @@ public class MaplePacketCreator {
mplew.writeInt(life.getObjectId());
mplew.write(5);
mplew.writeInt(life.getId());
mplew.skip(15);
mplew.write(0x88);
mplew.skip(6);
encodeTemporary(mplew, life.getStati());
mplew.writePos(life.getPosition());
mplew.write(life.getStance());
mplew.writeShort(0);//life.getStartFh()
@@ -3151,6 +3188,21 @@ public class MaplePacketCreator {
mplew.writeLong(firstmask);
mplew.writeLong(secondmask);
}
private static void writeLongEncodeTemporaryMask(final MaplePacketLittleEndianWriter mplew, Collection<MonsterStatus> stati) {
int masks[] = new int[4];
for (MonsterStatus statup : stati) {
int pos = statup.isFirst() ? 0 : 2;
for (int i = 0; i < 2; i++) {
masks[pos + i] |= statup.getValue() >> 32 * i;
}
}
for (int i = 0; i < masks.length; i++) {
mplew.writeInt(masks[i]);
}
}
public static byte[] cancelDebuff(long mask) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(19);
@@ -4137,30 +4189,6 @@ public class MaplePacketCreator {
mplew.writeInt(secondmask);
}
public static byte[] applyMonsterStatus(int oid, Map<MonsterStatus, Integer> stats, int skill, boolean monsterSkill, int delay, MobSkill mobskill) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.APPLY_MONSTER_STATUS.getValue());
mplew.writeInt(oid);
int mask = 0;
for (MonsterStatus stat : stats.keySet()) {
mask |= stat.getValue();
}
mplew.writeInt(mask);
for (Integer val : stats.values()) {
mplew.writeShort(val);
if (monsterSkill) {
mplew.writeShort(mobskill.getSkillId());
mplew.writeShort(mobskill.getSkillLevel());
} else {
mplew.writeInt(skill);
}
mplew.writeShort(0); // as this looks similar to giveBuff this
}
mplew.writeShort(delay); // delay in ms
mplew.write(1); // ?
return mplew.getPacket();
}
public static byte[] applyMonsterStatus(final int oid, final MonsterStatusEffect mse, final List<Integer> reflection) {
Map<MonsterStatus, Integer> stati = mse.getStati();
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();

View File

@@ -23,7 +23,6 @@ import client.MapleCharacter;
import config.YamlConfig;
import constants.game.GameConstants;
import constants.inventory.ItemConstants;
import constants.net.ServerConstants;
import server.MapleItemInformationProvider;
import tools.MaplePacketCreator;