Heal GMS + Improved chnl workers & Pshop tooltip + Equips on party HP
Slightly improved channel and disease announce workers performance. Completion of repeatable quests no longer generates fame to players. Equipment drop rates of Leprechaun were slightly decreased. Fixed Pet Item Ignore not checking certain exploit cases correctly. Optimized Pet Item Ignore server handler performance. Fixed some exploits and improved performance on PetLootHandler. Improved concurrency protection on MapleInventoryManipulator. Heal skill effect on players now works GMS-intended, as description says. Also removed the delayed Heal cast effect to others. Fixed party player HPBar not accounting the player's HP stat gained on equips towards the effective MaxHP. The duration of mists generated by mobs has been rescaled to 10x longer than what has been displayed until now (wz duration property is supposed to actually be in 100ms). Optimized timer management for mob skill cooldown and elemental effectiveness. Implemented an additional inventory check system, to be used in cases where it's expected to remove a set group for items (with quantity) to then add a new group of items. Fixed Player Shop/Hired Merchant "vacancy" tooltip, now properly showing whether the store has a visitor room or is already full at that time. Fixed Player Shops only using the standard stand type. Fixed cash pet food ignoring certain pet itemids when reading data from WZ.
This commit is contained in:
@@ -32,7 +32,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import tools.locks.MonitoredReentrantLock;
|
||||
import net.server.audit.locks.MonitoredReentrantLock;
|
||||
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
@@ -47,7 +47,7 @@ import client.inventory.MapleInventoryType;
|
||||
import client.inventory.MaplePet;
|
||||
import constants.ItemConstants;
|
||||
import java.util.Collections;
|
||||
import tools.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
|
||||
/*
|
||||
* @author Flav
|
||||
|
||||
@@ -123,6 +123,7 @@ public class MapleItemInformationProvider {
|
||||
protected Map<Integer, Integer> makerCatalystCache = new HashMap<>();
|
||||
protected Map<Integer, Map<String, Integer>> skillUpgradeCache = new HashMap<>();
|
||||
protected Map<Integer, MapleData> skillUpgradeInfoCache = new HashMap<>();
|
||||
protected Map<Integer, Pair<Integer, Set<Integer>>> cashPetFoodCache = new HashMap<>();
|
||||
|
||||
private MapleItemInformationProvider() {
|
||||
loadCardIdData();
|
||||
@@ -1298,18 +1299,37 @@ public class MapleItemInformationProvider {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public List<Integer> petsCanConsume(int itemId) {
|
||||
List<Integer> ret = new ArrayList<>();
|
||||
MapleData data = getItemData(itemId);
|
||||
int curPetId;
|
||||
for (int i = 0; i < data.getChildren().size(); i++) {
|
||||
curPetId = MapleDataTool.getInt("spec/" + Integer.toString(i), data, 0);
|
||||
if (curPetId == 0) {
|
||||
break;
|
||||
public Pair<Integer, Boolean> canPetConsume(Integer petId, Integer itemId) {
|
||||
Pair<Integer, Set<Integer>> foodData = cashPetFoodCache.get(itemId);
|
||||
|
||||
if(foodData == null) {
|
||||
Set<Integer> pets = new HashSet<>(4);
|
||||
int inc = 1;
|
||||
|
||||
MapleData data = getItemData(itemId);
|
||||
if(data != null) {
|
||||
MapleData specData = data.getChildByPath("spec");
|
||||
for(MapleData specItem : specData.getChildren()) {
|
||||
String itemName = specItem.getName();
|
||||
|
||||
try {
|
||||
Integer.parseInt(itemName); // check if it's a petid node
|
||||
|
||||
Integer petid = MapleDataTool.getInt(specItem, 0);
|
||||
pets.add(petid);
|
||||
} catch(NumberFormatException npe) {
|
||||
if(itemName.contentEquals("inc")) {
|
||||
inc = MapleDataTool.getInt(specItem, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret.add(Integer.valueOf(curPetId));
|
||||
|
||||
foodData = new Pair<>(inc, pets);
|
||||
cashPetFoodCache.put(itemId, foodData);
|
||||
}
|
||||
return ret;
|
||||
|
||||
return new Pair<>(foodData.getLeft(), foodData.getRight().contains(petId));
|
||||
}
|
||||
|
||||
public boolean isQuestItem(int itemId) {
|
||||
|
||||
@@ -718,27 +718,30 @@ public class MapleStatEffect {
|
||||
}
|
||||
|
||||
public boolean applyTo(MapleCharacter chr) {
|
||||
return applyTo(chr, chr, true, null, false);
|
||||
return applyTo(chr, chr, true, null, false, 1);
|
||||
}
|
||||
|
||||
public boolean applyTo(MapleCharacter chr, boolean useMaxRange) {
|
||||
return applyTo(chr, chr, true, null, useMaxRange);
|
||||
return applyTo(chr, chr, true, null, useMaxRange, 1);
|
||||
}
|
||||
|
||||
public boolean applyTo(MapleCharacter chr, Point pos) {
|
||||
return applyTo(chr, chr, true, pos, false);
|
||||
return applyTo(chr, chr, true, pos, false, 1);
|
||||
}
|
||||
|
||||
// primary: the player caster of the buff
|
||||
private boolean applyTo(MapleCharacter applyfrom, MapleCharacter applyto, boolean primary, Point pos, boolean useMaxRange) {
|
||||
private boolean applyTo(MapleCharacter applyfrom, MapleCharacter applyto, boolean primary, Point pos, boolean useMaxRange, int affectedPlayers) {
|
||||
if (skill && (sourceid == GM.HIDE || sourceid == SuperGM.HIDE)) {
|
||||
applyto.toggleHide(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
int hpchange = calcHPChange(applyfrom, primary);
|
||||
int mpchange = calcMPChange(applyfrom, primary);
|
||||
if (primary && isHeal()) {
|
||||
affectedPlayers = applyBuff(applyfrom, useMaxRange);
|
||||
}
|
||||
|
||||
int hpchange = calcHPChange(applyfrom, primary, affectedPlayers);
|
||||
int mpchange = calcMPChange(applyfrom, primary);
|
||||
if (primary) {
|
||||
if (itemConNo != 0) {
|
||||
if(!applyto.getClient().getAbstractPlayerInteraction().hasItem(itemCon, itemConNo)) {
|
||||
@@ -747,9 +750,7 @@ public class MapleStatEffect {
|
||||
}
|
||||
MapleInventoryManipulator.removeById(applyto.getClient(), ItemConstants.getInventoryType(itemCon), itemCon, itemConNo, false, true);
|
||||
}
|
||||
}
|
||||
List<Pair<MapleStat, Integer>> hpmpupdate = new ArrayList<>(2);
|
||||
if (!primary) {
|
||||
} else {
|
||||
if(isResurrection()) {
|
||||
hpchange = applyto.getMaxHp();
|
||||
applyto.setStance(0);
|
||||
@@ -758,6 +759,7 @@ public class MapleStatEffect {
|
||||
applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.spawnPlayerMapObject(applyto), false);
|
||||
}
|
||||
}
|
||||
|
||||
if (isDispel() && makeChanceResult()) {
|
||||
applyto.dispelDebuffs();
|
||||
} else if (isCureAllAbnormalStatus()) {
|
||||
@@ -770,6 +772,8 @@ public class MapleStatEffect {
|
||||
/*if (applyfrom.getMp() < getMpCon()) {
|
||||
AutobanFactory.MPCON.addPoint(applyfrom.getAutobanManager(), "mpCon hack for skill:" + sourceid + "; Player MP: " + applyto.getMp() + " MP Needed: " + getMpCon());
|
||||
} */
|
||||
|
||||
List<Pair<MapleStat, Integer>> hpmpupdate = new ArrayList<>(2);
|
||||
if (hpchange != 0) {
|
||||
if (hpchange < 0 && (-hpchange) >= applyto.getHp() && (!applyto.hasDisease(MapleDisease.ZOMBIFY) || hpCon > 0)) {
|
||||
if(!applyto.isGM()) {
|
||||
@@ -784,8 +788,9 @@ public class MapleStatEffect {
|
||||
applyto.setHp(newHp);
|
||||
hpmpupdate.add(new Pair<>(MapleStat.HP, Integer.valueOf(applyto.getHp())));
|
||||
}
|
||||
int newMp = applyto.getMp() + mpchange;
|
||||
|
||||
if (mpchange != 0) {
|
||||
int newMp = applyto.getMp() + mpchange;
|
||||
if (mpchange < 0 && -mpchange > applyto.getMp()) {
|
||||
if(!applyto.isGM()) {
|
||||
applyto.getClient().announce(MaplePacketCreator.enableActions());
|
||||
@@ -860,14 +865,16 @@ public class MapleStatEffect {
|
||||
applyBuffEffect(applyfrom, applyto, primary);
|
||||
}
|
||||
|
||||
if (primary && (overTime || isHeal())) {
|
||||
applyBuff(applyfrom, useMaxRange);
|
||||
}
|
||||
if (primary) {
|
||||
if (overTime) {
|
||||
applyBuff(applyfrom, useMaxRange);
|
||||
}
|
||||
|
||||
if (primary && isMonsterBuff()) {
|
||||
applyMonsterBuff(applyfrom);
|
||||
if (isMonsterBuff()) {
|
||||
applyMonsterBuff(applyfrom);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (this.getFatigue() != 0) {
|
||||
applyto.getMount().setTiredness(applyto.getMount().getTiredness() + this.getFatigue());
|
||||
}
|
||||
@@ -927,7 +934,9 @@ public class MapleStatEffect {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void applyBuff(MapleCharacter applyfrom, boolean useMaxRange) {
|
||||
private int applyBuff(MapleCharacter applyfrom, boolean useMaxRange) {
|
||||
int affectedc = 1;
|
||||
|
||||
if (isPartyBuff() && (applyfrom.getParty() != null || isGmBuff())) {
|
||||
Rectangle bounds = (!useMaxRange) ? calculateBoundingBox(applyfrom.getPosition(), applyfrom.isFacingLeft()) : new Rectangle(Integer.MIN_VALUE / 2, Integer.MIN_VALUE / 2, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
List<MapleMapObject> affecteds = applyfrom.getMap().getMapObjectsInRect(bounds, Arrays.asList(MapleMapObjectType.PLAYER));
|
||||
@@ -935,17 +944,27 @@ public class MapleStatEffect {
|
||||
for (MapleMapObject affectedmo : affecteds) {
|
||||
MapleCharacter affected = (MapleCharacter) affectedmo;
|
||||
if (affected != applyfrom && (isGmBuff() || applyfrom.getParty().equals(affected.getParty()))) {
|
||||
if ((!isResurrection() && affected.isAlive()) || (isResurrection() && !affected.isAlive())) {
|
||||
affectedp.add(affected);
|
||||
if (!isResurrection()) {
|
||||
if (affected.isAlive()) {
|
||||
affectedp.add(affected);
|
||||
}
|
||||
} else {
|
||||
if (!affected.isAlive()) {
|
||||
affectedp.add(affected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
affectedc += affectedp.size(); // used for heal
|
||||
for (MapleCharacter affected : affectedp) {
|
||||
applyTo(applyfrom, affected, false, null, useMaxRange);
|
||||
applyTo(applyfrom, affected, false, null, useMaxRange, affectedc);
|
||||
affected.getClient().announce(MaplePacketCreator.showOwnBuffEffect(sourceid, 2));
|
||||
affected.getMap().broadcastMessage(affected, MaplePacketCreator.showBuffeffect(affected.getId(), sourceid, 2), false);
|
||||
}
|
||||
}
|
||||
|
||||
return affectedc;
|
||||
}
|
||||
|
||||
private void applyMonsterBuff(MapleCharacter applyfrom) {
|
||||
@@ -1158,7 +1177,7 @@ public class MapleStatEffect {
|
||||
}
|
||||
}
|
||||
|
||||
private int calcHPChange(MapleCharacter applyfrom, boolean primary) {
|
||||
private int calcHPChange(MapleCharacter applyfrom, boolean primary, int affectedPlayers) {
|
||||
int hpchange = 0;
|
||||
if (hp != 0) {
|
||||
if (!skill) {
|
||||
@@ -1171,7 +1190,8 @@ public class MapleStatEffect {
|
||||
hpchange /= 2;
|
||||
}
|
||||
} else { // assumption: this is heal
|
||||
hpchange += makeHealHP(hp / 100.0, applyfrom.getTotalMagic(), 3, 5);
|
||||
float hpHeal = (applyfrom.getMaxHpEquipped() * (float) hp / (100.0f * affectedPlayers));
|
||||
hpchange += hpHeal;
|
||||
if (applyfrom.hasDisease(MapleDisease.ZOMBIFY)) {
|
||||
hpchange = -hpchange;
|
||||
hpCon = 0;
|
||||
|
||||
@@ -39,11 +39,11 @@ import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import tools.locks.MonitoredReentrantLock;
|
||||
import net.server.audit.locks.MonitoredReentrantLock;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.Pair;
|
||||
import tools.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -55,7 +55,7 @@ import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import tools.locks.MonitoredReentrantLock;
|
||||
import net.server.audit.locks.MonitoredReentrantLock;
|
||||
import net.server.Server;
|
||||
import net.server.channel.Channel;
|
||||
import net.server.world.World;
|
||||
@@ -70,7 +70,7 @@ import server.maps.MapleMapObjectType;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.Pair;
|
||||
import tools.Randomizer;
|
||||
import tools.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
|
||||
public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
private ChangeableStats ostats = null; //unused, v83 WZs offers no support for changeable stats.
|
||||
@@ -1248,14 +1248,15 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
}
|
||||
|
||||
final MapleMonster mons = this;
|
||||
TimerManager.getInstance().schedule(
|
||||
new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mons.clearSkill(skillId, level);
|
||||
}
|
||||
}, cooltime);
|
||||
MapleMap mmap = mons.getMap();
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mons.clearSkill(skillId, level);
|
||||
}
|
||||
};
|
||||
|
||||
mmap.getChannelServer().registerMobClearSkillAction(mmap.getId(), r, cooltime);
|
||||
}
|
||||
|
||||
public void clearSkill(int skillId, int level) {
|
||||
@@ -1359,8 +1360,9 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
final ElementalEffectiveness fEE = stats.getEffectiveness(e);
|
||||
if (!fEE.equals(ElementalEffectiveness.WEAK)) {
|
||||
stats.setEffectiveness(e, ee);
|
||||
TimerManager.getInstance().schedule(new Runnable() {
|
||||
|
||||
|
||||
MapleMap mmap = this.getMap();
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
monsterLock.lock();
|
||||
@@ -1371,7 +1373,9 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
monsterLock.unlock();
|
||||
}
|
||||
}
|
||||
}, milli);
|
||||
};
|
||||
|
||||
mmap.getChannelServer().registerMobClearSkillAction(mmap.getId(), r, milli);
|
||||
}
|
||||
} finally {
|
||||
monsterLock.unlock();
|
||||
|
||||
@@ -196,7 +196,7 @@ public class MobSkill {
|
||||
}
|
||||
break;
|
||||
case 131: // Mist
|
||||
monster.getMap().spawnMist(new MapleMist(calculateBoundingBox(monster.getPosition(), true), monster, this), x * 10, false, false, false);
|
||||
monster.getMap().spawnMist(new MapleMist(calculateBoundingBox(monster.getPosition(), true), monster, this), x * 100, false, false, false);
|
||||
break;
|
||||
case 132:
|
||||
disease = MapleDisease.CONFUSE;
|
||||
|
||||
@@ -27,15 +27,15 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import tools.locks.MonitoredReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import tools.locks.MonitoredLockType;
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -27,8 +27,8 @@ import scripting.portal.PortalScriptManager;
|
||||
import server.MaplePortal;
|
||||
import tools.MaplePacketCreator;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import tools.locks.MonitoredLockType;
|
||||
import tools.locks.MonitoredReentrantLock;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredReentrantLock;
|
||||
|
||||
public class MapleGenericPortal implements MaplePortal {
|
||||
|
||||
|
||||
@@ -40,13 +40,13 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import tools.locks.MonitoredReentrantLock;
|
||||
import net.server.audit.locks.MonitoredReentrantLock;
|
||||
import net.server.Server;
|
||||
import server.MapleItemInformationProvider;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.Pair;
|
||||
import tools.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -67,7 +67,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
private MapleMap map;
|
||||
private Lock visitorLock = new MonitoredReentrantLock(MonitoredLockType.VISITOR_MERCH, true);
|
||||
|
||||
public MapleHiredMerchant(final MapleCharacter owner, int itemId, String desc) {
|
||||
public MapleHiredMerchant(final MapleCharacter owner, String desc, int itemId) {
|
||||
this.setPosition(owner.getPosition());
|
||||
this.start = System.currentTimeMillis();
|
||||
this.ownerId = owner.getId();
|
||||
@@ -96,6 +96,22 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getShopRoomInfo() {
|
||||
visitorLock.lock();
|
||||
try {
|
||||
byte count = 0;
|
||||
for (MapleCharacter visitor : visitors) {
|
||||
if (visitor != null) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return new byte[]{count, (byte) (visitors.length + 1)};
|
||||
} finally {
|
||||
visitorLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addVisitor(MapleCharacter visitor) {
|
||||
visitorLock.lock();
|
||||
try {
|
||||
@@ -103,6 +119,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
if (i > -1) {
|
||||
visitors[i] = visitor;
|
||||
broadcastToVisitors(MaplePacketCreator.hiredMerchantVisitorAdd(visitor, i + 1));
|
||||
this.getMap().broadcastMessage(MaplePacketCreator.updateHiredMerchantBox(this));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -123,6 +140,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
if (visitors[slot] != null && visitors[slot].getId() == visitor.getId()) {
|
||||
visitors[slot] = null;
|
||||
broadcastToVisitors(MaplePacketCreator.hiredMerchantVisitorLeave(slot + 1));
|
||||
this.getMap().broadcastMessage(MaplePacketCreator.updateHiredMerchantBox(this));
|
||||
}
|
||||
} finally {
|
||||
visitorLock.unlock();
|
||||
@@ -151,15 +169,19 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
visitorLock.lock();
|
||||
try {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] != null) {
|
||||
visitors[i].setHiredMerchant(null);
|
||||
MapleCharacter visitor = visitors[i];
|
||||
|
||||
if (visitor != null) {
|
||||
visitor.setHiredMerchant(null);
|
||||
|
||||
visitors[i].getClient().announce(MaplePacketCreator.leaveHiredMerchant(i + 1, 0x11));
|
||||
visitors[i].getClient().announce(MaplePacketCreator.hiredMerchantMaintenanceMessage());
|
||||
visitor.getClient().announce(MaplePacketCreator.leaveHiredMerchant(i + 1, 0x11));
|
||||
visitor.getClient().announce(MaplePacketCreator.hiredMerchantMaintenanceMessage());
|
||||
|
||||
visitors[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
this.getMap().broadcastMessage(MaplePacketCreator.updateHiredMerchantBox(this));
|
||||
} finally {
|
||||
visitorLock.unlock();
|
||||
}
|
||||
@@ -272,7 +294,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
|
||||
public void forceClose() {
|
||||
//Server.getInstance().getChannel(world, channel).removeHiredMerchant(ownerId);
|
||||
map.broadcastMessage(MaplePacketCreator.destroyHiredMerchant(getOwnerId()));
|
||||
map.broadcastMessage(MaplePacketCreator.removeHiredMerchantBox(getOwnerId()));
|
||||
map.removeMapObject(this);
|
||||
|
||||
MapleCharacter owner = Server.getInstance().getWorld(world).getPlayerStorage().getCharacterById(ownerId);
|
||||
@@ -331,7 +353,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
|
||||
public void closeShop(MapleClient c, boolean timeout) {
|
||||
map.removeMapObject(this);
|
||||
map.broadcastMessage(MaplePacketCreator.destroyHiredMerchant(ownerId));
|
||||
map.broadcastMessage(MaplePacketCreator.removeHiredMerchantBox(ownerId));
|
||||
c.getChannelServer().removeHiredMerchant(ownerId);
|
||||
|
||||
try {
|
||||
@@ -634,7 +656,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
|
||||
@Override
|
||||
public void sendSpawnData(MapleClient client) {
|
||||
client.announce(MaplePacketCreator.spawnHiredMerchant(this));
|
||||
client.announce(MaplePacketCreator.spawnHiredMerchantBox(this));
|
||||
}
|
||||
|
||||
public class SoldItem {
|
||||
|
||||
@@ -52,9 +52,10 @@ import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import tools.locks.MonitoredReentrantLock;
|
||||
import tools.locks.MonitoredReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredReentrantLock;
|
||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||
@@ -90,7 +91,6 @@ import tools.FilePrinter;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.Pair;
|
||||
import tools.Randomizer;
|
||||
import tools.locks.MonitoredLockType;
|
||||
|
||||
public class MapleMap {
|
||||
private static final List<MapleMapObjectType> rangedMapobjectTypes = Arrays.asList(MapleMapObjectType.SHOP, MapleMapObjectType.ITEM, MapleMapObjectType.NPC, MapleMapObjectType.MONSTER, MapleMapObjectType.DOOR, MapleMapObjectType.SUMMON, MapleMapObjectType.REACTOR);
|
||||
@@ -1512,8 +1512,10 @@ public class MapleMap {
|
||||
chrRLock.lock();
|
||||
try {
|
||||
for (MapleCharacter chr : characters) {
|
||||
if (!chr.isHidden() && (chr.getControlledMonsters().size() < mincontrolled || mincontrolled == -1)) {
|
||||
mincontrolled = chr.getControlledMonsters().size();
|
||||
int ctrlMonsSize = chr.getControlledMonsters().size();
|
||||
|
||||
if (!chr.isHidden() && (ctrlMonsSize < mincontrolled || mincontrolled == -1)) {
|
||||
mincontrolled = ctrlMonsSize;
|
||||
newController = chr;
|
||||
}
|
||||
}
|
||||
@@ -1538,8 +1540,7 @@ public class MapleMap {
|
||||
objectRLock.lock();
|
||||
try {
|
||||
return new LinkedList(mapobjects.values());
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
objectRLock.unlock();
|
||||
}
|
||||
}
|
||||
@@ -1997,8 +1998,9 @@ public class MapleMap {
|
||||
poisonSchedule = tMan.register(poisonTask, 2000, 2500);
|
||||
} else {
|
||||
poisonSchedule = null;
|
||||
}
|
||||
tMan.schedule(new Runnable() {
|
||||
}
|
||||
|
||||
Runnable mistSchedule = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
removeMapObject(mist);
|
||||
@@ -2007,7 +2009,9 @@ public class MapleMap {
|
||||
}
|
||||
broadcastMessage(mist.makeDestroyData());
|
||||
}
|
||||
}, duration);
|
||||
};
|
||||
|
||||
this.getChannelServer().registerMobMistCancelAction(mapid, mistSchedule, duration);
|
||||
}
|
||||
|
||||
public void spawnKite(final MapleKite kite) {
|
||||
@@ -2899,8 +2903,7 @@ public class MapleMap {
|
||||
}
|
||||
|
||||
return mapChars;
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
chrRLock.unlock();
|
||||
}
|
||||
}
|
||||
@@ -2909,8 +2912,7 @@ public class MapleMap {
|
||||
chrRLock.lock();
|
||||
try {
|
||||
return Collections.unmodifiableCollection(this.characters);
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
chrRLock.unlock();
|
||||
}
|
||||
}
|
||||
@@ -2929,7 +2931,7 @@ public class MapleMap {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void updateMapObjectVisibility(MapleCharacter chr, MapleMapObject mo) {
|
||||
private static void updateMapObjectVisibility(MapleCharacter chr, MapleMapObject mo) {
|
||||
if (!chr.isMapObjectVisible(mo)) { // item entered view range
|
||||
if (mo.getType() == MapleMapObjectType.SUMMON || mo.getPosition().distanceSq(chr.getPosition()) <= getRangedDistance()) {
|
||||
chr.addVisibleMapObject(mo);
|
||||
@@ -3291,8 +3293,7 @@ public class MapleMap {
|
||||
if(characters.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
chrRLock.unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -33,10 +33,11 @@ import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import tools.locks.MonitoredReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataTool;
|
||||
@@ -49,7 +50,7 @@ import server.life.MaplePlayerNPCFactory;
|
||||
import scripting.event.EventInstanceManager;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.StringUtil;
|
||||
import tools.locks.MonitoredLockType;
|
||||
|
||||
|
||||
public class MapleMapFactory {
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ import client.MapleClient;
|
||||
import client.inventory.Item;
|
||||
import java.awt.Point;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import tools.locks.MonitoredReentrantLock;
|
||||
import net.server.audit.locks.MonitoredReentrantLock;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
|
||||
public class MapleMapItem extends AbstractMapleMapObject {
|
||||
protected MapleClient ownerClient;
|
||||
|
||||
@@ -26,9 +26,9 @@ import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import tools.locks.MonitoredReentrantLock;
|
||||
import net.server.audit.locks.MonitoredReentrantLock;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -37,13 +37,12 @@ import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import tools.locks.MonitoredReentrantLock;
|
||||
import net.server.audit.locks.MonitoredReentrantLock;
|
||||
import net.opcodes.SendOpcode;
|
||||
import server.MapleItemInformationProvider;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.Pair;
|
||||
import tools.data.output.MaplePacketLittleEndianWriter;
|
||||
import tools.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -53,6 +52,8 @@ import tools.locks.MonitoredLockType;
|
||||
public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
private AtomicBoolean open = new AtomicBoolean(false);
|
||||
private MapleCharacter owner;
|
||||
private int itemid;
|
||||
|
||||
private MapleCharacter[] visitors = new MapleCharacter[3];
|
||||
private List<MaplePlayerShopItem> items = new ArrayList<>();
|
||||
private List<SoldItem> sold = new LinkedList<>();
|
||||
@@ -63,10 +64,11 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
private Map<Integer, Byte> chatSlot = new LinkedHashMap<>();
|
||||
private Lock visitorLock = new MonitoredReentrantLock(MonitoredLockType.VISITOR_PSHOP, true);
|
||||
|
||||
public MaplePlayerShop(MapleCharacter owner, String description) {
|
||||
public MaplePlayerShop(MapleCharacter owner, String description, int itemid) {
|
||||
this.setPosition(owner.getPosition());
|
||||
this.owner = owner;
|
||||
this.description = description;
|
||||
this.itemid = itemid;
|
||||
}
|
||||
|
||||
public int getChannel() {
|
||||
@@ -77,6 +79,10 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
return owner.getMapId();
|
||||
}
|
||||
|
||||
public int getItemId() {
|
||||
return itemid;
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return open.get();
|
||||
}
|
||||
@@ -93,6 +99,22 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
visitorLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getShopRoomInfo() {
|
||||
visitorLock.lock();
|
||||
try {
|
||||
byte count = 0;
|
||||
for (MapleCharacter visitor : visitors) {
|
||||
if (visitor != null) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return new byte[]{count, (byte) visitors.length};
|
||||
} finally {
|
||||
visitorLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOwner(MapleCharacter c) {
|
||||
return owner.equals(c);
|
||||
@@ -103,9 +125,9 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
if (visitors[i] == null) {
|
||||
visitors[i] = visitor;
|
||||
visitor.setSlot(i);
|
||||
|
||||
this.broadcast(MaplePacketCreator.getPlayerShopNewVisitor(visitor, i + 1));
|
||||
|
||||
if(i == 2) visitor.getMap().broadcastMessage(MaplePacketCreator.addCharBox(owner, 1));
|
||||
owner.getMap().broadcastMessage(MaplePacketCreator.updatePlayerShopBox(this));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -123,7 +145,9 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
if (visitors[i] != null && visitors[i].getId() == visitor.getId()) {
|
||||
visitors[i] = null;
|
||||
visitor.setSlot(-1);
|
||||
|
||||
this.broadcast(MaplePacketCreator.getPlayerShopRemoveVisitor(i + 1));
|
||||
owner.getMap().broadcastMessage(MaplePacketCreator.updatePlayerShopBox(this));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -154,6 +178,7 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
this.broadcastRestoreToVisitors();
|
||||
owner.getMap().broadcastMessage(MaplePacketCreator.updatePlayerShopBox(this));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -161,7 +186,7 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
visitorLock.unlock();
|
||||
}
|
||||
|
||||
if(owner.getPlayerShop() != null) visitor.getMap().broadcastMessage(MaplePacketCreator.addCharBox(owner, 4));
|
||||
owner.getMap().broadcastMessage(MaplePacketCreator.updatePlayerShopBox(this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,7 +419,7 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
public void closeShop() {
|
||||
owner.getMap().broadcastMessage(MaplePacketCreator.removeCharBox(owner));
|
||||
owner.getMap().broadcastMessage(MaplePacketCreator.removePlayerShopBox(this));
|
||||
clearChatLog();
|
||||
removeVisitors();
|
||||
}
|
||||
@@ -527,12 +552,12 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
|
||||
@Override
|
||||
public void sendDestroyData(MapleClient client) {
|
||||
client.announce(MaplePacketCreator.removeCharBox(owner));
|
||||
client.announce(MaplePacketCreator.removePlayerShopBox(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSpawnData(MapleClient client) {
|
||||
client.announce(MaplePacketCreator.addCharBox(owner, 4));
|
||||
client.announce(MaplePacketCreator.updatePlayerShopBox(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -29,13 +29,13 @@ import java.util.List;
|
||||
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import tools.locks.MonitoredReentrantLock;
|
||||
import net.server.audit.locks.MonitoredReentrantLock;
|
||||
|
||||
import scripting.reactor.ReactorScriptManager;
|
||||
import server.TimerManager;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.Pair;
|
||||
import tools.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -54,7 +54,7 @@ public class MapleQuest {
|
||||
|
||||
private static final Set<Short> exploitableQuests = new HashSet<>();
|
||||
static {
|
||||
exploitableQuests.add((short) 2338);
|
||||
exploitableQuests.add((short) 2338); // there are a lot more exploitable quests, they need to be nit-picked
|
||||
exploitableQuests.add((short) 3637);
|
||||
exploitableQuests.add((short) 3714);
|
||||
exploitableQuests.add((short) 21752);
|
||||
@@ -106,25 +106,22 @@ public class MapleQuest {
|
||||
MapleQuestRequirementType type = MapleQuestRequirementType.getByWZName(startReq.getName());
|
||||
if (type.equals(MapleQuestRequirementType.INTERVAL)) {
|
||||
repeatable = true;
|
||||
}
|
||||
|
||||
if (type.equals(MapleQuestRequirementType.INFO_NUMBER)) {
|
||||
} else if (type.equals(MapleQuestRequirementType.INFO_NUMBER)) {
|
||||
infoNumber = (short) MapleDataTool.getInt(startReq, 0);
|
||||
}
|
||||
|
||||
MapleQuestRequirement req = this.getRequirement(type, startReq);
|
||||
|
||||
if(req == null)
|
||||
continue;
|
||||
|
||||
if (type.equals(MapleQuestRequirementType.MOB)) {
|
||||
} else if (type.equals(MapleQuestRequirementType.MOB)) {
|
||||
for (MapleData mob : startReq.getChildren()) {
|
||||
relevantMobs.add(MapleDataTool.getInt(mob.getChildByPath("id")));
|
||||
}
|
||||
}
|
||||
|
||||
MapleQuestRequirement req = this.getRequirement(type, startReq);
|
||||
if(req == null)
|
||||
continue;
|
||||
|
||||
startReqs.put(type, req);
|
||||
}
|
||||
}
|
||||
|
||||
MapleData completeReqData = reqData.getChildByPath("1");
|
||||
if (completeReqData != null) {
|
||||
for (MapleData completeReq : completeReqData.getChildren()) {
|
||||
@@ -136,8 +133,7 @@ public class MapleQuest {
|
||||
|
||||
if (type.equals(MapleQuestRequirementType.INFO_NUMBER)) {
|
||||
infoNumber = (short) MapleDataTool.getInt(completeReq, 0);
|
||||
}
|
||||
if (type.equals(MapleQuestRequirementType.MOB)) {
|
||||
} else if (type.equals(MapleQuestRequirementType.MOB)) {
|
||||
for (MapleData mob : completeReq.getChildren()) {
|
||||
relevantMobs.add(MapleDataTool.getInt(mob.getChildByPath("id")));
|
||||
}
|
||||
@@ -175,13 +171,13 @@ public class MapleQuest {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAutoComplete() {
|
||||
return autoPreComplete || autoComplete;
|
||||
}
|
||||
|
||||
public boolean isAutoStart() {
|
||||
return autoStart;
|
||||
}
|
||||
public boolean isAutoComplete() {
|
||||
return autoPreComplete || autoComplete;
|
||||
}
|
||||
|
||||
public boolean isAutoStart() {
|
||||
return autoStart;
|
||||
}
|
||||
|
||||
public static MapleQuest getInstance(int id) {
|
||||
MapleQuest ret = quests.get(id);
|
||||
@@ -226,7 +222,14 @@ public class MapleQuest {
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
|
||||
public boolean isSameDayRepeatable() {
|
||||
if(!repeatable) return false;
|
||||
|
||||
IntervalRequirement ir = (IntervalRequirement) startReqs.get(MapleQuestRequirementType.INTERVAL);
|
||||
return ir.getInterval() < ServerConstants.FAME_GAIN_MIN_HOUR_INTERVAL * 60 * 60 * 1000;
|
||||
}
|
||||
|
||||
public boolean canStartWithoutRequirements(MapleCharacter c) {
|
||||
MapleQuestStatus mqs = c.getQuest(this);
|
||||
return !(mqs.getStatus() != Status.NOT_STARTED && !(mqs.getStatus() == Status.COMPLETED && repeatable));
|
||||
|
||||
@@ -212,7 +212,7 @@ public class ItemAction extends MapleQuestAction {
|
||||
for(Pair<Item, MapleInventoryType> it: randomList) {
|
||||
int idx = it.getRight().getType() - 1;
|
||||
|
||||
result = MapleInventoryManipulator.checkSpaceProgressively(c, it.getLeft().getItemId(), it.getLeft().getQuantity(), "", rndUsed.get(idx));
|
||||
result = MapleInventoryManipulator.checkSpaceProgressively(c, it.getLeft().getItemId(), it.getLeft().getQuantity(), "", rndUsed.get(idx), false);
|
||||
if(result % 2 == 0) {
|
||||
chr.dropMessage(1, "Please check if you have enough space in your inventory.");
|
||||
return false;
|
||||
@@ -227,7 +227,7 @@ public class ItemAction extends MapleQuestAction {
|
||||
gainList.add(selected);
|
||||
}
|
||||
|
||||
if (!MapleInventory.checkSpots(chr, gainList, allSlotUsed)) {
|
||||
if (!MapleInventory.checkSpots(chr, gainList, allSlotUsed, false)) {
|
||||
chr.dropMessage(1, "Please check if you have enough space in your inventory.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user