Persistent diseases + PQ request system + GuildPQ fix
Implemented persistent diseases. Players now keep their disease status when logging out the game. Solved several concurrent access issues in MapleMap and MapleMonster. Implemented an option where an account's character slots can be accounted either by each world or all-server range. Fixed some issues with character slot count when entering/exiting Cash Shop. Fixed an exploit with Papulatus, on where players could create cracks of dimension infinitely. Solved an issue with the "reach" command not working properly when the targeted player is on an event instance. Devised an advanced and secure "PQ request" system. The service revolves around expecting massive number of players requesting a "pass" simultaneously, and fairly & swiftly responsing as much people as possible. Improved overall Whisper handler performance. Fixed GPQ Stage 1 statues not working as expected, which rendered the instance unplayable until now. Added commands for start, complete and reset quests.
This commit is contained in:
@@ -38,7 +38,7 @@ import client.MapleCharacter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Alan (SharpAceX)
|
||||
*/
|
||||
public class MapleExpedition {
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import constants.ServerConstants;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Alan (SharpAceX)
|
||||
*/
|
||||
|
||||
public enum MapleExpeditionType {
|
||||
|
||||
@@ -2,7 +2,7 @@ package server.gachapon;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Alan (SharpAceX)
|
||||
*/
|
||||
|
||||
public class Ellinia extends GachaponItems {
|
||||
|
||||
@@ -24,7 +24,7 @@ package server.gachapon;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Alan (SharpAceX)
|
||||
*/
|
||||
|
||||
public abstract class GachaponItems {
|
||||
|
||||
@@ -2,7 +2,7 @@ package server.gachapon;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Alan (SharpAceX)
|
||||
*/
|
||||
|
||||
public class Global extends GachaponItems {
|
||||
|
||||
@@ -2,7 +2,7 @@ package server.gachapon;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Alan (SharpAceX)
|
||||
*/
|
||||
|
||||
public class Henesys extends GachaponItems {
|
||||
|
||||
@@ -2,7 +2,7 @@ package server.gachapon;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Alan (SharpAceX)
|
||||
*/
|
||||
|
||||
public class KerningCity extends GachaponItems {
|
||||
|
||||
@@ -25,7 +25,7 @@ import tools.Randomizer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Alan (SharpAceX)
|
||||
*/
|
||||
public class MapleGachapon {
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package server.gachapon;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Alan (SharpAceX)
|
||||
*/
|
||||
|
||||
public class MushroomShrine extends GachaponItems {
|
||||
|
||||
@@ -2,7 +2,7 @@ package server.gachapon;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Alan (SharpAceX)
|
||||
*/
|
||||
|
||||
public class NautilusHarbor extends GachaponItems {
|
||||
|
||||
@@ -2,7 +2,7 @@ package server.gachapon;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Alan (SharpAceX)
|
||||
*/
|
||||
|
||||
public class NewLeafCity extends GachaponItems {
|
||||
|
||||
@@ -2,7 +2,7 @@ package server.gachapon;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Alan (SharpAceX)
|
||||
*/
|
||||
|
||||
public class Perion extends GachaponItems {
|
||||
|
||||
@@ -2,7 +2,7 @@ package server.gachapon;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Alan (SharpAceX)
|
||||
*/
|
||||
|
||||
public class ShowaSpaFemale extends GachaponItems {
|
||||
|
||||
@@ -2,7 +2,7 @@ package server.gachapon;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Alan (SharpAceX)
|
||||
*/
|
||||
|
||||
public class ShowaSpaMale extends GachaponItems {
|
||||
|
||||
@@ -2,7 +2,7 @@ package server.gachapon;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Alan (SharpAceX)
|
||||
*/
|
||||
|
||||
public class Sleepywood extends GachaponItems {
|
||||
|
||||
@@ -156,7 +156,8 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
return hp.get();
|
||||
}
|
||||
|
||||
public void addHp(int hp) {
|
||||
public synchronized void addHp(int hp) {
|
||||
if(this.hp.get() <= 0) return;
|
||||
this.hp.addAndGet(hp);
|
||||
}
|
||||
|
||||
@@ -287,6 +288,10 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void disposeMapObject() { // mob is no longer associated with the map it was in
|
||||
hp.set(-1);
|
||||
}
|
||||
|
||||
public void broadcastMobHpBar(MapleCharacter from) {
|
||||
if (hasBossHPBar()) {
|
||||
from.setPlayerAggro(this.hashCode());
|
||||
@@ -307,13 +312,58 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean damage(MapleCharacter attacker, int damage, boolean stayAlive) {
|
||||
boolean lastHit = false;
|
||||
|
||||
this.lockMonster();
|
||||
try {
|
||||
if (!this.isAlive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* pyramid not implemented
|
||||
Pair<Integer, Integer> cool = this.getStats().getCool();
|
||||
if (cool != null) {
|
||||
Pyramid pq = (Pyramid) chr.getPartyQuest();
|
||||
if (pq != null) {
|
||||
if (damage > 0) {
|
||||
if (damage >= cool.getLeft()) {
|
||||
if ((Math.random() * 100) < cool.getRight()) {
|
||||
pq.cool();
|
||||
} else {
|
||||
pq.kill();
|
||||
}
|
||||
} else {
|
||||
pq.kill();
|
||||
}
|
||||
} else {
|
||||
pq.miss();
|
||||
}
|
||||
killed = true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (damage > 0) {
|
||||
this.applyDamage(attacker, damage, stayAlive);
|
||||
if (!this.isAlive()) { // monster just died
|
||||
lastHit = true;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this.unlockMonster();
|
||||
}
|
||||
|
||||
return lastHit;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param from the player that dealt the damage
|
||||
* @param damage
|
||||
* @param stayAlive
|
||||
*/
|
||||
public synchronized void damage(MapleCharacter from, int damage, boolean stayAlive) {
|
||||
private void applyDamage(MapleCharacter from, int damage, boolean stayAlive) {
|
||||
Integer trueDamage = applyAndGetHpDamage(damage, stayAlive);
|
||||
if (trueDamage == null) {
|
||||
return;
|
||||
@@ -628,10 +678,8 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void dispatchMonsterKilled(boolean hasKiller) {
|
||||
if(!hasKiller) {
|
||||
dispatchUpdateQuestMobCount();
|
||||
}
|
||||
public void dispatchMonsterKilled(boolean hasKiller) {
|
||||
processMonsterKilled(hasKiller);
|
||||
|
||||
EventInstanceManager eim = getMap().getEventInstance();
|
||||
if (eim != null) {
|
||||
@@ -641,6 +689,12 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
eim.friendlyKilled(this, hasKiller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void processMonsterKilled(boolean hasKiller) {
|
||||
if(!hasKiller) {
|
||||
dispatchUpdateQuestMobCount();
|
||||
}
|
||||
|
||||
MonsterListener[] listenersList;
|
||||
statiLock.lock();
|
||||
@@ -1321,7 +1375,13 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
}
|
||||
}
|
||||
if (damage > 0) {
|
||||
damage(chr, damage, true);
|
||||
lockMonster();
|
||||
try {
|
||||
applyDamage(chr, damage, true);
|
||||
} finally {
|
||||
unlockMonster();
|
||||
}
|
||||
|
||||
if (type == 1) {
|
||||
map.broadcastMessage(MaplePacketCreator.damageMonster(getObjectId(), damage), getPosition());
|
||||
} else if (type == 2) {
|
||||
|
||||
@@ -24,6 +24,7 @@ package server.life;
|
||||
import client.MapleCharacter;
|
||||
import java.awt.Point;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import net.server.Server;
|
||||
|
||||
public class SpawnPoint {
|
||||
private int monster, mobTime, team, fh, f;
|
||||
@@ -42,7 +43,7 @@ public class SpawnPoint {
|
||||
this.f = monster.getF();
|
||||
this.immobile = immobile;
|
||||
this.mobInterval = mobInterval;
|
||||
this.nextPossibleSpawn = System.currentTimeMillis();
|
||||
this.nextPossibleSpawn = Server.getInstance().getCurrentTime();
|
||||
}
|
||||
|
||||
public int getSpawned() {
|
||||
@@ -61,7 +62,7 @@ public class SpawnPoint {
|
||||
if (denySpawn || mobTime < 0 || spawnedMonsters.get() > 0) {
|
||||
return false;
|
||||
}
|
||||
return nextPossibleSpawn <= System.currentTimeMillis();
|
||||
return nextPossibleSpawn <= Server.getInstance().getCurrentTime();
|
||||
}
|
||||
|
||||
public boolean shouldForceSpawn() {
|
||||
@@ -82,7 +83,7 @@ public class SpawnPoint {
|
||||
mob.addListener(new MonsterListener() {
|
||||
@Override
|
||||
public void monsterKilled(int aniTime) {
|
||||
nextPossibleSpawn = System.currentTimeMillis();
|
||||
nextPossibleSpawn = Server.getInstance().getCurrentTime();
|
||||
if (mobTime > 0) {
|
||||
nextPossibleSpawn += mobTime * 1000;
|
||||
} else {
|
||||
@@ -98,7 +99,7 @@ public class SpawnPoint {
|
||||
public void monsterHealed(int trueHeal) {}
|
||||
});
|
||||
if (mobTime == 0) {
|
||||
nextPossibleSpawn = System.currentTimeMillis() + mobInterval;
|
||||
nextPossibleSpawn = Server.getInstance().getCurrentTime() + mobInterval;
|
||||
}
|
||||
return mob;
|
||||
}
|
||||
|
||||
+124
-160
@@ -295,28 +295,21 @@ public class MapleMap {
|
||||
public int getTimeLeft() {
|
||||
return (int) ((timeLimit - System.currentTimeMillis()) / 1000);
|
||||
}
|
||||
|
||||
|
||||
public void setReactorState() {
|
||||
chrRLock.lock();
|
||||
objectRLock.lock();
|
||||
try {
|
||||
for (MapleMapObject o : mapobjects.values()) {
|
||||
if (o.getType() == MapleMapObjectType.REACTOR) {
|
||||
if (((MapleReactor) o).getState() < 1) {
|
||||
MapleReactor mr = (MapleReactor) o;
|
||||
mr.lockReactor();
|
||||
try {
|
||||
mr.resetReactorActions(1);
|
||||
broadcastMessage(MaplePacketCreator.triggerReactor((MapleReactor) o, 1));
|
||||
} finally {
|
||||
mr.unlockReactor();
|
||||
}
|
||||
for (MapleMapObject o : getMapObjects()) {
|
||||
if (o.getType() == MapleMapObjectType.REACTOR) {
|
||||
if (((MapleReactor) o).getState() < 1) {
|
||||
MapleReactor mr = (MapleReactor) o;
|
||||
mr.lockReactor();
|
||||
try {
|
||||
mr.resetReactorActions(1);
|
||||
broadcastMessage(MaplePacketCreator.triggerReactor((MapleReactor) o, 1));
|
||||
} finally {
|
||||
mr.unlockReactor();
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
objectRLock.unlock();
|
||||
chrRLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1191,45 +1184,7 @@ public class MapleMap {
|
||||
}
|
||||
}
|
||||
if (monster.isAlive()) {
|
||||
boolean killed = false;
|
||||
monster.lockMonster();
|
||||
try {
|
||||
if (!monster.isAlive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* pyramid not implemented
|
||||
Pair<Integer, Integer> cool = monster.getStats().getCool();
|
||||
if (cool != null) {
|
||||
Pyramid pq = (Pyramid) chr.getPartyQuest();
|
||||
if (pq != null) {
|
||||
if (damage > 0) {
|
||||
if (damage >= cool.getLeft()) {
|
||||
if ((Math.random() * 100) < cool.getRight()) {
|
||||
pq.cool();
|
||||
} else {
|
||||
pq.kill();
|
||||
}
|
||||
} else {
|
||||
pq.kill();
|
||||
}
|
||||
} else {
|
||||
pq.miss();
|
||||
}
|
||||
killed = true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (damage > 0) {
|
||||
monster.damage(chr, damage, false);
|
||||
if (!monster.isAlive()) { // monster just died
|
||||
killed = true;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
monster.unlockMonster();
|
||||
}
|
||||
boolean killed = monster.damage(chr, damage, false);
|
||||
if (monster.getStats().selfDestruction() != null && monster.getStats().selfDestruction().getHp() > -1) {// should work ;p
|
||||
if (monster.getHp() <= monster.getStats().selfDestruction().getHp()) {
|
||||
killMonster(monster, chr, true, monster.getStats().selfDestruction().getAction());
|
||||
@@ -1268,6 +1223,23 @@ public class MapleMap {
|
||||
Server.getInstance().getWorld(world).dropMessage(6, "[VICTORY] In a swift stroke of sorts, the crew that has attempted Pink Bean at channel " + channel + " has ultimately defeated it. The Temple of Time shines radiantly once again, the day finally coming back, as the crew that managed to finally conquer it returns victoriously from the battlefield!!");
|
||||
}
|
||||
|
||||
private boolean removeKilledMonsterObject(MapleMonster monster) {
|
||||
monster.lockMonster();
|
||||
try {
|
||||
if(monster.getHp() < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
spawnedMonstersOnMap.decrementAndGet();
|
||||
removeMapObject(monster);
|
||||
monster.disposeMapObject();
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
monster.unlockMonster();
|
||||
}
|
||||
}
|
||||
|
||||
public void killMonster(final MapleMonster monster, final MapleCharacter chr, final boolean withDrops) {
|
||||
killMonster(monster, chr, withDrops, 1);
|
||||
}
|
||||
@@ -1276,93 +1248,89 @@ public class MapleMap {
|
||||
if(monster == null) return;
|
||||
|
||||
if (chr == null) {
|
||||
spawnedMonstersOnMap.decrementAndGet();
|
||||
monster.setHpZero();
|
||||
removeMapObject(monster);
|
||||
|
||||
monster.dispatchMonsterKilled(false);
|
||||
broadcastMessage(MaplePacketCreator.killMonster(monster.getObjectId(), animation), monster.getPosition());
|
||||
return;
|
||||
}
|
||||
if (monster.getStats().getLevel() >= chr.getLevel() + 30 && !chr.isGM()) {
|
||||
AutobanFactory.GENERAL.alert(chr, " for killing a " + monster.getName() + " which is over 30 levels higher.");
|
||||
}
|
||||
/*if (chr.getQuest(MapleQuest.getInstance(29400)).getStatus().equals(MapleQuestStatus.Status.STARTED)) {
|
||||
if (chr.getLevel() >= 120 && monster.getStats().getLevel() >= 120) {
|
||||
//FIX MEDAL SHET
|
||||
} else if (monster.getStats().getLevel() >= chr.getLevel()) {
|
||||
}
|
||||
}*/
|
||||
int buff = monster.getBuffToGive();
|
||||
if (buff > -1) {
|
||||
MapleItemInformationProvider mii = MapleItemInformationProvider.getInstance();
|
||||
for (MapleMapObject mmo : this.getPlayers()) {
|
||||
MapleCharacter character = (MapleCharacter) mmo;
|
||||
if (character.isAlive()) {
|
||||
MapleStatEffect statEffect = mii.getItemEffect(buff);
|
||||
character.getClient().announce(MaplePacketCreator.showOwnBuffEffect(buff, 1));
|
||||
broadcastMessage(character, MaplePacketCreator.showBuffeffect(character.getId(), buff, 1), false);
|
||||
statEffect.applyTo(character);
|
||||
}
|
||||
if(removeKilledMonsterObject(monster)) {
|
||||
monster.dispatchMonsterKilled(false);
|
||||
broadcastMessage(MaplePacketCreator.killMonster(monster.getObjectId(), animation), monster.getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
spawnedMonstersOnMap.decrementAndGet();
|
||||
monster.setHpZero();
|
||||
removeMapObject(monster);
|
||||
|
||||
if (monster.getCP() > 0 && chr.getCarnival() != null) {
|
||||
chr.getCarnivalParty().addCP(chr, monster.getCP());
|
||||
chr.announce(MaplePacketCreator.updateCP(chr.getCP(), chr.getObtainedCP()));
|
||||
broadcastMessage(MaplePacketCreator.updatePartyCP(chr.getCarnivalParty()));
|
||||
//they drop items too ):
|
||||
}
|
||||
if (monster.getId() >= 8800003 && monster.getId() <= 8800010) {
|
||||
boolean makeZakReal = true;
|
||||
Collection<MapleMapObject> objects = getMapObjects();
|
||||
for (MapleMapObject object : objects) {
|
||||
MapleMonster mons = getMonsterByOid(object.getObjectId());
|
||||
if (mons != null) {
|
||||
if (mons.getId() >= 8800003 && mons.getId() <= 8800010) {
|
||||
makeZakReal = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(removeKilledMonsterObject(monster)) {
|
||||
if (monster.getStats().getLevel() >= chr.getLevel() + 30 && !chr.isGM()) {
|
||||
AutobanFactory.GENERAL.alert(chr, " for killing a " + monster.getName() + " which is over 30 levels higher.");
|
||||
}
|
||||
}
|
||||
if (makeZakReal) {
|
||||
MapleMap map = chr.getMap();
|
||||
|
||||
for (MapleMapObject object : objects) {
|
||||
MapleMonster mons = map.getMonsterByOid(object.getObjectId());
|
||||
if (mons != null) {
|
||||
if (mons.getId() == 8800000) {
|
||||
makeMonsterReal(mons);
|
||||
updateMonsterController(mons);
|
||||
break;
|
||||
/*if (chr.getQuest(MapleQuest.getInstance(29400)).getStatus().equals(MapleQuestStatus.Status.STARTED)) {
|
||||
if (chr.getLevel() >= 120 && monster.getStats().getLevel() >= 120) {
|
||||
//FIX MEDAL SHET
|
||||
} else if (monster.getStats().getLevel() >= chr.getLevel()) {
|
||||
}
|
||||
}*/
|
||||
int buff = monster.getBuffToGive();
|
||||
if (buff > -1) {
|
||||
MapleItemInformationProvider mii = MapleItemInformationProvider.getInstance();
|
||||
for (MapleMapObject mmo : this.getPlayers()) {
|
||||
MapleCharacter character = (MapleCharacter) mmo;
|
||||
if (character.isAlive()) {
|
||||
MapleStatEffect statEffect = mii.getItemEffect(buff);
|
||||
character.getClient().announce(MaplePacketCreator.showOwnBuffEffect(buff, 1));
|
||||
broadcastMessage(character, MaplePacketCreator.showBuffeffect(character.getId(), buff, 1), false);
|
||||
statEffect.applyTo(character);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MapleCharacter dropOwner = monster.killBy(chr);
|
||||
if (withDrops && !monster.dropsDisabled()) {
|
||||
if (dropOwner == null) {
|
||||
dropOwner = chr;
|
||||
}
|
||||
dropFromMonster(dropOwner, monster, false);
|
||||
}
|
||||
|
||||
if (monster.hasBossHPBar()) {
|
||||
for(MapleCharacter mc : this.getAllPlayers()) {
|
||||
if(mc.getTargetHpBarHash() == monster.hashCode()) {
|
||||
mc.resetPlayerAggro();
|
||||
|
||||
if (monster.getCP() > 0 && chr.getCarnival() != null) {
|
||||
chr.getCarnivalParty().addCP(chr, monster.getCP());
|
||||
chr.announce(MaplePacketCreator.updateCP(chr.getCP(), chr.getObtainedCP()));
|
||||
broadcastMessage(MaplePacketCreator.updatePartyCP(chr.getCarnivalParty()));
|
||||
//they drop items too ):
|
||||
}
|
||||
if (monster.getId() >= 8800003 && monster.getId() <= 8800010) {
|
||||
boolean makeZakReal = true;
|
||||
Collection<MapleMapObject> objects = getMapObjects();
|
||||
for (MapleMapObject object : objects) {
|
||||
MapleMonster mons = getMonsterByOid(object.getObjectId());
|
||||
if (mons != null) {
|
||||
if (mons.getId() >= 8800003 && mons.getId() <= 8800010) {
|
||||
makeZakReal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (makeZakReal) {
|
||||
MapleMap map = chr.getMap();
|
||||
|
||||
for (MapleMapObject object : objects) {
|
||||
MapleMonster mons = map.getMonsterByOid(object.getObjectId());
|
||||
if (mons != null) {
|
||||
if (mons.getId() == 8800000) {
|
||||
makeMonsterReal(mons);
|
||||
updateMonsterController(mons);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MapleCharacter dropOwner = monster.killBy(chr);
|
||||
if (withDrops && !monster.dropsDisabled()) {
|
||||
if (dropOwner == null) {
|
||||
dropOwner = chr;
|
||||
}
|
||||
dropFromMonster(dropOwner, monster, false);
|
||||
}
|
||||
|
||||
if (monster.hasBossHPBar()) {
|
||||
for(MapleCharacter mc : this.getAllPlayers()) {
|
||||
if(mc.getTargetHpBarHash() == monster.hashCode()) {
|
||||
mc.resetPlayerAggro();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
monster.dispatchMonsterKilled(true);
|
||||
broadcastMessage(MaplePacketCreator.killMonster(monster.getObjectId(), animation), monster.getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
monster.dispatchMonsterKilled(true);
|
||||
broadcastMessage(MaplePacketCreator.killMonster(monster.getObjectId(), animation), monster.getPosition());
|
||||
}
|
||||
|
||||
public void killFriendlies(MapleMonster mob) {
|
||||
@@ -1407,11 +1375,9 @@ public class MapleMap {
|
||||
continue;
|
||||
}
|
||||
|
||||
spawnedMonstersOnMap.decrementAndGet();
|
||||
monster.setHpZero();
|
||||
removeMapObject(monster);
|
||||
|
||||
monster.dispatchMonsterKilled(false);
|
||||
if(removeKilledMonsterObject(monster)) {
|
||||
monster.dispatchMonsterKilled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2228,33 +2194,31 @@ public class MapleMap {
|
||||
int reactItem = reactProp.getLeft(), reactQty = reactProp.getRight();
|
||||
Rectangle reactArea = react.getArea();
|
||||
|
||||
List<MapleMapItem> list = new ArrayList<>();
|
||||
List<MapleMapItem> list;
|
||||
objectRLock.lock();
|
||||
try {
|
||||
for(MapleMapItem mmi : droppedItems.keySet()) {
|
||||
mmi.lockItem();
|
||||
try {
|
||||
if(!mmi.isPickedUp()) {
|
||||
list.add(mmi);
|
||||
}
|
||||
} finally {
|
||||
mmi.unlockItem();
|
||||
}
|
||||
}
|
||||
list = new ArrayList<>(droppedItems.keySet());
|
||||
} finally {
|
||||
objectRLock.unlock();
|
||||
}
|
||||
|
||||
for(final MapleMapItem drop : list) {
|
||||
final Item item = drop.getItem();
|
||||
|
||||
if (item != null && reactItem == item.getItemId() && reactQty == item.getQuantity()) {
|
||||
if (reactArea.contains(drop.getPosition())) {
|
||||
MapleClient owner = drop.getOwnerClient();
|
||||
if(owner != null) {
|
||||
registerMapSchedule(new ActivateItemReactor(drop, react, owner), 5000);
|
||||
drop.lockItem();
|
||||
try {
|
||||
if(!drop.isPickedUp()) {
|
||||
final Item item = drop.getItem();
|
||||
|
||||
if (item != null && reactItem == item.getItemId() && reactQty == item.getQuantity()) {
|
||||
if (reactArea.contains(drop.getPosition())) {
|
||||
MapleClient owner = drop.getOwnerClient();
|
||||
if(owner != null) {
|
||||
registerMapSchedule(new ActivateItemReactor(drop, react, owner), 5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
drop.unlockItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2365,7 +2329,7 @@ public class MapleMap {
|
||||
try {
|
||||
characters.add(chr);
|
||||
chrSize = characters.size();
|
||||
|
||||
|
||||
addPartyMemberInternal(chr);
|
||||
itemMonitorTimeout = 1;
|
||||
} finally {
|
||||
|
||||
@@ -23,7 +23,7 @@ package server.maps;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Alan (SharpAceX)
|
||||
*/
|
||||
|
||||
public enum MapleMiniDungeonInfo {
|
||||
|
||||
@@ -7,7 +7,7 @@ import server.maps.MapleMap;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
/**
|
||||
* @author Rob //Thanks :3 - LOST MOTIVATION >=(
|
||||
* @author Rob
|
||||
*/
|
||||
public class MonsterCarnivalParty {
|
||||
|
||||
|
||||
@@ -540,6 +540,17 @@ public class MapleQuest {
|
||||
return medalid != null ? medalid : -1;
|
||||
}
|
||||
|
||||
public int getNpcRequirement(boolean complete) {
|
||||
Map<MapleQuestRequirementType, MapleQuestRequirement> reqs = !complete ? startReqs : completeReqs;
|
||||
|
||||
MapleQuestRequirement mqr = reqs.get(MapleQuestRequirementType.NPC);
|
||||
if (mqr != null) {
|
||||
return ((NpcRequirement) mqr).get();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadAllQuest() {
|
||||
questInfo = questData.getData("QuestInfo.img");
|
||||
questReq = questData.getData("Check.img");
|
||||
|
||||
@@ -49,4 +49,8 @@ public class NpcRequirement extends MapleQuestRequirement {
|
||||
public boolean check(MapleCharacter chr, Integer npcid) {
|
||||
return npcid != null && npcid == reqNPC;
|
||||
}
|
||||
|
||||
public int get() {
|
||||
return reqNPC;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,8 @@ public class PetRequirement extends MapleQuestRequirement {
|
||||
@Override
|
||||
public boolean check(MapleCharacter chr, Integer npcid) {
|
||||
for(MaplePet pet : chr.getPets()) {
|
||||
if(pet == null) continue; // thanks Arufonsu for showing a NPE occurring here
|
||||
|
||||
if(petIDs.contains(pet.getItemId()))
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user