Map chair skill + Hired Merchant fix
Changed map chair bonus healing mechanic to be a player skill, instead of promptly available for all players (healing buff takes place only if the player has the skill). Hired Merchant now properly checks for a space on the inventory before permitting a player to buy an item/bundle. Minor fix with concurrency on MapleStorage.
This commit is contained in:
@@ -63,7 +63,7 @@ public enum MapleBuffStat {
|
||||
BERSERK_FURY(0x8000000L),
|
||||
DIVINE_BODY(0x10000000L),
|
||||
SPARK(0x20000000L),
|
||||
//0x40000000L
|
||||
MAP_CHAIR(0x40000000L),
|
||||
FINALATTACK(0x80000000L),
|
||||
BATTLESHIP(0xA00000040L), // weird one
|
||||
WATK(0x100000000L),
|
||||
|
||||
@@ -121,6 +121,7 @@ import constants.GameConstants;
|
||||
import constants.ItemConstants;
|
||||
import constants.ServerConstants;
|
||||
import constants.skills.Aran;
|
||||
import constants.skills.Beginner;
|
||||
import constants.skills.Bishop;
|
||||
import constants.skills.BlazeWizard;
|
||||
import constants.skills.Bowmaster;
|
||||
@@ -135,10 +136,12 @@ import constants.skills.GM;
|
||||
import constants.skills.Hermit;
|
||||
import constants.skills.Hero;
|
||||
import constants.skills.ILArchMage;
|
||||
import constants.skills.Legend;
|
||||
import constants.skills.Magician;
|
||||
import constants.skills.Marauder;
|
||||
import constants.skills.Marksman;
|
||||
import constants.skills.NightLord;
|
||||
import constants.skills.Noblesse;
|
||||
import constants.skills.Paladin;
|
||||
import constants.skills.Priest;
|
||||
import constants.skills.Ranger;
|
||||
@@ -1248,7 +1251,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
private void changeMapInternal(final MapleMap to, final Point pos, final byte[] warpPacket) {
|
||||
if(!canWarpMap) return;
|
||||
|
||||
this.stopChairTask();
|
||||
this.unregisterChairBuff();
|
||||
this.clearBanishPlayerData();
|
||||
this.closePlayerInteractions();
|
||||
this.resetPlayerAggro();
|
||||
@@ -2994,6 +2997,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
prtLock.unlock();
|
||||
}
|
||||
}
|
||||
} else if (effect.isMapChair()) {
|
||||
stopChairTask();
|
||||
}
|
||||
|
||||
List<Pair<MapleBuffStat, MapleBuffStatValueHolder>> toCancel = deregisterBuffStats(buffstats);
|
||||
@@ -3263,6 +3268,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
stopExtraTask();
|
||||
startExtraTask(extraHpRec, extraMpRec, extraRecInterval); // HP & MP sharing the same task holder
|
||||
}
|
||||
} else if (effect.isMapChair()) {
|
||||
startChairTask();
|
||||
}
|
||||
|
||||
effLock.lock();
|
||||
@@ -3324,7 +3331,36 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
|
||||
recalcLocalStats();
|
||||
}
|
||||
|
||||
|
||||
private static int getJobMapChair(MapleJob job) {
|
||||
switch(job.getId() / 1000) {
|
||||
case 0:
|
||||
return Beginner.MAP_CHAIR;
|
||||
case 1:
|
||||
return Noblesse.MAP_CHAIR;
|
||||
default:
|
||||
return Legend.MAP_CHAIR;
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterChairBuff() {
|
||||
int skillId = getJobMapChair(job);
|
||||
int skillLv = getSkillLevel(skillId);
|
||||
if(skillLv > 0) {
|
||||
MapleStatEffect mapChairSkill = SkillFactory.getSkill(skillId).getEffect(skillLv);
|
||||
cancelEffect(mapChairSkill, false, -1);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerChairBuff() {
|
||||
int skillId = getJobMapChair(job);
|
||||
int skillLv = getSkillLevel(skillId);
|
||||
if(skillLv > 0) {
|
||||
MapleStatEffect mapChairSkill = SkillFactory.getSkill(skillId).getEffect(skillLv);
|
||||
mapChairSkill.applyTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
public int getChair() {
|
||||
return chair.get();
|
||||
}
|
||||
|
||||
@@ -1316,7 +1316,6 @@ public class MapleClient {
|
||||
player.cancelBuffExpireTask();
|
||||
player.cancelDiseaseExpireTask();
|
||||
player.cancelSkillCooldownTask();
|
||||
player.stopChairTask();
|
||||
//Cancelling magicdoor? Nope
|
||||
//Cancelling mounts? Noty
|
||||
if (player.getBuffedValue(MapleBuffStat.PUPPET) != null) {
|
||||
|
||||
@@ -74,9 +74,7 @@ import constants.skills.WhiteKnight;
|
||||
import constants.skills.WindArcher;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import provider.MapleData;
|
||||
@@ -189,6 +187,7 @@ public class SkillFactory {
|
||||
case Beginner.NIMBLE_FEET:
|
||||
case Beginner.MONSTER_RIDER:
|
||||
case Beginner.ECHO_OF_HERO:
|
||||
case Beginner.MAP_CHAIR:
|
||||
case Swordsman.IRON_BODY:
|
||||
case Fighter.AXE_BOOSTER:
|
||||
case Fighter.POWER_GUARD:
|
||||
@@ -303,6 +302,7 @@ public class SkillFactory {
|
||||
case Noblesse.MONSTER_RIDER:
|
||||
case Noblesse.NIMBLE_FEET:
|
||||
case Noblesse.RECOVERY:
|
||||
case Noblesse.MAP_CHAIR:
|
||||
case DawnWarrior.COMBO:
|
||||
case DawnWarrior.FINAL_ATTACK:
|
||||
case DawnWarrior.IRON_BODY:
|
||||
@@ -346,6 +346,7 @@ public class SkillFactory {
|
||||
case Legend.ECHO_OF_HERO:
|
||||
case Legend.RECOVERY:
|
||||
case Legend.MONSTER_RIDER:
|
||||
case Legend.MAP_CHAIR:
|
||||
case Aran.MAPLE_WARRIOR:
|
||||
case Aran.HEROS_WILL:
|
||||
case Aran.POLEARM_BOOSTER:
|
||||
|
||||
@@ -28,6 +28,7 @@ package constants.skills;
|
||||
public class Beginner {
|
||||
public static final int BLESSING_OF_THE_FAIRY = 12;
|
||||
public static final int FOLLOW_THE_LEADER = 8;
|
||||
public static final int MAP_CHAIR = 100;
|
||||
public static final int THREE_SNAILS = 1001;
|
||||
public static final int RECOVERY = 1001;
|
||||
public static final int NIMBLE_FEET = 1002;
|
||||
|
||||
@@ -4,7 +4,7 @@ public class Evan {
|
||||
// EVAN1
|
||||
public static final int BLESSING_OF_THE_FAIRY = 20010012;
|
||||
public static final int THREE_SNAILS = 20011000;
|
||||
public static final int RECOVERY = 20011001;
|
||||
public static final int RECOVERY = 20011001;
|
||||
public static final int NIMBLE_FEET = 20011002;
|
||||
public static final int LEGENDARY_SPIRIT = 20011003;
|
||||
public static final int MONSTER_RIDER = 20011004;
|
||||
|
||||
@@ -44,6 +44,7 @@ public class Legend {
|
||||
public static final int TUTORIAL_SKILL3 = 20000016;
|
||||
public static final int TUTORIAL_SKILL4 = 20000017; //combo
|
||||
public static final int TUTORIAL_SKILL5 = 20000018; //critical
|
||||
public static final int MAP_CHAIR = 20000100;
|
||||
public static final int YETI_MOUNT1 = 20001019;
|
||||
public static final int YETI_MOUNT2 = 20001022;
|
||||
public static final int WITCH_BROOMSTICK = 20001023;
|
||||
|
||||
@@ -27,6 +27,7 @@ package constants.skills;
|
||||
*/
|
||||
public class Noblesse {
|
||||
public static final int BLESSING_OF_THE_FAIRY = 10000012;
|
||||
public static final int MAP_CHAIR = 10000100;
|
||||
public static final int THREE_SNAILS = 10001000;
|
||||
public static final int RECOVERY = 10001001;
|
||||
public static final int NIMBLE_FEET = 10001002;
|
||||
|
||||
@@ -22,23 +22,28 @@
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.MapleClient;
|
||||
import client.MapleCharacter;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
public final class CancelChairHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
int id = slea.readShort();
|
||||
MapleCharacter mc = c.getPlayer();
|
||||
|
||||
if (id == -1) { // Cancel Chair
|
||||
c.getPlayer().setChair(0);
|
||||
c.getPlayer().stopChairTask();
|
||||
mc.setChair(0);
|
||||
mc.unregisterChairBuff();
|
||||
|
||||
c.announce(MaplePacketCreator.cancelChair(-1));
|
||||
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showChair(c.getPlayer().getId(), 0), false);
|
||||
} else { // Use In-Map Chair
|
||||
c.getPlayer().setChair(id);
|
||||
c.getPlayer().startChairTask();
|
||||
mc.setChair(id);
|
||||
mc.registerChairBuff();
|
||||
|
||||
c.announce(MaplePacketCreator.cancelChair(id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
||||
* @author Matze
|
||||
*/
|
||||
public final class NPCMoreTalkHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
byte lastMsg = slea.readByte(); // 00 (last msg type I think)
|
||||
byte action = slea.readByte(); // 00 = end chat, 01 == follow
|
||||
|
||||
@@ -33,6 +33,7 @@ import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
public final class NPCTalkHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
if (!c.getPlayer().isAlive()) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
|
||||
@@ -26,7 +26,6 @@ import client.MapleClient;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import scripting.quest.QuestScriptManager;
|
||||
import server.quest.MapleQuest;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
/**
|
||||
@@ -34,6 +33,7 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
||||
* @author Matze
|
||||
*/
|
||||
public final class QuestActionHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
byte action = slea.readByte();
|
||||
short questid = slea.readShort();
|
||||
|
||||
@@ -266,7 +266,9 @@ public class MapleStatEffect {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if((sourceid == Beginner.NIMBLE_FEET || sourceid == Noblesse.NIMBLE_FEET || sourceid == Evan.NIMBLE_FEET || sourceid == Legend.AGILE_BODY) && ServerConstants.USE_ULTRA_NIMBLE_FEET == true) {
|
||||
if(isMapChair(sourceid)) {
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.MAP_CHAIR, 1);
|
||||
} else if((sourceid == Beginner.NIMBLE_FEET || sourceid == Noblesse.NIMBLE_FEET || sourceid == Evan.NIMBLE_FEET || sourceid == Legend.AGILE_BODY) && ServerConstants.USE_ULTRA_NIMBLE_FEET == true) {
|
||||
ret.jump = (short)(ret.speed * 4);
|
||||
ret.speed *= 15;
|
||||
}
|
||||
@@ -756,8 +758,7 @@ public class MapleStatEffect {
|
||||
applyto.dispelDebuff(MapleDisease.SEDUCE);
|
||||
applyto.dispelDebuff(MapleDisease.ZOMBIFY);
|
||||
applyto.dispelDebuffs();
|
||||
}
|
||||
if (isComboReset()) {
|
||||
} else if (isComboReset()) {
|
||||
applyto.setCombo((short) 0);
|
||||
}
|
||||
/*if (applyfrom.getMp() < getMpCon()) {
|
||||
@@ -1322,6 +1323,15 @@ public class MapleStatEffect {
|
||||
return sourceid == Beginner.RECOVERY || sourceid == Noblesse.RECOVERY || sourceid == Legend.RECOVERY || sourceid == Evan.RECOVERY;
|
||||
}
|
||||
|
||||
public boolean isMapChair() {
|
||||
return sourceid == Beginner.MAP_CHAIR || sourceid == Noblesse.MAP_CHAIR || sourceid == Legend.MAP_CHAIR;
|
||||
}
|
||||
|
||||
public static boolean isMapChair(int sourceid) {
|
||||
return sourceid == Beginner.MAP_CHAIR || sourceid == Noblesse.MAP_CHAIR || sourceid == Legend.MAP_CHAIR;
|
||||
}
|
||||
|
||||
|
||||
public boolean isDojoBuff() {
|
||||
return sourceid >= 2022359 && sourceid <= 2022421;
|
||||
}
|
||||
|
||||
@@ -3,19 +3,16 @@
|
||||
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||
Matthias Butz <matze@odinms.de>
|
||||
Jan Christian Meyer <vimes@odinms.de>
|
||||
|
||||
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/>.
|
||||
*/
|
||||
@@ -164,12 +161,13 @@ public class MapleStorage {
|
||||
lock.lock();
|
||||
try {
|
||||
ret = items.remove(slot);
|
||||
|
||||
MapleInventoryType type = MapleItemInformationProvider.getInstance().getInventoryType(ret.getItemId());
|
||||
typeItems.put(type, new ArrayList<>(filterItems(type)));
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
MapleInventoryType type = MapleItemInformationProvider.getInstance().getInventoryType(ret.getItemId());
|
||||
typeItems.put(type, new ArrayList<>(filterItems(type)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -177,12 +175,12 @@ public class MapleStorage {
|
||||
lock.lock();
|
||||
try {
|
||||
items.add(item);
|
||||
|
||||
MapleInventoryType type = MapleItemInformationProvider.getInstance().getInventoryType(item.getItemId());
|
||||
typeItems.put(type, new ArrayList<>(filterItems(type)));
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
MapleInventoryType type = MapleItemInformationProvider.getInstance().getInventoryType(item.getItemId());
|
||||
typeItems.put(type, new ArrayList<>(filterItems(type)));
|
||||
}
|
||||
|
||||
public List<Item> getItems() {
|
||||
@@ -208,15 +206,20 @@ public class MapleStorage {
|
||||
}
|
||||
|
||||
public byte getSlot(MapleInventoryType type, byte slot) {
|
||||
byte ret = 0;
|
||||
List<Item> storageItems = getItems();
|
||||
for (Item item : storageItems) {
|
||||
if (item == typeItems.get(type).get(slot)) {
|
||||
return ret;
|
||||
lock.lock();
|
||||
try {
|
||||
byte ret = 0;
|
||||
List<Item> storageItems = getItems();
|
||||
for (Item item : storageItems) {
|
||||
if (item == typeItems.get(type).get(slot)) {
|
||||
return ret;
|
||||
}
|
||||
ret++;
|
||||
}
|
||||
ret++;
|
||||
return -1;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void sendStorage(MapleClient c, int npcId) {
|
||||
@@ -235,23 +238,33 @@ public class MapleStorage {
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
|
||||
List<Item> storageItems = getItems();
|
||||
for (MapleInventoryType type : MapleInventoryType.values()) {
|
||||
typeItems.put(type, new ArrayList<>(storageItems));
|
||||
}
|
||||
c.announce(MaplePacketCreator.getStorage(npcId, slots, storageItems, meso));
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
List<Item> storageItems = getItems();
|
||||
for (MapleInventoryType type : MapleInventoryType.values()) {
|
||||
typeItems.put(type, new ArrayList<>(storageItems));
|
||||
}
|
||||
c.announce(MaplePacketCreator.getStorage(npcId, slots, storageItems, meso));
|
||||
}
|
||||
|
||||
public void sendStored(MapleClient c, MapleInventoryType type) {
|
||||
c.announce(MaplePacketCreator.storeStorage(slots, type, typeItems.get(type)));
|
||||
lock.lock();
|
||||
try {
|
||||
c.announce(MaplePacketCreator.storeStorage(slots, type, typeItems.get(type)));
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendTakenOut(MapleClient c, MapleInventoryType type) {
|
||||
c.announce(MaplePacketCreator.takeOutStorage(slots, type, typeItems.get(type)));
|
||||
lock.lock();
|
||||
try {
|
||||
c.announce(MaplePacketCreator.takeOutStorage(slots, type, typeItems.get(type)));
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int getMeso() {
|
||||
@@ -279,6 +292,11 @@ public class MapleStorage {
|
||||
}
|
||||
|
||||
public void close() {
|
||||
typeItems.clear();
|
||||
lock.lock();
|
||||
try {
|
||||
typeItems.clear();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,7 +167,8 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
}
|
||||
int price = (int)Math.min((long)pItem.getPrice() * quantity, Integer.MAX_VALUE);
|
||||
if (c.getPlayer().getMeso() >= price) {
|
||||
if (MapleInventoryManipulator.addFromDrop(c, newItem, false)) {
|
||||
if (MapleInventoryManipulator.checkSpace(c, newItem.getItemId(), newItem.getQuantity(), newItem.getOwner())) {
|
||||
MapleInventoryManipulator.addFromDrop(c, newItem, false);
|
||||
c.getPlayer().gainMeso(-price, false);
|
||||
|
||||
synchronized (sold) {
|
||||
@@ -196,7 +197,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.getPlayer().dropMessage(1, "Your inventory is full. Please clean a slot before buying this item.");
|
||||
c.getPlayer().dropMessage(1, "Your inventory is full. Please clear a slot before buying this item.");
|
||||
}
|
||||
} else {
|
||||
c.getPlayer().dropMessage(1, "You do not have enough mesos.");
|
||||
|
||||
Reference in New Issue
Block a user