Poison/slow update + Map-persistent diseases + Selling zero-qty rechs.
Rebalanced CafePQ rewards. Rebalanced drop chance of some equipments and HT drops with high rates. Fixed an weird issue where a "Targa hat" would appear as a debuff effect. Added visual effect to be displayed to other players when the custom "Chair Mastery" skill is being used. Slow disease is now visible to other players. Poison damage now displays the correct damage amount to other players. Disease status are now visible for other players when changing maps. Fixed recharging price being accounted incorrectly. Fixed zero-quantity rechargeables not being able to sell at NPC shops.
This commit is contained in:
@@ -134,7 +134,7 @@ public class BuddyList {
|
||||
for(int bid : getBuddyIds()) {
|
||||
MapleCharacter chr = pstorage.getCharacterById(bid);
|
||||
|
||||
if(chr != null && chr.isLoggedin() && !chr.isAwayFromWorld()) {
|
||||
if(chr != null && chr.isLoggedinWorld()) {
|
||||
chr.announce(packet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,7 +257,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
private Map<Integer, MapleKeyBinding> keymap = new LinkedHashMap<>();
|
||||
private Map<Integer, MapleSummon> summons = new LinkedHashMap<>();
|
||||
private Map<Integer, MapleCoolDownValueHolder> coolDowns = new LinkedHashMap<>();
|
||||
private EnumMap<MapleDisease, MapleDiseaseValueHolder> diseases = new EnumMap<>(MapleDisease.class);
|
||||
private EnumMap<MapleDisease, Pair<MapleDiseaseValueHolder, MobSkill>> diseases = new EnumMap<>(MapleDisease.class);
|
||||
private Map<Integer, MapleDoor> doors = new LinkedHashMap<>();
|
||||
private Map<MapleQuest, Long> questExpirations = new LinkedHashMap<>();
|
||||
private ScheduledFuture<?> dragonBloodSchedule;
|
||||
@@ -428,6 +428,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public boolean isLoggedinWorld() {
|
||||
return this.isLoggedin() && !this.isAwayFromWorld();
|
||||
}
|
||||
|
||||
public boolean isAwayFromWorld() {
|
||||
return awayFromWorld.get();
|
||||
}
|
||||
@@ -2042,16 +2046,17 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
}
|
||||
|
||||
public Map<MapleDisease, Long> getAllDiseases() {
|
||||
public Map<MapleDisease, Pair<Long, MobSkill>> getAllDiseases() {
|
||||
chrLock.lock();
|
||||
try {
|
||||
long curtime = System.currentTimeMillis();
|
||||
Map<MapleDisease, Long> ret = new LinkedHashMap<>();
|
||||
Map<MapleDisease, Pair<Long, MobSkill>> ret = new LinkedHashMap<>();
|
||||
|
||||
for(Entry<MapleDisease, Long> de : diseaseExpires.entrySet()) {
|
||||
MapleDiseaseValueHolder mdvh = diseases.get(de.getKey());
|
||||
Pair<MapleDiseaseValueHolder, MobSkill> dee = diseases.get(de.getKey());
|
||||
MapleDiseaseValueHolder mdvh = dee.getLeft();
|
||||
|
||||
ret.put(de.getKey(), mdvh.length - (curtime - mdvh.startTime));
|
||||
ret.put(de.getKey(), new Pair<>(mdvh.length - (curtime - mdvh.startTime), dee.getRight()));
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -2060,16 +2065,36 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
}
|
||||
|
||||
public void silentApplyDiseases(Map<MapleDisease, Long> diseaseMap) {
|
||||
public void silentApplyDiseases(Map<MapleDisease, Pair<Long, MobSkill>> diseaseMap) {
|
||||
chrLock.lock();
|
||||
try {
|
||||
long curTime = System.currentTimeMillis();
|
||||
|
||||
for(Entry<MapleDisease, Long> di : diseaseMap.entrySet()) {
|
||||
long expTime = curTime + di.getValue();
|
||||
for(Entry<MapleDisease, Pair<Long, MobSkill>> di : diseaseMap.entrySet()) {
|
||||
long expTime = curTime + di.getValue().getLeft();
|
||||
|
||||
diseaseExpires.put(di.getKey(), expTime);
|
||||
diseases.put(di.getKey(), new MapleDiseaseValueHolder(curTime, expTime));
|
||||
diseases.put(di.getKey(), new Pair<>(new MapleDiseaseValueHolder(curTime, expTime), di.getValue().getRight()));
|
||||
}
|
||||
} finally {
|
||||
chrLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void announceDiseases(MapleClient c) {
|
||||
chrLock.lock();
|
||||
try {
|
||||
// Poison damage visibility and diseases status visibility, extended through map transitions thanks to Ronan
|
||||
|
||||
if(!this.isLoggedinWorld()) return;
|
||||
|
||||
for(Entry<MapleDisease, Pair<MapleDiseaseValueHolder, MobSkill>> di : diseases.entrySet()) {
|
||||
MapleDisease disease = di.getKey();
|
||||
MobSkill skill = di.getValue().getRight();
|
||||
final List<Pair<MapleDisease, Integer>> debuff = Collections.singletonList(new Pair<>(disease, Integer.valueOf(skill.getX())));
|
||||
|
||||
if(disease != MapleDisease.SLOW) c.announce(MaplePacketCreator.giveForeignDebuff(id, debuff, skill));
|
||||
else c.announce(MaplePacketCreator.giveForeignSlowDebuff(id, debuff, skill));
|
||||
}
|
||||
} finally {
|
||||
chrLock.unlock();
|
||||
@@ -2088,14 +2113,16 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
try {
|
||||
long curTime = System.currentTimeMillis();
|
||||
diseaseExpires.put(disease, curTime + skill.getDuration());
|
||||
diseases.put(disease, new MapleDiseaseValueHolder(curTime, skill.getDuration()));
|
||||
diseases.put(disease, new Pair<>(new MapleDiseaseValueHolder(curTime, skill.getDuration()), skill));
|
||||
} finally {
|
||||
chrLock.unlock();
|
||||
}
|
||||
|
||||
final List<Pair<MapleDisease, Integer>> debuff = Collections.singletonList(new Pair<>(disease, Integer.valueOf(skill.getX())));
|
||||
client.announce(MaplePacketCreator.giveDebuff(debuff, skill));
|
||||
map.broadcastMessage(this, MaplePacketCreator.giveForeignDebuff(id, debuff, skill), false);
|
||||
|
||||
if(disease != MapleDisease.SLOW) map.broadcastMessage(this, MaplePacketCreator.giveForeignDebuff(id, debuff, skill), false);
|
||||
else map.broadcastMessage(this, MaplePacketCreator.giveForeignSlowDebuff(id, debuff, skill), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2103,7 +2130,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
if (hasDisease(debuff)) {
|
||||
long mask = debuff.getValue();
|
||||
announce(MaplePacketCreator.cancelDebuff(mask));
|
||||
map.broadcastMessage(this, MaplePacketCreator.cancelForeignDebuff(id, mask), false);
|
||||
|
||||
if(debuff != MapleDisease.SLOW) map.broadcastMessage(this, MaplePacketCreator.cancelForeignDebuff(id, mask), false);
|
||||
else map.broadcastMessage(this, MaplePacketCreator.cancelForeignSlowDebuff(id), false);
|
||||
|
||||
chrLock.lock();
|
||||
try {
|
||||
@@ -3022,10 +3051,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
cancelEffect(ii.getItemEffect(itemId), false, -1);
|
||||
}
|
||||
|
||||
public void cancelEffect(MapleStatEffect effect, boolean overwrite, long startTime) {
|
||||
public boolean cancelEffect(MapleStatEffect effect, boolean overwrite, long startTime) {
|
||||
effLock.lock();
|
||||
try {
|
||||
cancelEffect(effect, overwrite, startTime, true);
|
||||
return cancelEffect(effect, overwrite, startTime, true);
|
||||
} finally {
|
||||
effLock.unlock();
|
||||
}
|
||||
@@ -3068,10 +3097,12 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
}
|
||||
|
||||
private void cancelEffect(MapleStatEffect effect, boolean overwrite, long startTime, boolean firstCancel) {
|
||||
private boolean cancelEffect(MapleStatEffect effect, boolean overwrite, long startTime, boolean firstCancel) {
|
||||
Set<MapleBuffStat> removedStats = new LinkedHashSet<>();
|
||||
dropBuffStats(cancelEffectInternal(effect, overwrite, startTime, removedStats));
|
||||
updateEffects(removedStats);
|
||||
|
||||
return !removedStats.isEmpty();
|
||||
}
|
||||
|
||||
private List<Pair<MapleBuffStat, MapleBuffStatValueHolder>> cancelEffectInternal(MapleStatEffect effect, boolean overwrite, long startTime, Set<MapleBuffStat> removedStats) {
|
||||
@@ -3480,26 +3511,31 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterChairBuff() {
|
||||
if(!ServerConstants.USE_CHAIR_EXTRAHEAL) return;
|
||||
public boolean unregisterChairBuff() {
|
||||
if(!ServerConstants.USE_CHAIR_EXTRAHEAL) return false;
|
||||
|
||||
int skillId = getJobMapChair(job);
|
||||
int skillLv = getSkillLevel(skillId);
|
||||
if(skillLv > 0) {
|
||||
MapleStatEffect mapChairSkill = SkillFactory.getSkill(skillId).getEffect(skillLv);
|
||||
cancelEffect(mapChairSkill, false, -1);
|
||||
return cancelEffect(mapChairSkill, false, -1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void registerChairBuff() {
|
||||
if(!ServerConstants.USE_CHAIR_EXTRAHEAL) return;
|
||||
public boolean registerChairBuff() {
|
||||
if(!ServerConstants.USE_CHAIR_EXTRAHEAL) return false;
|
||||
|
||||
int skillId = getJobMapChair(job);
|
||||
int skillLv = getSkillLevel(skillId);
|
||||
if(skillLv > 0) {
|
||||
MapleStatEffect mapChairSkill = SkillFactory.getSkill(skillId).getEffect(skillLv);
|
||||
mapChairSkill.applyTo(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getChair() {
|
||||
@@ -4216,7 +4252,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
try {
|
||||
if(party != null) {
|
||||
for(MaplePartyCharacter partyMembers: party.getMembers()) {
|
||||
if(partyMembers.getPlayer().getMap().hashCode() == thisMapHash) list.add(partyMembers.getPlayer());
|
||||
MapleCharacter chr = partyMembers.getPlayer();
|
||||
if(chr.getMap().hashCode() == thisMapHash && chr.isLoggedinWorld()) list.add(chr);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
@@ -7240,16 +7277,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
|
||||
if (quantity <= iQuant && iQuant > 0) {
|
||||
MapleInventoryManipulator.removeFromSlot(c, type, (byte) slot, quantity, false);
|
||||
double price;
|
||||
int itemid = item.getItemId();
|
||||
if (ItemConstants.isRechargable(itemid)) {
|
||||
price = ii.getWholePrice(itemid) / (double) ii.getSlotMax(c, itemid);
|
||||
} else {
|
||||
price = ii.getPrice(itemid);
|
||||
}
|
||||
|
||||
int recvMesos = (int) Math.max(Math.ceil(price * quantity), 0);
|
||||
if (price != -1 && recvMesos > 0) {
|
||||
int recvMesos = ii.getPrice(itemid, quantity);
|
||||
if (recvMesos > 0) {
|
||||
gainMeso(recvMesos, false);
|
||||
return(recvMesos);
|
||||
}
|
||||
@@ -7722,6 +7752,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
public void sendSpawnData(MapleClient client) {
|
||||
if (!this.isHidden() || client.getPlayer().gmLevel() > 1) {
|
||||
client.announce(MaplePacketCreator.spawnPlayerMapObject(this));
|
||||
|
||||
if(hasBuffFromSourceid(getJobMapChair(job))) {
|
||||
client.announce(MaplePacketCreator.giveForeignChairSkillEffect(id));
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isHidden()) {
|
||||
|
||||
@@ -1256,7 +1256,7 @@ public class MapleClient {
|
||||
}
|
||||
|
||||
public synchronized void announce(final byte[] packet) {//MINA CORE IS A FUCKING BITCH AND I HATE IT <3
|
||||
session.write(packet);
|
||||
session.write(packet);
|
||||
}
|
||||
|
||||
public void announceHint(String msg, int length) {
|
||||
|
||||
@@ -1764,7 +1764,7 @@ public class Commands {
|
||||
} else if(sub.length == 2) {
|
||||
statUpdate = Integer.valueOf(sub[1]);
|
||||
} else {
|
||||
player.yellowMessage("Syntax: !sethpmp [<playername>] <value>");
|
||||
player.yellowMessage("Syntax: !hpmp [<playername>] <value>");
|
||||
}
|
||||
|
||||
if(victim != null) {
|
||||
@@ -1779,6 +1779,41 @@ public class Commands {
|
||||
}
|
||||
break;
|
||||
|
||||
case "maxhpmp":
|
||||
victim = player;
|
||||
statUpdate = 1;
|
||||
|
||||
if (sub.length >= 3) {
|
||||
victim = c.getWorldServer().getPlayerStorage().getCharacterByName(sub[1]);
|
||||
statUpdate = Integer.valueOf(sub[2]);
|
||||
} else if(sub.length == 2) {
|
||||
statUpdate = Integer.valueOf(sub[1]);
|
||||
} else {
|
||||
player.yellowMessage("Syntax: !maxhpmp [<playername>] <value>");
|
||||
}
|
||||
|
||||
if(victim != null) {
|
||||
if(victim.getHp() > statUpdate) {
|
||||
victim.setHp(statUpdate);
|
||||
victim.updateSingleStat(MapleStat.HP, statUpdate);
|
||||
}
|
||||
|
||||
if(victim.getMp() > statUpdate) {
|
||||
victim.setMp(statUpdate);
|
||||
victim.updateSingleStat(MapleStat.MP, statUpdate);
|
||||
}
|
||||
|
||||
victim.setMaxHp(statUpdate);
|
||||
victim.setMaxMp(statUpdate);
|
||||
victim.updateSingleStat(MapleStat.MAXHP, statUpdate);
|
||||
victim.updateSingleStat(MapleStat.MAXMP, statUpdate);
|
||||
|
||||
victim.checkBerserk(victim.isHidden());
|
||||
} else {
|
||||
player.message("Player '" + sub[1] + "' could not be found on this world.");
|
||||
}
|
||||
break;
|
||||
|
||||
case "music":
|
||||
if (sub.length < 2) {
|
||||
player.yellowMessage("Syntax: !music <song>");
|
||||
|
||||
@@ -272,7 +272,7 @@ public class NewYearCardRecord {
|
||||
}
|
||||
|
||||
MapleCharacter target = Server.getInstance().getWorld(world).getPlayerStorage().getCharacterById(receiverId);
|
||||
if(target != null && target.isLoggedin() && !target.isAwayFromWorld()) {
|
||||
if(target != null && target.isLoggedinWorld()) {
|
||||
target.announce(MaplePacketCreator.onNewYearCardRes(target, NewYearCardRecord.this, 0xC, 0));
|
||||
}
|
||||
}
|
||||
@@ -328,7 +328,7 @@ public class NewYearCardRecord {
|
||||
chr.getMap().broadcastMessage(MaplePacketCreator.onNewYearCardRes(chr, nyc, 0xE, 0));
|
||||
|
||||
MapleCharacter other = chr.getClient().getWorldServer().getPlayerStorage().getCharacterById(nyc.getReceiverId());
|
||||
if(other != null && other.isLoggedin() && !other.isAwayFromWorld()) {
|
||||
if(other != null && other.isLoggedinWorld()) {
|
||||
other.removeNewYearRecord(nyc);
|
||||
other.getMap().broadcastMessage(MaplePacketCreator.onNewYearCardRes(other, nyc, 0xE, 0));
|
||||
|
||||
@@ -346,7 +346,7 @@ public class NewYearCardRecord {
|
||||
chr.getMap().broadcastMessage(MaplePacketCreator.onNewYearCardRes(chr, nyc, 0xE, 0));
|
||||
|
||||
MapleCharacter other = chr.getClient().getWorldServer().getPlayerStorage().getCharacterById(nyc.getSenderId());
|
||||
if(other != null && other.isLoggedin() && !other.isAwayFromWorld()) {
|
||||
if(other != null && other.isLoggedinWorld()) {
|
||||
other.removeNewYearRecord(nyc);
|
||||
other.getMap().broadcastMessage(MaplePacketCreator.onNewYearCardRes(other, nyc, 0xE, 0));
|
||||
|
||||
|
||||
@@ -171,6 +171,11 @@ public final class ItemConstants {
|
||||
public static boolean isOverall(int itemId) {
|
||||
return itemId / 10000 == 105;
|
||||
}
|
||||
|
||||
public static boolean isCashStore(int itemId) {
|
||||
int itemType = itemId / 10000;
|
||||
return itemType == 503 || itemType == 514;
|
||||
}
|
||||
|
||||
public static boolean isWeapon(int itemId) {
|
||||
return itemId >= 1302000 && itemId < 1492024;
|
||||
|
||||
@@ -26,6 +26,8 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import server.life.MobSkill;
|
||||
import tools.Pair;
|
||||
import tools.locks.MonitoredLockType;
|
||||
import tools.locks.MonitoredReentrantLock;
|
||||
|
||||
@@ -38,7 +40,7 @@ public class PlayerBuffStorage {
|
||||
private int id = (int) (Math.random() * 100);
|
||||
private final Lock lock = new MonitoredReentrantLock(MonitoredLockType.BUFF_STORAGE, true);
|
||||
private Map<Integer, List<PlayerBuffValueHolder>> buffs = new HashMap<>();
|
||||
private Map<Integer, Map<MapleDisease, Long>> diseases = new HashMap<>();
|
||||
private Map<Integer, Map<MapleDisease, Pair<Long, MobSkill>>> diseases = new HashMap<>();
|
||||
|
||||
public void addBuffsToStorage(int chrid, List<PlayerBuffValueHolder> toStore) {
|
||||
lock.lock();
|
||||
@@ -58,7 +60,7 @@ public class PlayerBuffStorage {
|
||||
}
|
||||
}
|
||||
|
||||
public void addDiseasesToStorage(int chrid, Map<MapleDisease, Long> toStore) {
|
||||
public void addDiseasesToStorage(int chrid, Map<MapleDisease, Pair<Long, MobSkill>> toStore) {
|
||||
lock.lock();
|
||||
try {
|
||||
diseases.put(chrid, toStore);
|
||||
@@ -67,7 +69,7 @@ public class PlayerBuffStorage {
|
||||
}
|
||||
}
|
||||
|
||||
public Map<MapleDisease, Long> getDiseasesFromStorage(int chrid) {
|
||||
public Map<MapleDisease, Pair<Long, MobSkill>> getDiseasesFromStorage(int chrid) {
|
||||
lock.lock();
|
||||
try {
|
||||
return diseases.remove(chrid);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
package net.server;
|
||||
|
||||
import net.server.worker.CharacterDiseaseWorker;
|
||||
import net.server.worker.CouponWorker;
|
||||
import net.server.worker.RankingWorker;
|
||||
import java.io.FileInputStream;
|
||||
@@ -94,9 +95,12 @@ public class Server {
|
||||
private final Map<MapleClient, Long> inLoginState = new HashMap<>(100);
|
||||
private final Lock srvLock = new MonitoredReentrantLock(MonitoredLockType.SERVER);
|
||||
private final Lock lgnLock = new MonitoredReentrantLock(MonitoredLockType.SERVER);
|
||||
private final Lock disLock = new MonitoredReentrantLock(MonitoredLockType.SERVER);
|
||||
private final PlayerBuffStorage buffStorage = new PlayerBuffStorage();
|
||||
private final Map<Integer, MapleAlliance> alliances = new HashMap<>(100);
|
||||
private final Map<Integer, NewYearCardRecord> newyears = new HashMap<>();
|
||||
private final List<MapleClient> processDiseaseAnnouncePlayers = new LinkedList<>();
|
||||
private final List<MapleClient> registeredDiseaseAnnouncePlayers = new LinkedList<>();
|
||||
|
||||
private boolean online = false;
|
||||
public static long uptime = System.currentTimeMillis();
|
||||
@@ -261,7 +265,39 @@ public class Server {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void runAnnouncePlayerDiseasesSchedule() {
|
||||
disLock.lock();
|
||||
try {
|
||||
while(!processDiseaseAnnouncePlayers.isEmpty()) {
|
||||
MapleClient c = processDiseaseAnnouncePlayers.remove(0);
|
||||
MapleCharacter player = c.getPlayer();
|
||||
if(player != null && player.isLoggedinWorld()) {
|
||||
for(MapleCharacter chr : player.getMap().getCharacters()) {
|
||||
chr.announceDiseases(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this is to force the system to wait for at least one complete tick before releasing disease info for the registered clients
|
||||
while(!registeredDiseaseAnnouncePlayers.isEmpty()) {
|
||||
MapleClient c = registeredDiseaseAnnouncePlayers.remove(0);
|
||||
processDiseaseAnnouncePlayers.add(c);
|
||||
}
|
||||
} finally {
|
||||
disLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void registerAnnouncePlayerDiseases(MapleClient c) {
|
||||
disLock.lock();
|
||||
try {
|
||||
registeredDiseaseAnnouncePlayers.add(c);
|
||||
} finally {
|
||||
disLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void init() {
|
||||
Properties p = new Properties();
|
||||
try {
|
||||
@@ -306,6 +342,7 @@ public class Server {
|
||||
disconnectIdlesOnLoginTask();
|
||||
|
||||
long timeLeft = getTimeLeftForNextHour();
|
||||
tMan.register(new CharacterDiseaseWorker(), 777, 777);
|
||||
tMan.register(new CouponWorker(), ServerConstants.COUPON_INTERVAL, timeLeft);
|
||||
tMan.register(new RankingWorker(), ServerConstants.RANKING_INTERVAL, timeLeft);
|
||||
|
||||
|
||||
@@ -36,13 +36,17 @@ public final class CancelChairHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
if (id == -1) { // Cancel Chair
|
||||
mc.setChair(0);
|
||||
mc.unregisterChairBuff();
|
||||
if(mc.unregisterChairBuff()) {
|
||||
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.cancelForeignChairSkillEffect(mc.getId()), false);
|
||||
}
|
||||
|
||||
c.announce(MaplePacketCreator.cancelChair(-1));
|
||||
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showChair(c.getPlayer().getId(), 0), false);
|
||||
} else { // Use In-Map Chair
|
||||
mc.setChair(id);
|
||||
mc.registerChairBuff();
|
||||
if(mc.registerChairBuff()) {
|
||||
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.giveForeignChairSkillEffect(mc.getId()), false);
|
||||
}
|
||||
|
||||
c.announce(MaplePacketCreator.cancelChair(id));
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import client.inventory.Equip;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.MapleInventory;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import constants.ItemConstants;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
@@ -64,6 +65,12 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if(ItemConstants.isCashStore(cItem.getItemId()) && chr.getLevel() < 16) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if (action == 0x03) { // Item
|
||||
Item item = cItem.toItem();
|
||||
cs.addToInventory(item);
|
||||
@@ -176,20 +183,20 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
|
||||
}
|
||||
}
|
||||
} else if (action == 0x08) { // Increase Character Slots
|
||||
slea.skip(1);
|
||||
int cash = slea.readInt();
|
||||
CashItem cItem = CashItemFactory.getItem(slea.readInt());
|
||||
slea.skip(1);
|
||||
int cash = slea.readInt();
|
||||
CashItem cItem = CashItemFactory.getItem(slea.readInt());
|
||||
|
||||
if (!canBuy(cItem, cs.getCash(cash))) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (!canBuy(cItem, cs.getCash(cash))) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if (c.gainCharacterSlot()) {
|
||||
c.announce(MaplePacketCreator.showBoughtCharacterSlot(c.getCharacterSlots()));
|
||||
cs.gainCash(cash, -cItem.getPrice());
|
||||
c.announce(MaplePacketCreator.showCash(chr));
|
||||
}
|
||||
if (c.gainCharacterSlot()) {
|
||||
c.announce(MaplePacketCreator.showBoughtCharacterSlot(c.getCharacterSlots()));
|
||||
cs.gainCash(cash, -cItem.getPrice());
|
||||
c.announce(MaplePacketCreator.showCash(chr));
|
||||
}
|
||||
} else if (action == 0x0D) { // Take from Cash Inventory
|
||||
Item item = cs.findByCashId(slea.readInt());
|
||||
if (item == null) {
|
||||
@@ -281,8 +288,8 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
|
||||
}
|
||||
c.announce(MaplePacketCreator.showCash(c.getPlayer()));
|
||||
} else if (action == 0x23) { //Friendship :3
|
||||
slea.readInt(); //Birthday
|
||||
// if (checkBirthday(c, birthday)) {
|
||||
slea.readInt(); //Birthday
|
||||
// if (checkBirthday(c, birthday)) {
|
||||
int payment = slea.readByte();
|
||||
slea.skip(3); //0s
|
||||
int snID = slea.readInt();
|
||||
|
||||
@@ -106,7 +106,7 @@ public final class NewYearCardHandler extends AbstractMaplePacketHandler {
|
||||
player.getMap().broadcastMessage(MaplePacketCreator.onNewYearCardRes(player, newyear, 0xD, 0));
|
||||
|
||||
MapleCharacter sender = c.getWorldServer().getPlayerStorage().getCharacterById(newyear.getSenderId());
|
||||
if(sender != null && sender.isLoggedin() && !sender.isAwayFromWorld()) {
|
||||
if(sender != null && sender.isLoggedinWorld()) {
|
||||
sender.getMap().broadcastMessage(MaplePacketCreator.onNewYearCardRes(sender, newyear, 0xD, 0));
|
||||
sender.dropMessage(6, "[NEW YEAR] Your addressee successfully received the New Year card.");
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ import java.net.InetSocketAddress;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import server.life.MobSkill;
|
||||
|
||||
public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@@ -129,7 +130,7 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
player.silentGiveBuffs(timedBuffs);
|
||||
}
|
||||
|
||||
Map<MapleDisease, Long> diseases = server.getPlayerBuffStorage().getDiseasesFromStorage(cid);
|
||||
Map<MapleDisease, Pair<Long, MobSkill>> diseases = server.getPlayerBuffStorage().getDiseasesFromStorage(cid);
|
||||
if (diseases != null) {
|
||||
player.silentApplyDiseases(diseases);
|
||||
}
|
||||
|
||||
33
src/net/server/worker/CharacterDiseaseWorker.java
Normal file
33
src/net/server/worker/CharacterDiseaseWorker.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
|
||||
Copyleft (L) 2017 RonanLana
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package net.server.worker;
|
||||
|
||||
import net.server.Server;
|
||||
|
||||
/**
|
||||
* @author Ronan
|
||||
* @info Thread responsible for announcing other players diseases when one enters into a map
|
||||
*/
|
||||
public class CharacterDiseaseWorker implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
Server.getInstance().runAnnouncePlayerDiseasesSchedule();
|
||||
}
|
||||
}
|
||||
@@ -842,7 +842,7 @@ public class World {
|
||||
|
||||
for(Map.Entry<Integer, Byte> dp: deployedPets.entrySet()) {
|
||||
MapleCharacter chr = this.getPlayerStorage().getCharacterById(dp.getKey() / 4);
|
||||
if(chr == null || !chr.isLoggedin() || chr.isAwayFromWorld()) continue;
|
||||
if(chr == null || !chr.isLoggedinWorld()) continue;
|
||||
|
||||
Byte dpVal = (byte)(dp.getValue() + 1);
|
||||
if(dpVal == ServerConstants.PET_EXHAUST_COUNT) {
|
||||
@@ -900,7 +900,7 @@ public class World {
|
||||
|
||||
for(Map.Entry<Integer, Byte> dp: deployedMounts.entrySet()) {
|
||||
MapleCharacter chr = this.getPlayerStorage().getCharacterById(dp.getKey());
|
||||
if(chr == null || !chr.isLoggedin() || chr.isAwayFromWorld()) continue;
|
||||
if(chr == null || !chr.isLoggedinWorld()) continue;
|
||||
|
||||
Byte dpVal = (byte)(dp.getValue() + 1);
|
||||
if(dpVal == ServerConstants.MOUNT_EXHAUST_COUNT) {
|
||||
|
||||
@@ -921,7 +921,7 @@ public class EventInstanceManager {
|
||||
for (MapleCharacter evChr : eventMembers) {
|
||||
MapleCharacter chr = mapChars.get(evChr.getId());
|
||||
|
||||
if(chr != null && chr.isLoggedin() && !chr.isAwayFromWorld()) {
|
||||
if(chr != null && chr.isLoggedinWorld()) {
|
||||
chr.updateQuestMobCount(mobid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,8 +91,8 @@ public class MapleItemInformationProvider {
|
||||
protected Map<Integer, MapleStatEffect> itemEffects = new HashMap<>();
|
||||
protected Map<Integer, Map<String, Integer>> equipStatsCache = new HashMap<>();
|
||||
protected Map<Integer, Equip> equipCache = new HashMap<>();
|
||||
protected Map<Integer, Double> priceCache = new HashMap<>();
|
||||
protected Map<Integer, Integer> wholePriceCache = new HashMap<>();
|
||||
protected Map<Integer, Double> unitPriceCache = new HashMap<>();
|
||||
protected Map<Integer, Integer> projectileWatkCache = new HashMap<>();
|
||||
protected Map<Integer, String> nameCache = new HashMap<>();
|
||||
protected Map<Integer, String> descCache = new HashMap<>();
|
||||
@@ -421,54 +421,96 @@ public class MapleItemInformationProvider {
|
||||
return pEntry;
|
||||
}
|
||||
|
||||
private Pair<Integer, Double> getItemPriceData(int itemId) {
|
||||
MapleData item = getItemData(itemId);
|
||||
if (item == null) {
|
||||
wholePriceCache.put(itemId, -1);
|
||||
unitPriceCache.put(itemId, 0.0);
|
||||
return new Pair<>(-1, 0.0);
|
||||
}
|
||||
|
||||
int pEntry = -1;
|
||||
MapleData pData = item.getChildByPath("info/price");
|
||||
if (pData != null) {
|
||||
pEntry = MapleDataTool.getInt(pData);
|
||||
}
|
||||
|
||||
double fEntry = 0.0f;
|
||||
pData = item.getChildByPath("info/unitPrice");
|
||||
if (pData != null) {
|
||||
try {
|
||||
fEntry = MapleDataTool.getDouble(pData);
|
||||
} catch (Exception e) {
|
||||
fEntry = (double) MapleDataTool.getInt(pData);
|
||||
}
|
||||
}
|
||||
|
||||
wholePriceCache.put(itemId, pEntry);
|
||||
unitPriceCache.put(itemId, fEntry);
|
||||
return new Pair<>(pEntry, fEntry);
|
||||
}
|
||||
|
||||
public int getWholePrice(int itemId) {
|
||||
if (wholePriceCache.containsKey(itemId)) {
|
||||
return wholePriceCache.get(itemId);
|
||||
}
|
||||
MapleData item = getItemData(itemId);
|
||||
if (item == null) {
|
||||
return -1;
|
||||
|
||||
return getItemPriceData(itemId).getLeft();
|
||||
}
|
||||
|
||||
public double getUnitPrice(int itemId) {
|
||||
if (unitPriceCache.containsKey(itemId)) {
|
||||
return unitPriceCache.get(itemId);
|
||||
}
|
||||
int pEntry;
|
||||
MapleData pData = item.getChildByPath("info/price");
|
||||
if (pData == null) {
|
||||
return -1;
|
||||
}
|
||||
pEntry = MapleDataTool.getInt(pData);
|
||||
wholePriceCache.put(itemId, pEntry);
|
||||
return pEntry;
|
||||
|
||||
return getItemPriceData(itemId).getRight();
|
||||
}
|
||||
|
||||
public double getPrice(int itemId) {
|
||||
if (priceCache.containsKey(itemId)) {
|
||||
return priceCache.get(itemId);
|
||||
}
|
||||
MapleData item = getItemData(itemId);
|
||||
if (item == null) {
|
||||
public int getPrice(int itemId, int quantity) {
|
||||
int retPrice = getWholePrice(itemId);
|
||||
if(retPrice == -1) {
|
||||
return -1;
|
||||
}
|
||||
double pEntry;
|
||||
MapleData pData = item.getChildByPath("info/unitPrice");
|
||||
if (pData != null) {
|
||||
try {
|
||||
pEntry = MapleDataTool.getDouble(pData);
|
||||
} catch (Exception e) {
|
||||
pEntry = (double) MapleDataTool.getInt(pData);
|
||||
}
|
||||
|
||||
if(!ItemConstants.isRechargable(itemId)) {
|
||||
retPrice *= quantity;
|
||||
} else {
|
||||
pData = item.getChildByPath("info/price");
|
||||
if (pData == null) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
pEntry = (double) MapleDataTool.getInt(pData);
|
||||
} catch(Exception e) {
|
||||
priceCache.put(itemId, 0.0);
|
||||
return 0;
|
||||
retPrice += Math.ceil(quantity * getUnitPrice(itemId));
|
||||
}
|
||||
|
||||
return retPrice;
|
||||
}
|
||||
|
||||
public static boolean canSell(Item item, short quantity) {
|
||||
if (item == null) { //Basic check
|
||||
return false;
|
||||
}
|
||||
|
||||
short iQuant = item.getQuantity();
|
||||
if (iQuant == 0xFFFF) {
|
||||
iQuant = 1;
|
||||
} else if(iQuant < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ItemConstants.isRechargable(item.getItemId())) {
|
||||
if (iQuant == 0 || quantity > iQuant) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
priceCache.put(itemId, pEntry);
|
||||
return pEntry;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static short getSellingQuantity(Item item, short quantity) {
|
||||
if (ItemConstants.isRechargable(item.getItemId())) {
|
||||
quantity = item.getQuantity();
|
||||
if (quantity == 0xFFFF) {
|
||||
quantity = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return quantity;
|
||||
}
|
||||
|
||||
protected String getEquipmentSlot(int itemId) {
|
||||
|
||||
@@ -88,7 +88,7 @@ public class MapleShop {
|
||||
return;
|
||||
}
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
if (item != null && item.getPrice() > 0) {
|
||||
if (item.getPrice() > 0) {
|
||||
if (c.getPlayer().getMeso() >= (long) item.getPrice() * quantity) {
|
||||
if (MapleInventoryManipulator.checkSpace(c, itemId, quantity, "")) {
|
||||
if (!ItemConstants.isRechargable(itemId)) { //Pets can't be bought from shops
|
||||
@@ -107,77 +107,64 @@ public class MapleShop {
|
||||
} else
|
||||
c.announce(MaplePacketCreator.shopTransaction((byte) 2));
|
||||
|
||||
} else if (item != null && item.getPitch() > 0) {
|
||||
if (c.getPlayer().getInventory(MapleInventoryType.ETC).countById(4310000) >= (long) item.getPitch() * quantity) {
|
||||
if (MapleInventoryManipulator.checkSpace(c, itemId, quantity, "")) {
|
||||
if (!ItemConstants.isRechargable(itemId)) {
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity);
|
||||
MapleInventoryManipulator.removeById(c, MapleInventoryType.ETC, 4310000, item.getPitch() * quantity, false, false);
|
||||
} else {
|
||||
short slotMax = ii.getSlotMax(c, item.getItemId());
|
||||
quantity = slotMax;
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity);
|
||||
MapleInventoryManipulator.removeById(c, MapleInventoryType.ETC, 4310000, item.getPitch() * quantity, false, false);
|
||||
}
|
||||
c.announce(MaplePacketCreator.shopTransaction((byte) 0));
|
||||
} else
|
||||
c.announce(MaplePacketCreator.shopTransaction((byte) 3));
|
||||
}
|
||||
|
||||
} else if (c.getPlayer().getInventory(MapleInventoryType.CASH).countById(token) != 0) {
|
||||
int amount = c.getPlayer().getInventory(MapleInventoryType.CASH).countById(token);
|
||||
int value = amount * tokenvalue;
|
||||
int cost = item.getPrice() * quantity;
|
||||
if (c.getPlayer().getMeso() + value >= cost) {
|
||||
int cardreduce = value - cost;
|
||||
int diff = cardreduce + c.getPlayer().getMeso();
|
||||
if (MapleInventoryManipulator.checkSpace(c, itemId, quantity, "")) {
|
||||
if (ItemConstants.isPet(itemId)) {
|
||||
int petid = MaplePet.createPet(itemId);
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity, null, petid, -1);
|
||||
} else {
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity);
|
||||
}
|
||||
c.getPlayer().gainMeso(diff, false);
|
||||
} else if (item.getPitch() > 0) {
|
||||
if (c.getPlayer().getInventory(MapleInventoryType.ETC).countById(4310000) >= (long) item.getPitch() * quantity) {
|
||||
if (MapleInventoryManipulator.checkSpace(c, itemId, quantity, "")) {
|
||||
if (!ItemConstants.isRechargable(itemId)) {
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity);
|
||||
MapleInventoryManipulator.removeById(c, MapleInventoryType.ETC, 4310000, item.getPitch() * quantity, false, false);
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.shopTransaction((byte) 3));
|
||||
short slotMax = ii.getSlotMax(c, item.getItemId());
|
||||
quantity = slotMax;
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity);
|
||||
MapleInventoryManipulator.removeById(c, MapleInventoryType.ETC, 4310000, item.getPitch() * quantity, false, false);
|
||||
}
|
||||
c.announce(MaplePacketCreator.shopTransaction((byte) 0));
|
||||
} else
|
||||
c.announce(MaplePacketCreator.shopTransaction((byte) 2));
|
||||
c.announce(MaplePacketCreator.shopTransaction((byte) 3));
|
||||
}
|
||||
|
||||
} else if (c.getPlayer().getInventory(MapleInventoryType.CASH).countById(token) != 0) {
|
||||
int amount = c.getPlayer().getInventory(MapleInventoryType.CASH).countById(token);
|
||||
int value = amount * tokenvalue;
|
||||
int cost = item.getPrice() * quantity;
|
||||
if (c.getPlayer().getMeso() + value >= cost) {
|
||||
int cardreduce = value - cost;
|
||||
int diff = cardreduce + c.getPlayer().getMeso();
|
||||
if (MapleInventoryManipulator.checkSpace(c, itemId, quantity, "")) {
|
||||
if (ItemConstants.isPet(itemId)) {
|
||||
int petid = MaplePet.createPet(itemId);
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity, null, petid, -1);
|
||||
} else {
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity);
|
||||
}
|
||||
c.getPlayer().gainMeso(diff, false);
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.shopTransaction((byte) 3));
|
||||
}
|
||||
c.announce(MaplePacketCreator.shopTransaction((byte) 0));
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.shopTransaction((byte) 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void sell(MapleClient c, MapleInventoryType type, short slot, short quantity) {
|
||||
if (quantity == 0xFFFF || quantity == 0) {
|
||||
quantity = 1;
|
||||
}
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
Item item = c.getPlayer().getInventory(type).getItem((short) slot);
|
||||
if (item == null){ //Basic check
|
||||
return;
|
||||
}
|
||||
if (ItemConstants.isRechargable(item.getItemId())) {
|
||||
quantity = item.getQuantity();
|
||||
}
|
||||
if (quantity < 0) {
|
||||
} else if (quantity < 0) {
|
||||
return;
|
||||
}
|
||||
short iQuant = item.getQuantity();
|
||||
if (iQuant == 0xFFFF) {
|
||||
iQuant = 1;
|
||||
}
|
||||
if (quantity <= iQuant && iQuant > 0) {
|
||||
|
||||
Item item = c.getPlayer().getInventory(type).getItem((short) slot);
|
||||
if(MapleItemInformationProvider.canSell(item, quantity)) {
|
||||
quantity = MapleItemInformationProvider.getSellingQuantity(item, quantity);
|
||||
MapleInventoryManipulator.removeFromSlot(c, type, (byte) slot, quantity, false);
|
||||
double price;
|
||||
if (ItemConstants.isRechargable(item.getItemId())) {
|
||||
price = ii.getWholePrice(item.getItemId()) / (double) ii.getSlotMax(c, item.getItemId());
|
||||
} else {
|
||||
price = ii.getPrice(item.getItemId());
|
||||
}
|
||||
int recvMesos = (int) Math.max(Math.ceil(price * quantity), 0);
|
||||
if (price != -1 && recvMesos > 0) {
|
||||
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
int recvMesos = ii.getPrice(item.getItemId(), quantity);
|
||||
if (recvMesos > 0) {
|
||||
c.getPlayer().gainMeso(recvMesos, false);
|
||||
}
|
||||
c.announce(MaplePacketCreator.shopTransaction((byte) 0x8));
|
||||
@@ -195,7 +182,7 @@ public class MapleShop {
|
||||
return;
|
||||
}
|
||||
if (item.getQuantity() < slotMax) {
|
||||
int price = (int) Math.round(ii.getPrice(item.getItemId()) * (slotMax - item.getQuantity()));
|
||||
int price = (int) Math.ceil(ii.getUnitPrice(item.getItemId()) * (slotMax - item.getQuantity()));
|
||||
if (c.getPlayer().getMeso() >= price) {
|
||||
item.setQuantity(slotMax);
|
||||
c.getPlayer().forceUpdateItem(item);
|
||||
|
||||
@@ -552,7 +552,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
for (Integer chrid : attackerChrids) {
|
||||
MapleCharacter chr = mapChars.get(chrid);
|
||||
|
||||
if(chr != null && chr.isLoggedin() && !chr.isAwayFromWorld()) {
|
||||
if(chr != null && chr.isLoggedinWorld()) {
|
||||
chr.updateQuestMobCount(mobid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
String qtyStr = (item.getQuantity() > 1) ? " (qty. " + item.getQuantity() + ")" : "";
|
||||
|
||||
MapleCharacter player = Server.getInstance().getWorld(world).getPlayerStorage().getCharacterById(ownerId);
|
||||
if(player != null && player.isLoggedin() && !player.isAwayFromWorld()) {
|
||||
if(player != null && player.isLoggedinWorld()) {
|
||||
player.dropMessage(6, "[HIRED MERCHANT] Item '" + MapleItemInformationProvider.getInstance().getName(item.getItemId()) + "'" + qtyStr + " has been sold for " + mesos + " mesos.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2322,6 +2322,11 @@ public class MapleMap {
|
||||
}
|
||||
|
||||
chr.receivePartyMemberHP();
|
||||
announcePlayerDiseases(chr.getClient());
|
||||
}
|
||||
|
||||
private static void announcePlayerDiseases(final MapleClient c) {
|
||||
Server.getInstance().registerAnnouncePlayerDiseases(c);
|
||||
}
|
||||
|
||||
public MaplePortal getRandomPlayerSpawnpoint() {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
package server.maps;
|
||||
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||
@@ -21,7 +19,7 @@ package server.maps;
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package server.maps;
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -2256,10 +2256,11 @@ public class MaplePacketCreator {
|
||||
}
|
||||
}
|
||||
|
||||
// someone thought it was a good idea to handle floating point representation through packets ROFL
|
||||
private static int doubleToShortBits(double d) {
|
||||
return (int) (Double.doubleToLongBits(d) >> 48);
|
||||
}
|
||||
|
||||
|
||||
public static byte[] getNPCShop(MapleClient c, int sid, List<MapleShopItem> items) {
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||
@@ -2278,7 +2279,7 @@ public class MaplePacketCreator {
|
||||
} else {
|
||||
mplew.writeShort(0);
|
||||
mplew.writeInt(0);
|
||||
mplew.writeShort(doubleToShortBits(ii.getPrice(item.getItemId())));
|
||||
mplew.writeShort(doubleToShortBits(ii.getUnitPrice(item.getItemId())));
|
||||
mplew.writeShort(ii.getSlotMax(c, item.getItemId()));
|
||||
}
|
||||
}
|
||||
@@ -2440,26 +2441,31 @@ public class MaplePacketCreator {
|
||||
mplew.writeInt(cid);
|
||||
mplew.write(skill);
|
||||
mplew.writeInt(damage);
|
||||
mplew.writeInt(monsteridfrom);
|
||||
mplew.write(direction);
|
||||
if (pgmr) {
|
||||
mplew.write(pgmr_1);
|
||||
mplew.write(is_pg ? 1 : 0);
|
||||
mplew.writeInt(oid);
|
||||
mplew.write(6);
|
||||
mplew.writeShort(pos_x);
|
||||
mplew.writeShort(pos_y);
|
||||
mplew.write(0);
|
||||
if(skill != -4) {
|
||||
mplew.writeInt(monsteridfrom);
|
||||
mplew.write(direction);
|
||||
if (pgmr) {
|
||||
mplew.write(pgmr_1);
|
||||
mplew.write(is_pg ? 1 : 0);
|
||||
mplew.writeInt(oid);
|
||||
mplew.write(6);
|
||||
mplew.writeShort(pos_x);
|
||||
mplew.writeShort(pos_y);
|
||||
mplew.write(0);
|
||||
} else {
|
||||
mplew.writeShort(0);
|
||||
}
|
||||
mplew.writeInt(damage);
|
||||
if (fake > 0) {
|
||||
mplew.writeInt(fake);
|
||||
}
|
||||
} else {
|
||||
mplew.writeShort(0);
|
||||
}
|
||||
mplew.writeInt(damage);
|
||||
if (fake > 0) {
|
||||
mplew.writeInt(fake);
|
||||
mplew.writeInt(damage);
|
||||
}
|
||||
|
||||
return mplew.getPacket();
|
||||
}
|
||||
|
||||
|
||||
public static byte[] charNameResponse(String charname, boolean nameUsed) {
|
||||
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||
mplew.writeShort(SendOpcode.CHAR_NAME_RESPONSE.getValue());
|
||||
@@ -2760,7 +2766,7 @@ public class MaplePacketCreator {
|
||||
mplew.writeLong(firstmask);
|
||||
mplew.writeLong(secondmask);
|
||||
}
|
||||
|
||||
|
||||
public static byte[] giveDebuff(List<Pair<MapleDisease, Integer>> statups, MobSkill skill) {
|
||||
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||
mplew.writeShort(SendOpcode.GIVE_BUFF.getValue());
|
||||
@@ -2776,8 +2782,10 @@ public class MaplePacketCreator {
|
||||
mplew.write(1);
|
||||
return mplew.getPacket();
|
||||
}
|
||||
|
||||
|
||||
public static byte[] giveForeignDebuff(int cid, List<Pair<MapleDisease, Integer>> statups, MobSkill skill) {
|
||||
// Poison damage visibility and missing diseases status visibility, extended through map transitions thanks to Ronan
|
||||
|
||||
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||
mplew.writeShort(SendOpcode.GIVE_FOREIGN_BUFF.getValue());
|
||||
mplew.writeInt(cid);
|
||||
@@ -2867,6 +2875,69 @@ public class MaplePacketCreator {
|
||||
return mplew.getPacket();
|
||||
}
|
||||
|
||||
private static void writeLongMaskSlowD(final MaplePacketLittleEndianWriter mplew) {
|
||||
mplew.writeInt(0);
|
||||
mplew.writeInt(2048);
|
||||
mplew.writeLong(0);
|
||||
}
|
||||
|
||||
public static byte[] giveForeignSlowDebuff(int cid, List<Pair<MapleDisease, Integer>> statups, MobSkill skill) {
|
||||
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||
mplew.writeShort(SendOpcode.GIVE_FOREIGN_BUFF.getValue());
|
||||
mplew.writeInt(cid);
|
||||
writeLongMaskSlowD(mplew);
|
||||
for (Pair<MapleDisease, Integer> statup : statups) {
|
||||
if(statup.getLeft() == MapleDisease.POISON) mplew.writeShort(statup.getRight().shortValue());
|
||||
mplew.writeShort(skill.getSkillId());
|
||||
mplew.writeShort(skill.getSkillLevel());
|
||||
}
|
||||
mplew.writeShort(0); // same as give_buff
|
||||
mplew.writeShort(900);//Delay
|
||||
return mplew.getPacket();
|
||||
}
|
||||
|
||||
public static byte[] cancelForeignSlowDebuff(int cid) {
|
||||
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||
mplew.writeShort(SendOpcode.CANCEL_FOREIGN_BUFF.getValue());
|
||||
mplew.writeInt(cid);
|
||||
writeLongMaskSlowD(mplew);
|
||||
return mplew.getPacket();
|
||||
}
|
||||
|
||||
private static void writeLongMaskChair(final MaplePacketLittleEndianWriter mplew) {
|
||||
mplew.writeInt(0);
|
||||
mplew.writeInt(262144);
|
||||
mplew.writeLong(0);
|
||||
}
|
||||
|
||||
public static byte[] giveForeignChairSkillEffect(int cid) {
|
||||
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||
mplew.writeShort(SendOpcode.GIVE_FOREIGN_BUFF.getValue());
|
||||
mplew.writeInt(cid);
|
||||
writeLongMaskChair(mplew);
|
||||
|
||||
mplew.writeShort(0);
|
||||
mplew.writeShort(0);
|
||||
mplew.writeShort(100);
|
||||
mplew.writeShort(1);
|
||||
|
||||
mplew.writeShort(0);
|
||||
mplew.writeShort(900);
|
||||
|
||||
for(int i = 0; i < 7; i++) mplew.write(0);
|
||||
|
||||
return mplew.getPacket();
|
||||
}
|
||||
|
||||
public static byte[] cancelForeignChairSkillEffect(int cid) {
|
||||
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(19);
|
||||
mplew.writeShort(SendOpcode.CANCEL_FOREIGN_BUFF.getValue());
|
||||
mplew.writeInt(cid);
|
||||
writeLongMaskChair(mplew);
|
||||
|
||||
return mplew.getPacket();
|
||||
}
|
||||
|
||||
public static byte[] getPlayerShopChat(MapleCharacter c, String chat, boolean owner) {
|
||||
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||
mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue());
|
||||
@@ -6114,7 +6185,7 @@ public class MaplePacketCreator {
|
||||
mplew.write(amount);
|
||||
return mplew.getPacket();
|
||||
}
|
||||
|
||||
|
||||
public static byte[] showWheelsLeft(int left) {
|
||||
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||
mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue());
|
||||
|
||||
@@ -98,7 +98,7 @@ public class GenericLittleEndianWriter implements LittleEndianWriter {
|
||||
bos.writeByte((byte) (i & 0xFF));
|
||||
bos.writeByte((byte) ((i >>> 8) & 0xFF));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes an integer to the stream.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user