package server.maps;
import client.MapleBuffStat;
import client.MapleCharacter;
import client.MapleClient;
import client.MonsterFamiliar;
import client.Skill;
import client.SkillFactory;
import client.inventory.Equip;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import client.inventory.MaplePet;
import client.status.MonsterStatus;
import client.status.MonsterStatusEffect;
import constants.GameConstants;
import constants.ItemConstants;
import constants.ServerConstants;
import database.DatabaseConnection;
import handling.channel.ChannelServer;
import handling.world.PartyOperation;
import handling.world.WorldBroadcastService;
import handling.world.party.ExpeditionType;
import handling.world.party.MaplePartyCharacter;
import java.awt.Point;
import java.awt.Rectangle;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TimerTask;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import scripting.event.EventManager;
import server.MapleCarnivalFactory;
import server.MapleInventoryManipulator;
import server.MapleItemInformationProvider;
import server.MaplePortal;
import server.MapleStatEffect;
import server.Randomizer;
import server.SpeedRunner;
import server.Timer.EtcTimer;
import server.Timer.MapTimer;
import server.events.MapleEvent;
import server.life.MapleLifeFactory;
import server.life.MapleMonster;
import server.life.MapleMonsterInformationProvider;
import server.life.MapleNPC;
import server.life.MonsterDropEntry;
import server.life.MonsterGlobalDropEntry;
import server.life.SpawnPoint;
import server.life.SpawnPointAreaBoss;
import server.life.Spawns;
import server.squad.MapleSquad;
import server.squad.MapleSquadType;
import tools.FileoutputUtil;
import tools.MaplePacketCreator;
import tools.Pair;
import tools.StringUtil;
import tools.packet.BuffPacket;
import tools.packet.InventoryPacket;
import tools.packet.MobPacket;
import tools.packet.NPCPacket;
import tools.packet.PartyPacket;
import tools.packet.PetPacket;
import tools.packet.SkillPacket;
import tools.packet.SummonPacket;
import tools.packet.UIPacket;
public final class MapleMap {
private final Map<MapleMapObjectType, LinkedHashMap<Integer, MapleMapObject>> mapobjects;
private final Map<MapleMapObjectType, ReentrantReadWriteLock> mapobjectlocks;
private final List<MapleCharacter> characters = new ArrayList();
private final ReentrantReadWriteLock charactersLock = new ReentrantReadWriteLock();
private final AtomicInteger runningOid = new AtomicInteger(100000);
private final Lock runningOidLock = new ReentrantLock(true);
private final List<Spawns> monsterSpawn = new ArrayList();
private final AtomicInteger spawnedMonstersOnMap = new AtomicInteger(0);
private final Map<Integer, MaplePortal> portals = new HashMap();
private MapleFootholdTree footholds = null;
private final float monsterRate;
private float recoveryRate;
private MapleMapEffect mapEffect;
private final int channel;
private short decHP = 0; // 地图自动掉血值
private int decHPInterval = 10000; // 地图自动掉血间隔
private short createMobInterval = 9000;
private short top = 0;
private short bottom = 0;
private short left = 0;
private short right = 0;
private int consumeItemCoolTime = 0;
private int protectItem = 0;
private final int mapid;
private int returnMapId;
private int timeLimit;
private int fieldLimit;
private int maxRegularSpawn = 0;
private int fixedMob;
private int forcedReturnMap = 999999999;
private int instanceid = -1;
private int lvForceMove = 0;
private int lvLimit = 0;
private int permanentWeather = 0;
private int partyBonusRate = 0;
private boolean town;
private boolean clock;
private boolean boat;
private boolean docked;
private boolean personalShop;
private boolean everlast = false;
private boolean dropsDisabled = false;
private boolean gDropsDisabled = false;
private boolean soaring = false;
private boolean squadTimer = false;
private boolean isSpawns = true;
private boolean checkStates = true;
private String mapName;
private String streetName;
private String onUserEnter;
private String onFirstUserEnter;
private String speedRunLeader = "";
private final List<Integer> dced = new ArrayList();
private List<Point> spawnPoints = new ArrayList();
private ScheduledFuture<?> squadSchedule;
private long speedRunStart = 0;
private long lastSpawnTime = 0;
private long lastHurtTime = 0;
private MapleNodes nodes;
private MapleSquadType squad;
private final Map<String, Integer> environment = new LinkedHashMap();
private long runeTine = 0;
private boolean special = false;
public MapleMap(int mapid, int channel, int returnMapId, float monsterRate) {
this.mapid = mapid;
this.channel = channel;
this.returnMapId = returnMapId;
if (this.returnMapId == 999999999) {
this.returnMapId = mapid;
}
special = mapid == 105200510;
if (GameConstants.getPartyPlay(mapid) > 0) {
this.monsterRate = ((monsterRate - 1.0F) * 2.5F + 1.0F);
} else {
this.monsterRate = monsterRate;
}
EnumMap objsMap = new EnumMap(MapleMapObjectType.class);
EnumMap objlockmap = new EnumMap(MapleMapObjectType.class);
for (MapleMapObjectType type : MapleMapObjectType.values()) {
objsMap.put(type, new LinkedHashMap());
objlockmap.put(type, new ReentrantReadWriteLock());
}
this.mapobjects = Collections.unmodifiableMap(objsMap);
this.mapobjectlocks = Collections.unmodifiableMap(objlockmap);
}
public void setSpawns(boolean fm) {
this.isSpawns = fm;
}
public boolean getSpawns() {
return this.isSpawns;
}
public boolean getSpecial() {
return this.special;
}
public void setFixedMob(int fm) {
this.fixedMob = fm;
}
public void setForceMove(int fm) {
this.lvForceMove = fm;
}
public int getForceMove() {
return this.lvForceMove;
}
public void setLevelLimit(int fm) {
this.lvLimit = fm;
}
public int getLevelLimit() {
return this.lvLimit;
}
public void setReturnMapId(int rmi) {
this.returnMapId = rmi;
}
public void setSoaring(boolean b) {
this.soaring = b;
}
public boolean canSoar() {
return this.soaring;
}
public void toggleDrops() {
this.dropsDisabled = (!this.dropsDisabled);
}
public void setDrops(boolean b) {
this.dropsDisabled = b;
}
public void toggleGDrops() {
this.gDropsDisabled = (!this.gDropsDisabled);
}
public int getId() {
return this.mapid;
}
public MapleMap getReturnMap() {
return ChannelServer.getInstance(this.channel).getMapFactory().getMap(this.returnMapId);
}
public int getReturnMapId() {
return this.returnMapId;
}
public int getForcedReturnId() {
return this.forcedReturnMap;
}
public MapleMap getForcedReturnMap() {
return ChannelServer.getInstance(this.channel).getMapFactory().getMap(this.forcedReturnMap);
}
public void setForcedReturnMap(int map) {
this.forcedReturnMap = map;
}
public float getRecoveryRate() {
return this.recoveryRate;
}
public void setRecoveryRate(float recoveryRate) {
this.recoveryRate = recoveryRate;
}
public int getFieldLimit() {
return this.fieldLimit;
}
public void setFieldLimit(int fieldLimit) {
this.fieldLimit = fieldLimit;
}
public void setCreateMobInterval(short createMobInterval) {
this.createMobInterval = createMobInterval;
}
public void setTimeLimit(int timeLimit) {
this.timeLimit = timeLimit;
}
public void setMapName(String mapName) {
this.mapName = mapName;
}
public String getMapName() {
return this.mapName;
}
public String getStreetName() {
return this.streetName;
}
public void setFirstUserEnter(String onFirstUserEnter) {
this.onFirstUserEnter = onFirstUserEnter;
}
public void setUserEnter(String onUserEnter) {
this.onUserEnter = onUserEnter;
}
public String getFirstUserEnter() {
return this.onFirstUserEnter;
}
public String getUserEnter() {
return this.onUserEnter;
}
public boolean hasClock() {
return this.clock;
}
public void setClock(boolean hasClock) {
this.clock = hasClock;
}
public boolean isTown() {
return this.town;
}
public void setTown(boolean town) {
this.town = town;
}
public boolean allowPersonalShop() {
return this.personalShop;
}
public void setPersonalShop(boolean personalShop) {
this.personalShop = personalShop;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
public void setEverlast(boolean everlast) {
this.everlast = everlast;
}
public boolean getEverlast() {
return this.everlast;
}
public int getHPDec() {
return this.decHP;
}
public void setHPDec(int delta) {
if ((delta > 0) || (this.mapid == 749040100)) {
this.lastHurtTime = System.currentTimeMillis();
}
this.decHP = (short) delta;
}
public int getHPDecInterval() {
return this.decHPInterval;
}
public void setHPDecInterval(int delta) {
this.decHPInterval = delta;
}
public int getHPDecProtect() {
return this.protectItem;
}
public void setHPDecProtect(int delta) {
this.protectItem = delta;
}
public void setSpawnPoints(List<Point> Points) {
this.spawnPoints = Points;
}
public List<Point> getSpawnPoints() {
return this.spawnPoints;
}
public int getCurrentPartyId() {
this.charactersLock.readLock().lock();
try {
for (MapleCharacter chr : this.characters) {
if (chr.getParty() != null) {
int i = chr.getParty().getId();
return i;
}
}
} finally {
this.charactersLock.readLock().unlock();
}
return -1;
}
public void addMapObject(MapleMapObject mapobject) {
this.runningOidLock.lock();
try {
if (mapobject.getObjectId() != 0) {
mapobject.setObjectId(mapobject.getObjectId());
} else {
mapobject.setObjectId(runningOid.getAndIncrement());
}
} finally {
this.runningOidLock.unlock();
}
ReentrantReadWriteLock rl = this.mapobjectlocks.get(mapobject.getType());
rl.writeLock().lock();
try {
((LinkedHashMap) this.mapobjects.get(mapobject.getType())).put(mapobject.getObjectId(), mapobject);
} finally {
rl.writeLock().unlock();
}
}
private void spawnAndAddRangedMapObject(MapleMapObject mapobject, DelayedPacketCreation packetbakery) {
addMapObject(mapobject);
this.charactersLock.readLock().lock();
try {
for (MapleCharacter chr : this.characters) {
if ((mapobject.getType() == MapleMapObjectType.MIST) || (chr.getTruePosition().distance(mapobject.getTruePosition()) <= GameConstants.maxViewRangeSq())) {
packetbakery.sendPackets(chr.getClient());
chr.addVisibleMapObject(mapobject);
}
}
} finally {
this.charactersLock.readLock().unlock();
}
}
public void removeMapObject(MapleMapObject obj) {
ReentrantReadWriteLock rl = this.mapobjectlocks.get(obj.getType());
rl.writeLock().lock();
try {
((LinkedHashMap) this.mapobjects.get(obj.getType())).remove(obj.getObjectId());
} finally {
rl.writeLock().unlock();
}
}
public Point calcPointBelow(Point initial) {
MapleFoothold fh = this.footholds.findBelow(initial);
if (fh == null) {
return null;
}
int dropY = fh.getY1();
if ((!fh.isWall()) && (fh.getY1() != fh.getY2())) {
double s1 = Math.abs(fh.getY2() - fh.getY1());
double s2 = Math.abs(fh.getX2() - fh.getX1());
double s5 = Math.cos(Math.atan(s2 / s1)) * (Math.abs(initial.x - fh.getX1()) / Math.cos(Math.atan(s1 / s2)));
if (fh.getY2() < fh.getY1()) {
dropY = fh.getY1() - (int) s5;
} else {
dropY = fh.getY1() + (int) s5;
}
}
return new Point(initial.x, dropY);
}
public Point calcDropPos(Point initial, Point fallback) {
Point ret = calcPointBelow(new Point(initial.x, initial.y - 99));
if (ret == null) {
return fallback;
}
return ret;
}
private void dropFromMonster(MapleCharacter chr, MapleMonster mob, boolean instanced) {//TODO 怪物死亡掉落物品
if (mob == null) {
chr.dropMessage(1,"怪物为空了!");
return;
}
if (chr == null) {
chr.dropMessage(1,"角色为空了!");
return;
}
if ((ChannelServer.getInstance(this.channel) == null) ) {
chr.dropMessage(1,"频道为空了!");
return;
}
// if ((this.dropsDisabled)) {
// chr.dropMessage(1,"该地图不能掉落道具");
// return;
// }
if ((mob.dropsDisabled())) {
chr.dropMessage(1,"怪物不能掉落道具:"+mob.getId());
return;
}
int maxSize = 200;
if ((!instanced) && (maxSize >= 300) && (((LinkedHashMap) this.mapobjects.get(MapleMapObjectType.ITEM)).size() >= maxSize)) {
removeDropsDelay();
if (chr.isShowPacket()) {
chr.dropMessage(6, new StringBuilder().append("[系统提示] 当前地图的道具数量达到 ").append(maxSize).append(" 系统已自动清理掉所有地上的物品信息.").toString());
}
}
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
byte droptype = (byte) (chr.getParty() != null ? 1 : mob.getStats().isFfaLoot() ? 2 : mob.getStats().isExplosiveReward() ? 3 : 0);
int mobpos = mob.getTruePosition().x;
int mesoServerRate = ChannelServer.getInstance(this.channel).getMesoRate(chr.getWorld());
int dropServerRate = ChannelServer.getInstance(this.channel).getDropRate(chr.getWorld());
int cashServerRate = ChannelServer.getInstance(this.channel).getCashRate();
int globalServerRate = ChannelServer.getInstance(this.channel).getGlobalRate();
byte d = 1;
Point pos = new Point(0, mob.getTruePosition().y);
MapleMonsterInformationProvider mi = MapleMonsterInformationProvider.getInstance();
List derp = mi.retrieveDrop(mob.getId());
if (derp == null) {
FileoutputUtil.log("找不到怪物的掉落:"+mob.getId());
return;
}
List<MonsterDropEntry> dropEntry = new ArrayList(derp);
Collections.shuffle(dropEntry);
for (MonsterDropEntry de : dropEntry) {
if (de.itemId == mob.getStolen()) {
continue;
}
if (Randomizer.nextInt(10000) < (int) (de.chance * dropServerRate * chr.getDropMod() * (chr.getStat().getDropBuff() / 100.0D))) {
if (((droptype != 3) && (de.itemId == 0))) {
continue;
}
// if (droptype == 3) {
// pos.x = (mobpos + (d % 2 == 0 ? 40 * (d + 1) / 2 : -(40 * (d / 2))));
// } else {
pos.x = Math.min(Math.max(mobpos - 25 * (d / 2), footholds.getMinDropX() + 25),footholds.getMaxDropX() - d * 25);
// pos.x = (mobpos + (d % 2 == 0 ? 25 * (d + 1) / 2 : -(25 * (d / 2))));
// }
if (de.itemId > 0) {
Item idrop;
if (ItemConstants.getInventoryType(de.itemId) == MapleInventoryType.EQUIP) {
idrop = ii.randomizeStats((Equip) ii.getEquipById(de.itemId));
} else {
int range = Math.abs(de.Maximum - de.Minimum);
idrop = new Item(de.itemId, (byte) 0, (short) (de.Maximum != 1 ? Randomizer.nextInt(range <= 0 ? 1 : range) + de.Minimum : 1), (short) 0);
}
idrop.setGMLog(new StringBuilder().append("怪物掉落: ").append(mob.getId()).append(" 地图: ").append(this.mapid).append(" 时间: ").append(FileoutputUtil.CurrentReadable_Date()).toString());
if (ItemConstants.isNoticeItem(de.itemId)) {
broadcastMessage(MaplePacketCreator.serverMessageNotice(new StringBuilder(127).append("\"").append(chr.getName()).append("\" 在\"").append(chr.getMap().getMapName()).append("\"杀死\"").append(mob.getStats().getName()).append("\",掉落道具\"").append(ii.getName(de.itemId)).append("\"").toString()));
}
spawnMobDrop(idrop, calcDropPos(pos, mob.getTruePosition()), mob, chr, droptype, de.questid);
}
d++;
}
}
d++;
pos.x = Math.min(Math.max(mobpos - 25 * (d / 2), footholds.getMinDropX() + 25),footholds.getMaxDropX() - d * 25);
int mesos = Randomizer.nextInt(mob.getMobLevel() * 10) + mob.getMobLevel();
if (mesos > 0) {
spawnMobMesoDrop((int) (mesos * (chr.getStat().mesoBuff / 100.0D) * chr.getDropMod() * mesoServerRate), calcDropPos(pos, mob.getTruePosition()), mob, chr, false, droptype);
}
List<MonsterGlobalDropEntry> globalEntry = new ArrayList(mi.getGlobalDrop());
Collections.shuffle(globalEntry);
int cashz = ((mob.getStats().isBoss()) && (mob.getStats().getHPDisplayType() == 0) ? 20 : 1) * cashServerRate;
int cashModifier = (int) (mob.getStats().isBoss() ? mob.getStats().isPartyBonus() ? mob.getMobExp() / 1000 : 0 : mob.getMobExp() / 1000 + mob.getMobMaxHp() / 20000L);
for (MonsterGlobalDropEntry de : globalEntry) {
if (de.chance == 0) {
continue;
}
if ((Randomizer.nextInt(GameConstants.DROP_ITEM_PER) < de.chance * globalServerRate) && ((de.continent < 0) || ((de.continent < 10) && (this.mapid / 100000000 == de.continent)) || ((de.continent < 100) && (this.mapid / 10000000 == de.continent)) || ((de.continent < 1000) && (this.mapid / 1000000 == de.continent)))) {
if ((de.itemId == 0) && (cashServerRate != 0)) {
int giveCash = Randomizer.nextInt(cashz) + cashz + cashModifier;
if (giveCash > 0) {
chr.modifyCSPoints(2, giveCash, true);
}
} else if (!this.gDropsDisabled) {
if (droptype == 3) {
pos.x = (mobpos + (d % 2 == 0 ? 40 * (d + 1) / 2 : -(40 * (d / 2))));
} else {
pos.x = (mobpos + (d % 2 == 0 ? 25 * (d + 1) / 2 : -(25 * (d / 2))));
}
Item idrop;
if (ItemConstants.getInventoryType(de.itemId) == MapleInventoryType.EQUIP) {
idrop = ii.randomizeStats((Equip) ii.getEquipById(de.itemId));
} else {
idrop = new Item(de.itemId, (byte) 0, (short) (de.Maximum != 1 ? Randomizer.nextInt(de.Maximum - de.Minimum) + de.Minimum : 1), (short) 0);
}
idrop.setGMLog(new StringBuilder().append("怪物掉落: ").append(mob.getId()).append(" 地图: ").append(this.mapid).append(" (Global) 时间: ").append(FileoutputUtil.CurrentReadable_Date()).toString());
if (ItemConstants.isNoticeItem(de.itemId)) {
broadcastMessage(MaplePacketCreator.serverMessageNotice(new StringBuilder(127).append("\"").append(chr.getName()).append("\" 在\"").append(chr.getMap().getMapName()).append("\"杀死\" ").append(mob.getStats().getName()).append("\",掉落道具\"").append(ii.getName(de.itemId)).append("\"").toString()));
}
spawnMobDrop(idrop, calcDropPos(pos, mob.getTruePosition()), mob, chr, de.onlySelf ? 0 : droptype, de.questid);
d++;
}
}
}
}
public void removeMonster(MapleMonster monster) {
if (monster == null) {
return;
}
this.spawnedMonstersOnMap.decrementAndGet();
broadcastMessage(MobPacket.killMonster(monster.getObjectId(), 0));
removeMapObject(monster);
monster.killed();
}
public void killMonster(final MapleMonster monster) {
if (monster == null) {
return;
}
this.spawnedMonstersOnMap.decrementAndGet();
monster.setHp(0L);
final java.util.Timer timer = new java.util.Timer(true);
TimerTask task = new TimerTask() {
@Override
public void run() {
if (monster.getLinkCID() <= 0) {
monster.spawnRevives(monster.getMap());
}
timer.cancel();
}
};
if (monster.getId() == 8820108 || monster.getId() == 8810026 || monster.getId() == 8820108 || monster.getId() == 8810130 || monster.getId() == 8820008) {
timer.schedule(task, 4500);
} else {
if (monster.getLinkCID() <= 0) {
monster.spawnRevives(monster.getMap());
}
}
broadcastMessage(MobPacket.killMonster(monster.getObjectId(), monster.getStats().getSelfD() < 0 ? 1 : monster.getStats().getSelfD()));
removeMapObject(monster);
monster.killed();
}
public void killMonster(MapleMonster monster, MapleCharacter chr, boolean withDrops, boolean second, byte animation) {
killMonster(monster, chr, withDrops, second, animation, 0);
}
/**
* 杀死怪物
* @param monster
* @param chr
* @param withDrops
* @param second
* @param animation
* @param lastSkill
*/
public void killMonster(final MapleMonster monster, final MapleCharacter chr, boolean withDrops, boolean second, byte animation, int lastSkill) {
// if (((monster.getId() == 8810122) || (monster.getId() == 8810018)) && (!second)) {
// MapTimer.getInstance().schedule(new Runnable() {
// @Override
// public void run() {
// MapleMap.this.killMonster(monster, chr, true, true, (byte) 1);
// MapleMap.this.killAllMonsters(true);
// }
// }, 3000);
// return;
// }
// if (monster.getStatusSourceID(MonsterStatus.持续掉血) == 2111010) { //TODO 处理绿水灵病毒
// Skill skills = SkillFactory.getSkill(2111010);
// int skilllevel = chr.getSkillLevel(2111010);
// MapleStatEffect infoEffect = skills.getEffect(skilllevel);
// infoEffect.applyBuffEffect(chr, monster.getBuff(MonsterStatus.持续掉血).getPoisonSchedule());
// }
this.spawnedMonstersOnMap.decrementAndGet();
removeMapObject(monster);
monster.killed();
MapleSquad sqd = getSquadByMap();
boolean instanced = (sqd != null) || (monster.getEventInstance() != null) || (getEMByMap() != null);
int dropOwner = monster.killBy(chr, lastSkill);
if (animation >= 0) {
broadcastMessage(MobPacket.killMonster(monster.getObjectId(), animation));
}
if (dropOwner != -1) { // 这里加经验
monster.killGainExp(lastSkill);
}
int mobid = monster.getId();
ExpeditionType type = null;
if ((mobid == 8800002) && ((this.mapid == 280030000))) {
this.charactersLock.readLock().lock();
if (this.speedRunStart > 0L) {
type = ExpeditionType.Zakum;
}
doShrine(true);
} else if ((mobid >= 8800003) && (mobid <= 8800010)) {
boolean makeZakReal = true;
Collection<MapleMonster> monsters = getAllMonstersThreadsafe();
for (MapleMonster mons : monsters) {
if ((mons.getId() >= 8800003) && (mons.getId() <= 8800010)) {
makeZakReal = false;
break;
}
}
if (makeZakReal) {
for (Object object : monsters) {
MapleMonster mons = (MapleMonster) object;
if (mons.getId() == 8800000) {
Point pos = mons.getTruePosition();
killAllMonsters(true);
spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(8800000), pos);
break;
}
}
}
} else if ((mobid >= 8800103) && (mobid <= 8800110)) {
boolean makeZakReal = true;
Collection<MapleMonster> monsters = getAllMonstersThreadsafe();
for (MapleMonster mons : monsters) {
if ((mons.getId() >= 8800103) && (mons.getId() <= 8800110)) {
makeZakReal = false;
break;
}
}
if (makeZakReal) {
for (MapleMonster mons : monsters) {
if (mons.getId() == 8800100) {
Point pos = mons.getTruePosition();
killAllMonsters(true);
spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(8800100), pos);
break;
}
}
}
} else if (mobid >= 8800023 && mobid <= 8800030) {
boolean makeZakReal = true;
final Collection<MapleMonster> monsters = getAllMonstersThreadsafe();
for (final MapleMonster mons : monsters) {
if (mons.getId() >= 8800023 && mons.getId() <= 8800030) {
makeZakReal = false;
break;
}
}
if (makeZakReal) {
for (final MapleMonster mons : monsters) {
if (mons.getId() == 8800020) {
final Point pos = mons.getTruePosition();
this.killAllMonsters(true);
spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(8800020), pos);
break;
}
}
}
} else if ((mobid >= 9400903) && (mobid <= 9400910)) {
boolean makeZakReal = true;
Collection<MapleMonster> monsters = getAllMonstersThreadsafe();
for (MapleMonster mons : monsters) {
if ((mons.getId() >= 9400903) && (mons.getId() <= 9400910)) {
makeZakReal = false;
break;
}
}
if (makeZakReal) {
for (MapleMonster mons : monsters) {
if (mons.getId() == 9400900) {
Point pos = mons.getTruePosition();
killAllMonsters(true);
spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(9400900), pos);
break;
}
}
}
} else if ((mobid / 100000 == 98) && (chr.getMapId() / 10000000 == 95) && (getAllMonstersThreadsafe().isEmpty())) {
switch (chr.getMapId() % 1000 / 100) {
case 0:
case 1:
case 2:
case 3:
case 4:
chr.getClient().getSession().write(UIPacket.MapEff("monsterPark/clear"));
break;
case 5:
if (chr.getMapId() / 1000000 == 952) {
chr.getClient().getSession().write(UIPacket.MapEff("monsterPark/clearF"));
} else {
chr.getClient().getSession().write(UIPacket.MapEff("monsterPark/clear"));
}
break;
case 6:
chr.getClient().getSession().write(UIPacket.MapEff("monsterPark/clearF"));
}
} else if ((mobid / 100000 == 93) && (chr.getMapId() / 1000000 == 955) && (getAllMonstersThreadsafe().isEmpty())) {
switch (chr.getMapId() % 1000 / 100) {
case 1:
case 2:
chr.getClient().getSession().write(MaplePacketCreator.showEffect("aswan/clear"));
chr.getClient().getSession().write(MaplePacketCreator.playSound("Party1/Clear"));
break;
case 3:
chr.getClient().getSession().write(MaplePacketCreator.showEffect("aswan/clearF"));
chr.getClient().getSession().write(MaplePacketCreator.playSound("Party1/Clear"));
chr.dropMessage(-1, "你已经通过了所有回合。请通过传送口移动到外部。");
}
}
if ((type != null) && (this.speedRunStart > 0L) && (this.speedRunLeader.length() > 0)) {
String name = "";
switch (type.name()) {
case "Normal_Balrog":
name = "蝙蝠怪";
break;
}
long endTime = System.currentTimeMillis();
String time = StringUtil.getReadableMillis(this.speedRunStart, endTime);
broadcastMessage(MaplePacketCreator.serverMessageNotice(new StringBuilder(127).append(this.speedRunLeader).append("带领的远征队,耗时: ").append(time).append(" 击败了 ").append(name).append("!").toString()));
getRankAndAdd(this.speedRunLeader, time, type, endTime - this.speedRunStart, sqd == null ? null : sqd.getMembers());
endSpeedRun();
}
if ((withDrops) && (dropOwner != -1)) {
MapleCharacter drop;
if (dropOwner <= 0) {
drop = chr;
} else {
drop = getCharacterById(dropOwner);
if (drop == null) {
drop = chr;
}
}
dropFromMonster(drop, monster, instanced);
}
if ((ServerConstants.打怪获得点抵用卷 || this.isBossMap()) && Randomizer.nextInt(100) < 30) {
int NX = Math.max(monster.getMobLevel(), 1);
if (chr.getParty() != null && chr.getParty().getMembers().size() >= 2) {
for (MaplePartyCharacter pch : chr.getParty().getMembers()) {
if (pch.getMapid() == this.getId()) {
pch.getChr().modifyCSPoints(monster.getStats().isBoss() ? 1 : 2, NX / (7 - chr.getParty().getMembers().size()), true);
}
}
} else {
chr.modifyCSPoints(monster.getStats().isBoss() ? 1 : 2, NX / 10, true);
}
} else if (cangetNXMap() && Randomizer.nextInt(100) < 30) {
int NX = Math.max(monster.getMobLevel(), 1);
if (chr.getParty() != null && chr.getParty().getMembers().size() >= 1) {
for (MaplePartyCharacter pch : chr.getParty().getMembers()) {
if (pch.getMapid() == this.getId()) {
pch.getChr().modifyCSPoints(monster.getStats().isBoss() ? 1 : 2, Math.max(NX / 150, 1) * chr.getParty().getMembers().size() * pch.getChr().getPQLog("MonsterPark"), true);
}
}
}
}
}
public boolean cangetNXMap() {
switch (this.getId()) {
case 952000000:
return true;
}
if (this.getId() >= 952000000 && this.getId() <= 954061000 || this.getId() >= 925020100 && this.getId() <= 925033000) {
return true;
}
return false;
}
public List<MapleReactor> getAllReactor() {
return getAllReactorsThreadsafe();
}
public List<MapleReactor> getAllReactorsThreadsafe() {
ArrayList ret = new ArrayList();
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().lock();
try {
for (MapleMapObject mmo : mapobjects.get(MapleMapObjectType.REACTOR).values()) {
ret.add((MapleReactor) mmo);
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().unlock();
}
return ret;
}
public List<MapleSummon> getAllSummonsThreadsafe() {
ArrayList ret = new ArrayList();
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.SUMMON)).readLock().lock();
try {
for (MapleMapObject mmo : mapobjects.get(MapleMapObjectType.SUMMON).values()) {
if ((mmo instanceof MapleSummon)) {
ret.add((MapleSummon) mmo);
}
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.SUMMON)).readLock().unlock();
}
return ret;
}
public List<MapleMapObject> getAllDoor() {
return getAllDoorsThreadsafe();
}
public List<MapleMapObject> getAllDoorsThreadsafe() {
ArrayList ret = new ArrayList();
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.DOOR)).readLock().lock();
try {
for (MapleMapObject mmo : mapobjects.get(MapleMapObjectType.DOOR).values()) {
if ((mmo instanceof MapleDoor)) {
ret.add(mmo);
}
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.DOOR)).readLock().unlock();
}
return ret;
}
public List<MapleMapObject> getAllMechDoorsThreadsafe() {
ArrayList ret = new ArrayList();
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.DOOR)).readLock().lock();
try {
for (MapleMapObject mmo : mapobjects.get(MapleMapObjectType.DOOR).values()) {
if ((mmo instanceof MechDoor)) {
ret.add(mmo);
}
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.DOOR)).readLock().unlock();
}
return ret;
}
public List<MapleMapObject> getAllMerchant() {
return getAllHiredMerchantsThreadsafe();
}
public List<MapleMapObject> getAllHiredMerchantsThreadsafe() {
ArrayList ret = new ArrayList();
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.HIRED_MERCHANT)).readLock().lock();
try {
for (MapleMapObject mmo : mapobjects.get(MapleMapObjectType.HIRED_MERCHANT).values()) {
ret.add(mmo);
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.HIRED_MERCHANT)).readLock().unlock();
}
return ret;
}
public List<MapleMonster> getAllMonster() {
return getAllMonstersThreadsafe();
}
public List<MapleMonster> getAllMonstersThreadsafe() {
ArrayList ret = new ArrayList();
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.MONSTER)).readLock().lock();
try {
for (MapleMapObject mmo : mapobjects.get(MapleMapObjectType.MONSTER).values()) {
ret.add((MapleMonster) mmo);
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.MONSTER)).readLock().unlock();
}
return ret;
}
public List<Integer> getAllUniqueMonsters() {
ArrayList ret = new ArrayList();
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.MONSTER)).readLock().lock();
try {
for (MapleMapObject mmo : mapobjects.get(MapleMapObjectType.MONSTER).values()) {
int theId = ((MapleMonster) mmo).getId();
if (!ret.contains(theId)) {
ret.add(theId);
}
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.MONSTER)).readLock().unlock();
}
return ret;
}
public void killAllMonsters(){
killAllMonsters(false);
}
public void killAllMonsters(boolean animate) {
for (MapleMapObject monstermo : getAllMonstersThreadsafe()) {
MapleMonster monster = (MapleMonster) monstermo;
this.spawnedMonstersOnMap.decrementAndGet();
monster.setHp(0L);
broadcastMessage(MobPacket.killMonster(monster.getObjectId(), animate ? 1 : 0));
removeMapObject(monster);
monster.killed();
}
}
public void killMonster(int monsId) {
for (MapleMapObject mmo : getAllMonstersThreadsafe()) {
if (((MapleMonster) mmo).getId() == monsId) {
this.spawnedMonstersOnMap.decrementAndGet();
removeMapObject(mmo);
broadcastMessage(MobPacket.killMonster(mmo.getObjectId(), 1));
((MapleMonster) mmo).killed();
break;
}
}
}
private String MapDebug_Log() {
StringBuilder sb = new StringBuilder("Defeat time : ");
sb.append(FileoutputUtil.CurrentReadable_Time());
sb.append(" | Mapid : ").append(this.mapid);
this.charactersLock.readLock().lock();
try {
sb.append(" Users [").append(this.characters.size()).append("] | ");
for (MapleCharacter mc : this.characters) {
sb.append(mc.getName()).append(", ");
}
} finally {
this.charactersLock.readLock().unlock();
}
return sb.toString();
}
public void limitReactor(int rid, int num) {
List<MapleReactor> toDestroy = new ArrayList();
Map contained = new LinkedHashMap();
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().lock();
try {
for (MapleMapObject obj : mapobjects.get(MapleMapObjectType.REACTOR).values()) {
MapleReactor mr = (MapleReactor) obj;
if (contained.containsKey(mr.getReactorId())) {
if (((Integer) contained.get(mr.getReactorId())) >= num) {
toDestroy.add(mr);
} else {
contained.put(mr.getReactorId(), ((Integer) contained.get(mr.getReactorId())) + 1);
}
} else {
contained.put(mr.getReactorId(), 1);
}
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().unlock();
}
for (MapleReactor mr : toDestroy) {
destroyReactor(mr.getObjectId());
}
}
public void destroyReactors(int first, int last) {
List<MapleReactor> toDestroy = new ArrayList();
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().lock();
try {
for (MapleMapObject obj : mapobjects.get(MapleMapObjectType.REACTOR).values()) {
MapleReactor mr = (MapleReactor) obj;
if ((mr.getReactorId() >= first) && (mr.getReactorId() <= last)) {
toDestroy.add(mr);
}
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().unlock();
}
for (MapleReactor mr : toDestroy) {
destroyReactor(mr.getObjectId());
}
}
public void destroyReactor(int oid) {
final MapleReactor reactor = getReactorByOid(oid);
if (reactor == null) {
return;
}
broadcastMessage(MaplePacketCreator.destroyReactor(reactor));
reactor.setAlive(false);
removeMapObject(reactor);
reactor.setTimerActive(false);
if (reactor.getDelay() > 0) {
MapTimer.getInstance().schedule(new Runnable() {
@Override
public void run() {
MapleMap.this.respawnReactor(reactor);
}
}, reactor.getDelay());
}
}
public void reloadReactors() {
List<MapleReactor> toSpawn = new ArrayList();
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().lock();
try {
for (MapleMapObject obj : mapobjects.get(MapleMapObjectType.REACTOR).values()) {
MapleReactor reactor = (MapleReactor) obj;
broadcastMessage(MaplePacketCreator.destroyReactor(reactor));
reactor.setAlive(false);
reactor.setTimerActive(false);
toSpawn.add(reactor);
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().unlock();
}
for (MapleReactor r : toSpawn) {
removeMapObject(r);
if (!r.isCustom()) {
respawnReactor(r);
}
}
}
public void resetReactors() {
setReactorState((byte) 0);
}
public void setReactorState() {
setReactorState((byte) 1);
}
public void setReactorState(byte state) {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().lock();
try {
for (MapleMapObject obj : mapobjects.get(MapleMapObjectType.REACTOR).values()) {
((MapleReactor) obj).forceHitReactor(state);
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().unlock();
}
}
public void setReactorDelay(int state) {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().lock();
try {
for (MapleMapObject obj : mapobjects.get(MapleMapObjectType.REACTOR).values()) {
((MapleReactor) obj).setDelay(state);
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().unlock();
}
}
public void shuffleReactors() {
shuffleReactors(0, 9999999);
}
public void shuffleReactors(int first, int last) {
List points = new ArrayList();
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().lock();
try {
for (MapleMapObject obj : mapobjects.get(MapleMapObjectType.REACTOR).values()) {
MapleReactor mr = (MapleReactor) obj;
if ((mr.getReactorId() >= first) && (mr.getReactorId() <= last)) {
points.add(mr.getPosition());
}
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().unlock();
}
Collections.shuffle(points);
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().lock();
try {
for (MapleMapObject obj : mapobjects.get(MapleMapObjectType.REACTOR).values()) {
MapleReactor mr = (MapleReactor) obj;
if ((mr.getReactorId() >= first) && (mr.getReactorId() <= last)) {
mr.setPosition((Point) points.remove(points.size() - 1));
}
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().unlock();
}
}
public void updateMonsterController(MapleMonster monster) {
if (!monster.isAlive() || (monster.getLinkCID() > 0) || (monster.getStats().isEscort())) {
return;
}
MapleCharacter Controller = monster.getController();
if (Controller != null && Controller.getMap() != null) {
if (Controller.getMap().getId() != this.getId() || Controller.getTruePosition().distance(monster.getTruePosition()) > monster.getRange()) {
// FileoutputUtil.log("停止控制 " + monster.getObjectId() +" tr: "+Controller.getTruePosition().distance(monster.getTruePosition())+" "+monster.getRange());
monster.getController().stopControllingMonster(monster);
} else {
return;
}
}
int mincontrolled = -1;
MapleCharacter newController = null;
this.charactersLock.readLock().lock();
try {
for (MapleCharacter chr : this.characters) {
if (!chr.isHidden() && (chr.getControlledSize() < mincontrolled || mincontrolled == -1) && (chr.getTruePosition().distanceSq(monster.getTruePosition()) <= monster.getRange())) {
mincontrolled = chr.getControlledSize();
newController = chr;
}
}
} finally {
this.charactersLock.readLock().unlock();
}
if (newController != null) {
// FileoutputUtil.log("新控制 " + monster.getObjectId());
if (monster.isFirstAttack()) {
newController.controlMonster(monster, true);
monster.setControllerHasAggro(true);
} else {
newController.controlMonster(monster, false);
}
}
}
public final MapleMapObject getMapObject(int oid, MapleMapObjectType type) {
this.mapobjectlocks.get(type).readLock().lock();
try {
return this.mapobjects.get(type).get(oid);
} finally {
this.mapobjectlocks.get(type).readLock().unlock();
}
}
public boolean containsNPC(int npcid) {
this.mapobjectlocks.get(MapleMapObjectType.NPC).readLock().lock();
try {
Iterator itr = ((LinkedHashMap) this.mapobjects.get(MapleMapObjectType.NPC)).values().iterator();
MapleNPC n;
while (itr.hasNext()) {
n = (MapleNPC) itr.next();
if (n.getId() == npcid) {
return true;
}
}
return false;
} finally {
this.mapobjectlocks.get(MapleMapObjectType.NPC).readLock().unlock();
}
}
public MapleNPC getNPCById(int id) {
this.mapobjectlocks.get(MapleMapObjectType.NPC).readLock().lock();
try {
Iterator itr = ((LinkedHashMap) this.mapobjects.get(MapleMapObjectType.NPC)).values().iterator();
MapleNPC n;
while (itr.hasNext()) {
n = (MapleNPC) itr.next();
if (n.getId() == id) {
return n;
}
}
return null;
} finally {
this.mapobjectlocks.get(MapleMapObjectType.NPC).readLock().unlock();
}
}
public MapleMonster getMonsterById(int id) {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.MONSTER)).readLock().lock();
try {
MapleMonster ret = null;
Iterator itr = ((LinkedHashMap) this.mapobjects.get(MapleMapObjectType.MONSTER)).values().iterator();
MapleMonster n;
while (itr.hasNext()) {
n = (MapleMonster) itr.next();
if (n.getId() == id) {
ret = n;
break;
}
}
return ret;
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.MONSTER)).readLock().unlock();
}
}
public int countMonsterById(int id) {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.MONSTER)).readLock().lock();
try {
int ret = 0;
Iterator itr = ((LinkedHashMap) this.mapobjects.get(MapleMapObjectType.MONSTER)).values().iterator();
MapleMonster n;
while (itr.hasNext()) {
n = (MapleMonster) itr.next();
if (n.getId() == id) {
ret++;
}
}
return ret;
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.MONSTER)).readLock().unlock();
}
}
public MapleReactor getReactorById(int id) {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().lock();
try {
MapleReactor ret = null;
Iterator itr = ((LinkedHashMap) this.mapobjects.get(MapleMapObjectType.REACTOR)).values().iterator();
MapleReactor n;
while (itr.hasNext()) {
n = (MapleReactor) itr.next();
if (n.getReactorId() == id) {
ret = n;
break;
}
}
return ret;
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().unlock();
}
}
public MapleMonster getMonsterByOid(int oid) {
MapleMapObject mmo = getMapObject(oid, MapleMapObjectType.MONSTER);
if (mmo == null) {
return null;
}
return (MapleMonster) mmo;
}
public MapleSummon getSummonByOid(int oid) {
MapleMapObject mmo = getMapObject(oid, MapleMapObjectType.SUMMON);
if (mmo == null) {
return null;
}
return (MapleSummon) mmo;
}
public MapleNPC getNPCByOid(int oid) {
MapleMapObject mmo = getMapObject(oid, MapleMapObjectType.NPC);
if (mmo == null) {
return null;
}
return (MapleNPC) mmo;
}
public MapleReactor getReactorByOid(int oid) {
MapleMapObject mmo = getMapObject(oid, MapleMapObjectType.REACTOR);
if (mmo == null) {
return null;
}
return (MapleReactor) mmo;
}
public MonsterFamiliar getFamiliarByOid(int oid) {
MapleMapObject mmo = getMapObject(oid, MapleMapObjectType.FAMILIAR);
if (mmo == null) {
return null;
}
return (MonsterFamiliar) mmo;
}
public MapleDefender getMistByOid(int oid) {
MapleMapObject mmo = getMapObject(oid, MapleMapObjectType.MIST);
if (mmo == null) {
return null;
}
return (MapleDefender) mmo;
}
public MapleReactor getReactorByName(String name) {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().lock();
try {
for (MapleMapObject obj : mapobjects.get(MapleMapObjectType.REACTOR).values()) {
MapleReactor mr = (MapleReactor) obj;
if (mr.getName().equalsIgnoreCase(name)) {
MapleReactor localMapleReactor1 = mr;
return localMapleReactor1;
}
}
return null;
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().unlock();
}
}
public void spawnNpc(int id, Point pos) {
MapleNPC npc = MapleLifeFactory.getNPC(id);
npc.setPosition(pos);
npc.setCy(pos.y);
npc.setRx0(pos.x + 50);
npc.setRx1(pos.x - 50);
npc.setFh(getFootholds().findBelow(pos).getId());
npc.setCustom(true);
addMapObject(npc);
broadcastMessage(NPCPacket.spawnNPC(npc, true));
}
public final void spawnNpcForPlayer(MapleClient c, final int id, final Point pos) {
final MapleNPC npc = MapleLifeFactory.getNPC(id);
npc.setPosition(pos);
npc.setCy(pos.y);
npc.setRx0(pos.x + 50);
npc.setRx1(pos.x - 50);
npc.setFh(getFootholds().findBelow(pos).getId());
npc.setCustom(true);
addMapObject(npc);
c.getSession().write(NPCPacket.spawnNPC(npc, true));
}
public void removeNpc(int npcid) {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.NPC)).writeLock().lock();
try {
Iterator itr = ((LinkedHashMap) this.mapobjects.get(MapleMapObjectType.NPC)).values().iterator();
while (itr.hasNext()) {
MapleNPC npc = (MapleNPC) itr.next();
if ((npc.isCustom()) && ((npcid == -1) || (npc.getId() == npcid))) {
broadcastMessage(NPCPacket.removeNPCController(npc.getObjectId()));
broadcastMessage(NPCPacket.removeNPC(npc.getObjectId()));
itr.remove();
}
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.NPC)).writeLock().unlock();
}
}
public void hideNpc(int npcid) {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.NPC)).readLock().lock();
try {
Iterator itr = ((LinkedHashMap) this.mapobjects.get(MapleMapObjectType.NPC)).values().iterator();
while (itr.hasNext()) {
MapleNPC npc = (MapleNPC) itr.next();
if ((npcid == -1) || (npc.getId() == npcid)) {
broadcastMessage(NPCPacket.removeNPCController(npc.getObjectId()));
broadcastMessage(NPCPacket.removeNPC(npc.getObjectId()));
}
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.NPC)).readLock().unlock();
}
}
public void spawnReactorOnGroundBelow(MapleReactor mob, Point pos) {
mob.setPosition(pos);
mob.setCustom(true);
spawnReactor(mob);
}
public void spawnMonster_sSack(MapleMonster mob, Point pos, int spawnType) {
mob.setPosition(calcPointBelow(new Point(pos.x, pos.y - 1)));
spawnMonster(mob, spawnType);
}
public void spawnMonster_Pokemon(MapleMonster mob, Point pos, int spawnType) {
Point spos = calcPointBelow(new Point(pos.x, pos.y - 1));
mob.setPosition(spos);
spawnMonster(mob, spawnType, true);
}
public void spawnMonsterOnGroundBelow(MapleMonster mob, Point pos) {
spawnMonster_sSack(mob, pos, -2);
}
public int spawnMonsterWithEffectBelow(MapleMonster mob, Point pos, int effect) {
Point spos = calcPointBelow(new Point(pos.x, pos.y - 1));
return spawnMonsterWithEffect(mob, effect, spos);
}
public void spawnZakum(int x, int y) {
Point pos = new Point(x, y);
MapleMonster mainb = MapleLifeFactory.getMonster(8800000);
Point spos = calcPointBelow(new Point(pos.x, pos.y - 1));
mainb.setPosition(spos);
mainb.setFake(true);
spawnFakeMonster(mainb);
int[] zakpart = {8800003, 8800004, 8800005, 8800006, 8800007, 8800008, 8800009, 8800010};
for (int i : zakpart) {
MapleMonster part = MapleLifeFactory.getMonster(i);
part.setPosition(spos);
spawnMonster(part, -2);
}
if (this.squadSchedule != null) {
cancelSquadSchedule(false);
}
}
public void spawnChaosZakum(int x, int y) {
Point pos = new Point(x, y);
MapleMonster mainb = MapleLifeFactory.getMonster(8800100);
Point spos = calcPointBelow(new Point(pos.x, pos.y - 1));
mainb.setPosition(spos);
mainb.setFake(true);
spawnFakeMonster(mainb);
int[] zakpart = {8800103, 8800104, 8800105, 8800106, 8800107, 8800108, 8800109, 8800110};
for (int i : zakpart) {
MapleMonster part = MapleLifeFactory.getMonster(i);
part.setPosition(spos);
spawnMonster(part, -2);
}
if (this.squadSchedule != null) {
cancelSquadSchedule(false);
}
}
public final void spawnSimpleZakum(final int x, final int y) {
final Point pos = new Point(x, y);
final MapleMonster mainb = MapleLifeFactory.getMonster(8800020);
final Point spos = calcPointBelow(new Point(pos.x, pos.y - 1));
mainb.setPosition(spos);
mainb.setFake(true);
// Might be possible to use the map object for reference in future.
spawnFakeMonster(mainb);
final int[] zakpart = {8800023, 8800024, 8800025, 8800026, 8800027,
8800028, 8800029, 8800030};
for (final int i : zakpart) {
final MapleMonster part = MapleLifeFactory.getMonster(i);
part.setPosition(spos);
spawnMonster(part, -2);
}
if (squadSchedule != null) {
cancelSquadSchedule(false);
}
}
public void spawnPinkZakum(int x, int y) {
Point pos = new Point(x, y);
MapleMonster mainb = MapleLifeFactory.getMonster(9400900);
Point spos = calcPointBelow(new Point(pos.x, pos.y - 1));
mainb.setPosition(spos);
mainb.setFake(true);
spawnFakeMonster(mainb);
int[] zakpart = {9400903, 9400904, 9400905, 9400906, 9400907, 9400908, 9400909, 9400910};
for (int i : zakpart) {
MapleMonster part = MapleLifeFactory.getMonster(i);
part.setPosition(spos);
spawnMonster(part, -2);
}
if (this.squadSchedule != null) {
cancelSquadSchedule(false);
}
}
public void spawnFakeMonsterOnGroundBelow(MapleMonster mob, Point pos) {
Point spos = calcPointBelow(new Point(pos.x, pos.y - 1));
spos.y -= 1;
mob.setPosition(spos);
spawnFakeMonster(mob);
}
private void checkRemoveAfter(MapleMonster monster) {
int ra = monster.getStats().getRemoveAfter();
if ((ra > 0) && (monster.getLinkCID() <= 0)) {
monster.registerKill(ra * 1000);
}
}
public void spawnRevives(final MapleMonster monster, final int oid) {
monster.setMap(this);
checkRemoveAfter(monster);
monster.setLinkOid(oid);
spawnAndAddRangedMapObject(monster, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
c.getSession().write(MobPacket.spawnMonster(monster, monster.getStats().getSummonType() <= 1 ? -3 : monster.getStats().getSummonType(), oid));
}
});
updateMonsterController(monster);
this.spawnedMonstersOnMap.incrementAndGet();
}
public void spawnMonster(MapleMonster monster, int spawnType) {
spawnMonster(monster, spawnType, false);
}
public void spawnMonster(final MapleMonster monster, final int spawnType, final boolean overwrite) {
monster.setMap(this);
checkRemoveAfter(monster);
if (monster.getId() == 9300166) {
MapTimer.getInstance().schedule(new Runnable() {
@Override
public void run() {
broadcastMessage(MobPacket.killMonster(monster.getObjectId(), 2));
}
}, 3000);
}
spawnAndAddRangedMapObject(monster, new DelayedPacketCreation() {
@Override
public final void sendPackets(MapleClient c) {
c.getSession().write(MobPacket.spawnMonster(monster, monster.getStats().getSummonType() <= 1 || monster.getStats().getSummonType() == 27 || overwrite ? spawnType : monster.getStats().getSummonType(), 0));
}
});
updateMonsterController(monster);
spawnedMonstersOnMap.incrementAndGet();
}
public int spawnMonsterWithEffect(final MapleMonster monster, final int effect, Point pos) {
try {
monster.setMap(this);
monster.setPosition(pos);
spawnAndAddRangedMapObject(monster, new DelayedPacketCreation() // spawnAndAddRangedMapObject(monster, new DelayedPacketCreation(monster, effect)
{
@Override
public void sendPackets(MapleClient c) {
c.getSession().write(MobPacket.spawnMonster(monster, effect, 0));
}
});
updateMonsterController(monster);
this.spawnedMonstersOnMap.incrementAndGet();
return monster.getObjectId();
} catch (Exception e) {
}
return -1;
}
public void spawnFakeMonster(final MapleMonster monster) {
monster.setMap(this);
monster.setFake(true);
spawnAndAddRangedMapObject(monster, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
c.getSession().write(MobPacket.spawnMonster(monster, -4, 0));
}
});
updateMonsterController(monster);
this.spawnedMonstersOnMap.incrementAndGet();
}
public void spawnReactor(final MapleReactor reactor) {
reactor.setMap(this);
spawnAndAddRangedMapObject(reactor, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
c.getSession().write(MaplePacketCreator.spawnReactor(reactor));
}
});
}
private void respawnReactor(MapleReactor reactor) {
if ((!isSecretMap()) && (reactor.getReactorId() >= 100000) && (reactor.getReactorId() <= 200011)) {
int newRid = (reactor.getReactorId() < 200000 ? 100000 : 200000) + Randomizer.nextInt(11);
int prop = reactor.getReactorId() % 100;
if ((Randomizer.nextInt(22) <= prop) && (newRid % 100 < 10)) {
newRid++;
}
if ((Randomizer.nextInt(110) <= prop) && (newRid % 100 < 11)) {
newRid++;
}
List toSpawnPos = new ArrayList(this.spawnPoints);
for (MapleMapObject reactor1l : getAllReactorsThreadsafe()) {
MapleReactor reactor2l = (MapleReactor) reactor1l;
if ((!toSpawnPos.isEmpty()) && (toSpawnPos.contains(reactor2l.getPosition()))) {
toSpawnPos.remove(reactor2l.getPosition());
}
}
MapleReactor newReactor = new MapleReactor(MapleReactorFactory.getReactor(newRid), newRid);
newReactor.setPosition(toSpawnPos.isEmpty() ? reactor.getPosition() : (Point) toSpawnPos.get(Randomizer.nextInt(toSpawnPos.size())));
newReactor.setDelay(newRid % 100 == 11 ? 60000 : 5000);
spawnReactor(newReactor);
} else {
reactor.setState((byte) 0);
reactor.setAlive(true);
spawnReactor(reactor);
}
}
public boolean isSecretMap() {
switch (this.mapid) {
case 910001001:
case 910001002:
case 910001003:
case 910001004:
case 910001005:
case 910001006:
case 910001007:
case 910001008:
case 910001009:
case 910001010:
return true;
}
return false;
}
public final void spawnDoor(final MapleDoor door) {
spawnAndAddRangedMapObject(door, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
door.sendSpawnData(c);
c.getSession().write(MaplePacketCreator.enableActions());
}
});
}
public final void spawnArrowsTurret(final MapleArrowsTurret aturet) { //召唤箭矢炮盘
MapTimer tMan = MapTimer.getInstance();
final ScheduledFuture poisonSchedule;
spawnAndAddRangedMapObject(aturet, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
broadcastMessage(SkillPacket.spawnArrowsTurret(aturet));
c.getSession().write(SkillPacket.ArrowsTurretAction(aturet));
}
});
poisonSchedule = tMan.register(new Runnable() {
@Override
public void run() {
//for (MapleCharacter chr : aturet.getMap().getCharacters()) {
if (MapleMap.this.getCharacterById(aturet.getOwnerId()) == null) {
//if (!aturet.getMap().getCharacters().equals(aturet.getOwner())) {
MapleMap.this.removeMapObject(aturet);
MapleMap.this.broadcastMessage(SkillPacket.cancelArrowsTurret(aturet));
}
}
}, 500, 500);
aturet.setSchedule(tMan.schedule(new Runnable() {
@Override
public void run() {
poisonSchedule.cancel(false);
MapleMap.this.removeMapObject(aturet);
MapleMap.this.broadcastMessage(SkillPacket.cancelArrowsTurret(aturet));
}
}, ((20 + (long) Math.floor(aturet.getSkillLevel() / 3)) * 1000)));
}
public final void spawnSummon(final MapleSummon summon) {//第二次发送的召唤兽包
summon.updateMap(this);
spawnAndAddRangedMapObject(summon, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
if ((summon != null) && (c.getPlayer() != null) && ((!summon.isChangedMap()) || (summon.getOwnerId() == c.getPlayer().getId()))) {
c.getSession().write(SummonPacket.spawnSummon(summon, true));
}
}
});
}
public void spawnFamiliar(final MonsterFamiliar familiar) {
spawnAndAddRangedMapObject(familiar, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
if ((familiar != null) && (c.getPlayer() != null)) {
c.getSession().write(MaplePacketCreator.spawnFamiliar(familiar, true));
}
}
});
}
public void spawnExtractor(final MapleExtractor ex) {
spawnAndAddRangedMapObject(ex, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
ex.sendSpawnData(c);
}
});
}
public void spawnLove(final MapleLove love) {
spawnAndAddRangedMapObject(love, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
love.sendSpawnData(c);
}
});
MapTimer tMan = MapTimer.getInstance();
tMan.schedule(new Runnable() {
@Override
public void run() {
MapleMap.this.broadcastMessage(MaplePacketCreator.removeLove(love.getObjectId(), love.getItemId()));
MapleMap.this.removeMapObject(love);
}
}, 3600000L);
}
public void spawnMist(final MapleDefender mist, final int duration, boolean fake) {
spawnAndAddRangedMapObject(mist, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
mist.sendSpawnData(c);
}
});
MapTimer tMan = MapTimer.getInstance();
final ScheduledFuture poisonSchedule;
if ((mist.isPoisonMist()) && (!mist.isMobMist())) {
final MapleCharacter owner = getCharacterById(mist.getOwnerId());
poisonSchedule = tMan.register(new Runnable() {
@Override
public void run() {
for (MapleMapObject mo : MapleMap.this.getMapObjectsInRect(mist.getBox(), Collections.singletonList(MapleMapObjectType.MONSTER))) {
if ((mist.makeChanceResult()) && (!((MapleCharacter) mo).hasDOT()) && (((MapleCharacter) mo).getId() != mist.getOwnerId())) {
((MapleCharacter) mo).setDOT(mist.getSource().getDOT(), mist.getSourceSkill().getId(), mist.getSkillLevel());
} else if ((mist.makeChanceResult()) && (!((MapleMonster) mo).isBuffed(MonsterStatus.中毒))
&& (owner != null)) {
((MapleMonster) mo).applyStatus(owner, new MonsterStatusEffect(MonsterStatus.中毒, 1, mist.getSourceSkill().getId(), null, false), true, duration, true, mist.getSource());
}
}
}
}, 2000, 2500);
} else {//poisonSchedule = tMan.register(new Runnable()
//ScheduledFuture poisonSchedule;
if (mist.isRecoverMist()) {
poisonSchedule = tMan.register(new Runnable() {
@Override
public void run() {
for (MapleMapObject mo : MapleMap.this.getMapObjectsInRect(mist.getBox(), Collections.singletonList(MapleMapObjectType.PLAYER))) {
MapleCharacter chr = (MapleCharacter) mo;
if (mist.makeChanceResult() && chr.isAlive()) {
chr.addMPHP((int) ((mist.getSource().getX() * (chr.getStat().getMaxHp() / 100.0D))), (int) (mist.getSource().getX() * (chr.getStat().getMaxMp() / 100.0D)));
}
}
}
}, 2000, 2500);
} else if (!mist.isMobMist() && mist.getSourceSkill().getId() == 4121015) {
final MapleCharacter owner = getCharacterById(mist.getOwnerId());
poisonSchedule = tMan.register(new Runnable() {
@Override
public void run() {
for (MapleMapObject mo : MapleMap.this.getMapObjectsInRect(mist.getBox(), Collections.singletonList( MapleMapObjectType.MONSTER))) {
if ((mist.makeChanceResult()) && (!((MapleCharacter) mo).hasDOT()) && (((MapleCharacter) mo).getId() != mist.getOwnerId())) {
((MapleCharacter) mo).setDOT(mist.getSource().getDOT(), mist.getSourceSkill().getId(), mist.getSkillLevel());
} else if ((mist.makeChanceResult()) && (!((MapleMonster) mo).isBuffed(MonsterStatus.中毒))
&& (owner != null)) {
((MapleMonster) mo).applyStatus(owner, new MonsterStatusEffect(MonsterStatus.物攻, -mist.getSource().getW(), mist.getSourceSkill().getId(), null, false), false, duration, true, mist.getSource());
((MapleMonster) mo).applyStatus(owner, new MonsterStatusEffect(MonsterStatus.魔攻, -mist.getSource().getW(), mist.getSourceSkill().getId(), null, false), false, duration, true, mist.getSource());
((MapleMonster) mo).applyStatus(owner, new MonsterStatusEffect(MonsterStatus.速度, mist.getSource().getY(), mist.getSourceSkill().getId(), null, false), false, duration, true, mist.getSource());
}
}
}
}, 2000, 2500);
} else if ((mist.isPoisonMist()) && (mist.isMobMist())) {
poisonSchedule = tMan.register(new Runnable() {
@Override
public void run() {
for (MapleMapObject mo : MapleMap.this.getMapObjectsInRect(mist.getBox(), Collections.singletonList(MapleMapObjectType.PLAYER))) {
((MapleCharacter) mo).setDOT(mist.getSource().getDOT(), mist.getMobSkill().getSkillId(), mist.getMobSkill().getSkillLevel());
}
}
}, 2000, 2500);
}else if ((mist.isGivebuff()) && (!mist.isMobMist())) {
poisonSchedule = tMan.register(new Runnable() {
@Override
public void run() {
for (MapleMapObject mo : MapleMap.this.getMapObjectsInRect(mist.getBox(), Collections.singletonList(MapleMapObjectType.PLAYER))) {
if (((MapleCharacter) mo).getParty() != null && ((MapleCharacter) mo).getParty().getMemberById(mist.getOwnerId()) != null && ((MapleCharacter) mo).getBuffStats(mist.getSource(), -1) == null || ((MapleCharacter) mo).getId() == mist.getOwnerId() && ((MapleCharacter) mo).getBuffStats(mist.getSource(), -1) == null) {
mist.getSource().applyBuffEffect(((MapleCharacter) mo), mist.getSource().getDuration());
}
}
if (MapleMap.this.getCharacterById_InMap(mist.getOwnerId()).getParty() != null && mist.getSourceSkill().getId() != 35121010) {
for (MaplePartyCharacter mo : MapleMap.this.getCharacterById_InMap(mist.getOwnerId()).getParty().getMembers()) {
if (!getCharactersIntersect(mist.getBox()).contains(MapleMap.this.getCharacterById_InMap(mo.getId())) && MapleMap.this.getCharacterById_InMap(mo.getId()).getBuffStats(mist.getSource(), -1) != null) {
MapleMap.this.getCharacterById_InMap(mo.getId()).cancelEffect(mist.getSource(), false, -1);
}
}
}
}
}, 2000, 2500);
} else {
int id = mist.isMobMist() ? mist.getMobSkill().getSkillId() : mist.getSourceSkill().getId();
String from = mist.isMobMist() ? "怪物" : "玩家:" + mist.getOwnerId();
FileoutputUtil.log("[未处理 mist] 来自 " + from + " 技能ID:" + id + "");
poisonSchedule = null;
}
}
mist.setPoisonSchedule(poisonSchedule);
mist.setSchedule(tMan.schedule(new Runnable() {
@Override
public void run() {
MapleMap.this.removeMapObject(mist);
if (poisonSchedule != null) {
poisonSchedule.cancel(false);
}
MapleMap.this.broadcastMessage(MaplePacketCreator.removeMist(mist.getObjectId(), false));
}
}, duration));
}
public void disappearingItemDrop(MapleMapObject dropper, MapleCharacter owner, Item item, Point pos) {
Point droppos = calcDropPos(pos, pos);
MapleMapItem drop = new MapleMapItem(item, droppos, dropper, owner, (byte) 1, false);
broadcastMessage(InventoryPacket.dropItemFromMapObject(drop, dropper.getTruePosition(), droppos, (byte) 3, false), drop.getTruePosition());
}
public void spawnMesoDrop(int meso, Point position, final MapleMapObject dropper, MapleCharacter owner, boolean playerDrop, byte droptype) {
final Point droppos = calcDropPos(position, position);
final MapleMapItem mdrop = new MapleMapItem(meso, droppos, dropper, owner, droptype, playerDrop);
spawnAndAddRangedMapObject(mdrop, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
c.getSession().write(InventoryPacket.dropItemFromMapObject(mdrop, dropper.getTruePosition(), droppos, (byte) 1, false));
}
});
if (!this.everlast) {
mdrop.registerExpire(120000L);
if ((droptype == 0) || (droptype == 1)) {
mdrop.registerFFA(30000L);
}
}
}
public void spawnMobMesoDrop(int meso, final Point position, final MapleMapObject dropper, MapleCharacter owner, boolean playerDrop, byte droptype) {
final MapleMapItem mdrop = new MapleMapItem(meso, position, dropper, owner, droptype, playerDrop);
spawnAndAddRangedMapObject(mdrop, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
c.getSession().write(InventoryPacket.dropItemFromMapObject(mdrop, dropper.getTruePosition(), position, (byte) 1, false));
}
});
mdrop.registerExpire(120000L);
if ((droptype == 0) || (droptype == 1)) {
mdrop.registerFFA(30000L);
}
}
public void spawnMobDrop(final Item idrop, final Point dropPos, final MapleMonster mob, MapleCharacter chr, byte droptype, final int questid) {
final MapleMapItem mdrop = new MapleMapItem(idrop, dropPos, mob, chr, droptype, false, questid);
spawnAndAddRangedMapObject(mdrop, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
if ((c != null) && (c.getPlayer() != null) && ((questid <= 0) || (c.getPlayer().getQuestStatus(questid) == 1)) && ((idrop.getItemId() / 10000 != 238) ) && (mob != null) && (dropPos != null)) {
c.getSession().write(InventoryPacket.dropItemFromMapObject(mdrop, mob.getTruePosition(), dropPos, (byte) 1, false));
}
}
});
mdrop.registerExpire(120000L);
if ((droptype == 0) || (droptype == 1)) {
mdrop.registerFFA(30000L);
}
activateItemReactors(mdrop, chr.getClient());
}
public void spawnRandDrop() {
if ((this.mapid != 910000000) || (this.channel != 1)) {
return;
}
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.ITEM)).readLock().lock();
try {
for (MapleMapObject o : mapobjects.get(MapleMapObjectType.ITEM).values()) {
if (((MapleMapItem) o).isRandDrop()) {
return;
}
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.ITEM)).readLock().unlock();
}
MapTimer.getInstance().schedule(new Runnable() {
@Override
public void run() {
Point pos = new Point(Randomizer.nextInt(800) + 531, -806);
int theItem = Randomizer.nextInt(1000);
int itemid;
if (theItem < 950) {
itemid = GameConstants.normalDrops[Randomizer.nextInt(GameConstants.normalDrops.length)];
} else {
if (theItem < 990) {
itemid = GameConstants.rareDrops[Randomizer.nextInt(GameConstants.rareDrops.length)];
} else {
itemid = GameConstants.superDrops[Randomizer.nextInt(GameConstants.superDrops.length)];
}
}
MapleMap.this.spawnAutoDrop(itemid, pos);
}
}, 20000L);
}
public void spawnAutoDrop(int itemid, final Point pos) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
Item idrop;
if (ItemConstants.getInventoryType(itemid) == MapleInventoryType.EQUIP) {
idrop = ii.randomizeStats((Equip) ii.getEquipById(itemid));
} else {
idrop = new Item(itemid, (byte) 0, (short) 1, (short) 0);
}
idrop.setGMLog(new StringBuilder().append("自动掉落 ").append(itemid).append(" 地图 ").append(this.mapid).toString());
final MapleMapItem mdrop = new MapleMapItem(pos, idrop);
spawnAndAddRangedMapObject(mdrop, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
c.getSession().write(InventoryPacket.dropItemFromMapObject(mdrop, pos, pos, (byte) 1, false));
}
});
broadcastMessage(InventoryPacket.dropItemFromMapObject(mdrop, pos, pos, (byte) 0, false));
if (itemid / 10000 != 291) {
mdrop.registerExpire(120000L);
}
}
public void spawnItemDrop(final MapleMapObject dropper, MapleCharacter owner, Item item, Point pos, boolean ffaDrop, boolean playerDrop) {
final Point droppos = calcDropPos(pos, pos);
final MapleMapItem drop = new MapleMapItem(item, droppos, dropper, owner, (byte) 2, playerDrop);
spawnAndAddRangedMapObject(drop, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
c.getSession().write(InventoryPacket.dropItemFromMapObject(drop, dropper.getTruePosition(), droppos, (byte) 1, false));
}
});
broadcastMessage(InventoryPacket.dropItemFromMapObject(drop, dropper.getTruePosition(), droppos, (byte) 0, false));
if (!this.everlast) {
drop.registerExpire(120000L);
activateItemReactors(drop, owner.getClient());
}
}
public void spawnItemDrop(final MapleMapObject dropper, MapleCharacter owner,int itemId,short quantity) {
final Point droppos = calcDropPos(owner.getPosition(), owner.getPosition());
Item toDrop;
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
if (GameConstants.getInventoryType(itemId) == MapleInventoryType.EQUIP) {
toDrop = ii.randomizeStats((Equip) ii.getEquipById(itemId));
} else {
toDrop = new client.inventory.Item(itemId, (byte) 0, quantity, (byte) 0);
}
final MapleMapItem drop = new MapleMapItem(toDrop, droppos, dropper, owner, (byte) 2, false);
spawnAndAddRangedMapObject(drop, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
c.getSession().write(InventoryPacket.dropItemFromMapObject(drop, dropper.getTruePosition(), droppos, (byte) 1, false));
}
});
broadcastMessage(InventoryPacket.dropItemFromMapObject(drop, dropper.getTruePosition(), droppos, (byte) 0, false));
if (!this.everlast) {
drop.registerExpire(120000L);
activateItemReactors(drop, owner.getClient());
}
}
private void activateItemReactors(MapleMapItem drop, MapleClient c) {
Item item = drop.getItem();
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().lock();
try {
for (MapleMapObject o : mapobjects.get(MapleMapObjectType.REACTOR).values()) {
MapleReactor react = (MapleReactor) o;
if ((react.getReactorType() == 100)
&& (item.getItemId() == GameConstants.getCustomReactItem(react.getReactorId(), (react.getReactItem().getLeft()))) && ((react.getReactItem().getRight()) == item.getQuantity())
&& (react.getArea().contains(drop.getTruePosition()))
&& (!react.isTimerActive())) {
MapTimer.getInstance().schedule(new ActivateItemReactor(drop, react, c), 5000L);
react.setTimerActive(true);
break;
}
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.REACTOR)).readLock().unlock();
}
}
public int getItemsSize() {
return ((LinkedHashMap) this.mapobjects.get(MapleMapObjectType.ITEM)).size();
}
public int getExtractorSize() {
return ((LinkedHashMap) this.mapobjects.get(MapleMapObjectType.EXTRACTOR)).size();
}
public int getMobsSize() {
return ((LinkedHashMap) this.mapobjects.get(MapleMapObjectType.MONSTER)).size();
}
public int getRunesSize() {
return ((LinkedHashMap) this.mapobjects.get(MapleMapObjectType.MAPLE_RUNE)).size();
}
public List<MapleMapItem> getAllItems() {
return getAllItemsThreadsafe();
}
public List<MapleMapItem> getAllItemsThreadsafe() {
ArrayList ret = new ArrayList();
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.ITEM)).readLock().lock();
try {
for (MapleMapObject mmo : mapobjects.get(MapleMapObjectType.ITEM).values()) {
ret.add((MapleMapItem) mmo);
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.ITEM)).readLock().unlock();
}
return ret;
}
public Point getPointOfItem(int itemid) {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.ITEM)).readLock().lock();
try {
for (MapleMapObject mmo : mapobjects.get(MapleMapObjectType.ITEM).values()) {
MapleMapItem mm = (MapleMapItem) mmo;
if ((mm.getItem() != null) && (mm.getItem().getItemId() == itemid)) {
Point localPoint = mm.getPosition();
return localPoint;
}
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.ITEM)).readLock().unlock();
}
return null;
}
public List<MapleDefender> getAllMistsThreadsafe() {
ArrayList ret = new ArrayList();
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.MIST)).readLock().lock();
try {
for (MapleMapObject mmo : mapobjects.get(MapleMapObjectType.MIST).values()) {
ret.add((MapleDefender) mmo);
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.MIST)).readLock().unlock();
}
return ret;
}
public void returnEverLastItem(MapleCharacter chr) {
for (MapleMapObject o : getAllItemsThreadsafe()) {
MapleMapItem item = (MapleMapItem) o;
if (item.getOwner() == chr.getId()) {
item.setPickedUp(true);
broadcastMessage(InventoryPacket.removeItemFromMap(item.getObjectId(), 2, chr.getId()), item.getTruePosition());
if (item.getMeso() > 0) {
chr.gainMeso(item.getMeso(), false);
} else {
MapleInventoryManipulator.addFromDrop(chr.getClient(), item.getItem(), false);
}
removeMapObject(item);
}
}
spawnRandDrop();
}
public void startMapEffect(String msg, int itemId) {
startMapEffect(msg, itemId, false);
}
public void startMapEffect(String msg, int itemId, boolean jukebox) {
if (this.mapEffect != null) {
return;
}
this.mapEffect = new MapleMapEffect(msg, itemId);
this.mapEffect.setJukebox(jukebox);
broadcastMessage(this.mapEffect.makeStartData());
MapTimer.getInstance().schedule(new Runnable() {
@Override
public void run() {
if (MapleMap.this.mapEffect != null) {
MapleMap.this.broadcastMessage(MapleMap.this.mapEffect.makeDestroyData());
MapleMap.this.mapEffect = null;
}
}
}, jukebox ? 300000L : 30000L);
}
public void startPredictCardMapEffect(String msg, int itemId, int effectType) {
startMapEffect(msg, itemId, 30, effectType);
}
public void startMapEffect(String msg, int itemId, int time) {
startMapEffect(msg, itemId, time, -1);
}
public void startMapEffect(String msg, int itemId, int time, int effectType) {
if (this.mapEffect != null) {
return;
}
if (time <= 0) {
time = 5;
}
this.mapEffect = new MapleMapEffect(msg, itemId, effectType);
this.mapEffect.setJukebox(false);
// broadcastMessage(this.mapEffect.makeStartData());
MapTimer.getInstance().schedule(new Runnable() {
@Override
public void run() {
if (MapleMap.this.mapEffect != null) {
MapleMap.this.broadcastMessage(MapleMap.this.mapEffect.makeDestroyData());
MapleMap.this.mapEffect = null;
}
}
}, time * 1000);
}
public void startExtendedMapEffect(final String msg, final int itemId) {
broadcastMessage(MaplePacketCreator.startMapEffect(msg, itemId, true));
MapTimer.getInstance().schedule(new Runnable() {
@Override
public void run() {
MapleMap.this.broadcastMessage(MaplePacketCreator.removeMapEffect());
MapleMap.this.broadcastMessage(MaplePacketCreator.startMapEffect(msg, itemId, false));
}
}, 60000L);
}
public void startSimpleMapEffect(String msg, int itemId) {
broadcastMessage(MaplePacketCreator.startMapEffect(msg, itemId, true));
}
public void startJukebox(String msg, int itemId) {
startMapEffect(msg, itemId, true);
}
/**
* 添加玩家到地图
*
* @param chr
*/
public final void addPlayer(final MapleCharacter chr) {
this.mapobjectlocks.get(MapleMapObjectType.PLAYER).writeLock().lock();
try {
this.mapobjects.get(MapleMapObjectType.PLAYER).put(chr.getObjectId(), chr);
} finally {
this.mapobjectlocks.get(MapleMapObjectType.PLAYER).writeLock().unlock();
}
this.charactersLock.writeLock().lock();
try {
this.characters.add(chr);
} finally {
this.charactersLock.writeLock().unlock();
}
chr.setChangeTime(true);
if ((GameConstants.isTeamMap(this.mapid))) {
chr.setTeam(getAndSwitchTeam() ? 0 : 1);
}
byte[] packet = MaplePacketCreator.spawnPlayerMapobject(chr); //封包在这
if (!chr.isHidden()) {
broadcastMessage(chr, packet, false);
if ((chr.isIntern()) && (this.speedRunStart > 0L)) {
endSpeedRun();
broadcastMessage(MaplePacketCreator.serverMessageNotice("The speed run has ended."));
}
} else {
broadcastGMMessage(chr, packet, false);
}
if (!onFirstUserEnter.equals("")) {
if (getCharactersSize() == 1) {
MapScriptMethods.startScript_FirstUser(chr.getClient(), onFirstUserEnter);
}
}
if (!onUserEnter.equals("")) {
MapScriptMethods.startScript_User(chr.getClient(), onUserEnter);
}
sendObjectPlacement(chr);
// GameConstants.achievementRatio(chr.getClient());
if ((GameConstants.isTeamMap(this.mapid)) ) {
//chr.getClient().getSession().write(MaplePacketCreator.showEquipEffect(chr.getTeam()));
}
MaplePet pets = chr.getSpawnPets(); //宠物发的包
if ((pets != null) && (pets.getSummoned())) {
pets.setPos(chr.getTruePosition());
// chr.getClient().getSession().write(PetPacket.updatePet(pets, chr.getInventory(MapleInventoryType.CASH).getItem((short) (byte) pets.getInventoryPosition()), false));
chr.getClient().getSession().write(PetPacket.showPet(chr, pets, false, false, true));
// chr.getClient().getSession().write(PetPacket.loadExceptionList(chr, pets));
}
if (chr.getSummonedFamiliar() != null) {
// chr.spawnFamiliar(chr.getSummonedFamiliar());
}
if (chr.getParty() != null) {
// chr.silentPartyUpdate();
// chr.getClient().getSession().write(PartyPacket.updateParty(chr.getClient().getChannel(), chr.getParty(), PartyOperation.更新队伍, null));
// chr.updatePartyMemberHP();
// chr.receivePartyMemberHP();
}
boolean quickMove = false;
if ((!chr.isInBlockedMap()) && (chr.getLevel() >= 10)) {
for (MapleQuickMove qm : MapleQuickMove.values()) {
if (qm.getMap() == chr.getMapId()) {
List<MapleQuickMove.QuickMoveNPC> qmn = new LinkedList();
int npcs = qm.getNPCFlag();
for (MapleQuickMove.QuickMoveNPC npc : MapleQuickMove.QuickMoveNPC.values()) {
if ((npcs & npc.getValue()) != 0 && npc.show()) {
qmn.add(npc);
}
}
quickMove = true;
chr.getClient().getSession().write(MaplePacketCreator.getQuickMoveInfo(true, qmn));
break;
}
}
}
if (!quickMove) {
// chr.getClient().getSession().write(MaplePacketCreator.getQuickMoveInfo(false, new LinkedList()));
}
Map<Integer,MapleSummon> ss = chr.getSummonsReadLock();//召唤兽
try {
for (MapleSummon summon : ss.values()) {
summon.setPosition(chr.getTruePosition());
chr.addVisibleMapObject(summon);
spawnSummon(summon);
}
} finally {
chr.unlockSummonsReadLock();
}
// if (this.mapEffect != null) {
// this.mapEffect.sendStartData(chr.getClient());
// }
if ((this.timeLimit > 0) && (getForcedReturnMap() != null)) {
chr.startMapTimeLimitTask(this.timeLimit, getForcedReturnMap());
}
// if ((chr.getBuffedValue(MapleBuffStat.骑兽技能) != null) && (!GameConstants.is反抗者(chr.getJob()))
// && (FieldLimitType.Mount.check(this.fieldLimit))) {
// chr.cancelEffectFromBuffStat(MapleBuffStat.骑兽技能);
// }
if (chr.getSidekick() != null) {
MapleCharacter side = getCharacterById(chr.getSidekick().getCharacter(chr.getSidekick().getCharacter(0).getId() == chr.getId() ? 1 : 0).getId());
if (side != null) {
chr.getSidekick().applyBuff(side);
chr.getSidekick().applyBuff(chr);
}
}
if ((chr.getEventInstance() != null) && (chr.getEventInstance().isTimerStarted())) {
chr.getClient().getSession().write(MaplePacketCreator.getClock((int) (chr.getEventInstance().getTimeLeft() / 1000L)));
}
if (hasClock()) {
Calendar cal = Calendar.getInstance();
chr.getClient().getSession().write(MaplePacketCreator.getClockTime(cal.get(11), cal.get(12), cal.get(13)));
}
if(hasBoat() == 2) { // 船还在
chr.getClient().getSession().write(MaplePacketCreator.boatPacket(true));
}
if ((chr.getCarnivalParty() != null) && (chr.getEventInstance() != null)) {
chr.getEventInstance().onMapLoad(chr);
}
MapleEvent.mapLoad(chr, this.channel);
if ((getSquadBegin() != null) && (getSquadBegin().getTimeLeft() > 0L) && (getSquadBegin().getStatus() == 1)) {
chr.getClient().getSession().write(MaplePacketCreator.getClock((int) (getSquadBegin().getTimeLeft() / 1000L)));
}
if ((this.mapid / 1000 != 105100) && (this.mapid / 100 != 8020003) && (this.mapid / 100 != 8020008) && (this.mapid != 271040100)) {
MapleSquad sqd = getSquadByMap();
EventManager em = getEMByMap();
if ((!this.squadTimer) && (sqd != null) && (chr.getName().equals(sqd.getLeaderName())) && (em != null) && (em.getProperty("leader") != null) && (em.getProperty("leader").equals("true")) && (this.checkStates)) {
doShrine(false);
this.squadTimer = true;
}
}
if ((getNumMonsters() > 0) && ((this.mapid == 280030001) || (this.mapid == 240060201) || (this.mapid == 280030000) || (this.mapid == 280030100) || (this.mapid == 240060200) || (this.mapid == 220080001) || (this.mapid == 541020800) || (this.mapid == 541010100))) {
String music = "Bgm09/TimeAttack";
switch (this.mapid) {
case 240060200:
case 240060201:
music = "Bgm14/HonTale";
break;
case 280030000:
case 280030001:
case 280030100:
music = "Bgm06/FinalFight";
}
chr.getClient().getSession().write(MaplePacketCreator.musicChange(music));
}
if (this.permanentWeather > 0) {
chr.getClient().getSession().write(MaplePacketCreator.startMapEffect("", this.permanentWeather, false));
}
if (getPlatforms().size() > 0) {
chr.getClient().getSession().write(MaplePacketCreator.getMovingPlatforms(this));
}
if (this.environment.size() > 0) {
chr.getClient().getSession().write(MaplePacketCreator.getUpdateEnvironment(this));
}
}
public int getNumItems() {
mapobjectlocks.get(MapleMapObjectType.ITEM).readLock().lock();
try {
return mapobjects.get(MapleMapObjectType.ITEM).size();
} finally {
mapobjectlocks.get(MapleMapObjectType.ITEM).readLock().unlock();
}
}
public int getNumMonsters() {
mapobjectlocks.get(MapleMapObjectType.MONSTER).readLock().lock();
try {
return mapobjects.get(MapleMapObjectType.MONSTER).size();
} finally {
mapobjectlocks.get(MapleMapObjectType.MONSTER).readLock().unlock();
}
}
public void doShrine(final boolean spawned) {
if (this.squadSchedule != null) {
cancelSquadSchedule(true);
}
MapleSquad sqd = getSquadByMap();
if (sqd == null) {
return;
}
final int mode = (this.mapid == 240060200) || (this.mapid == 240060201) ? 3 : this.mapid == 280030001 ? 2 : (this.mapid == 280030000) || (this.mapid == 280030100) ? 1 : 0;
EventManager em = getEMByMap();
if ((em != null) && (getCharactersSize() > 0)) {
final String leaderName = sqd.getLeaderName();
final String state = em.getProperty("state");
MapleMap returnMapa = getForcedReturnMap();
if ((returnMapa == null) || (returnMapa.getId() == this.mapid)) {
returnMapa = getReturnMap();
}
if (mode == 1 || mode == 2) { //chaoszakum
broadcastMessage(MaplePacketCreator.showChaosZakumShrine(spawned, 5));
} else if (mode == 3) { //ht/chaosht
broadcastMessage(MaplePacketCreator.showChaosHorntailShrine(spawned, 5));
} else {
broadcastMessage(MaplePacketCreator.showHorntailShrine(spawned, 5));
}
if (spawned) { //both of these together dont go well
broadcastMessage(MaplePacketCreator.getClock(300));
}
final MapleMap returnMapz = returnMapa;
Runnable run;
if (!spawned) {
final List<MapleMonster> monsterz = getAllMonstersThreadsafe();
final List<Integer> monsteridz = new ArrayList<>();
for (MapleMapObject m : monsterz) {
monsteridz.add(m.getObjectId());
}
run = new Runnable() {
@Override
public void run() {
MapleSquad sqnow = MapleMap.this.getSquadByMap();
if ((MapleMap.this.getCharactersSize() > 0) && (MapleMap.this.getNumMonsters() == monsterz.size()) && (sqnow != null) && (sqnow.getStatus() == 2) && (sqnow.getLeaderName().equals(leaderName)) && (MapleMap.this.getEMByMap().getProperty("state").equals(state))) {
boolean passed = monsterz.isEmpty();
for (MapleMapObject m : MapleMap.this.getAllMonstersThreadsafe()) {
for (int i : monsteridz) {
if (m.getObjectId() == i) {
passed = true;
break;
}
}
if (passed) {
break;
}
}
if (passed) {
byte[] packet;
if ((mode == 1) || (mode == 2)) {
packet = MaplePacketCreator.showChaosZakumShrine(spawned, 0);
} else {
packet = MaplePacketCreator.showHorntailShrine(spawned, 0);
}
for (MapleCharacter chr : MapleMap.this.getCharactersThreadsafe()) {
chr.getClient().getSession().write(packet);
chr.changeMap(returnMapz, returnMapz.getPortal(0));
}
MapleMap.this.checkStates("");
MapleMap.this.resetFully();
}
}
}
};
} else {
run = new Runnable() {
@Override
public void run() {
MapleSquad sqnow = MapleMap.this.getSquadByMap();
if ((MapleMap.this.getCharactersSize() > 0) && (sqnow != null) && (sqnow.getStatus() == 2) && (sqnow.getLeaderName().equals(leaderName)) && (MapleMap.this.getEMByMap().getProperty("state").equals(state))) {
byte[] packet;
if ((mode == 1) || (mode == 2)) {
packet = MaplePacketCreator.showChaosZakumShrine(spawned, 0);
} else {
packet = MaplePacketCreator.showHorntailShrine(spawned, 0);
}
for (MapleCharacter chr : MapleMap.this.getCharactersThreadsafe()) {
chr.getClient().getSession().write(packet);
chr.changeMap(returnMapz, returnMapz.getPortal(0));
}
MapleMap.this.checkStates("");
MapleMap.this.resetFully();
}
}
};
}
this.squadSchedule = MapTimer.getInstance().schedule(run, 300000L);
}
}
public MapleSquad getSquadByMap() {
MapleSquadType zz;
switch (this.mapid) {
case 105100300:
case 105100400:
zz = MapleSquadType.bossbalrog;
break;
case 280030000:
case 280030100:
zz = MapleSquadType.zak;
break;
case 280030001:
zz = MapleSquadType.chaoszak;
break;
case 240060200:
zz = MapleSquadType.horntail;
break;
case 240060201:
zz = MapleSquadType.chaosht;
break;
case 270050100:
zz = MapleSquadType.pinkbean;
break;
case 270051100:
zz = MapleSquadType.chaospb;
break;
case 802000111:
zz = MapleSquadType.nmm_squad;
break;
case 802000211:
zz = MapleSquadType.vergamot;
break;
case 802000311:
zz = MapleSquadType.tokyo_2095;
break;
case 802000411:
zz = MapleSquadType.dunas;
break;
case 802000611:
zz = MapleSquadType.nibergen_squad;
break;
case 802000711:
zz = MapleSquadType.dunas2;
break;
case 802000801:
case 802000802:
case 802000803:
zz = MapleSquadType.core_blaze;
break;
case 802000821:
case 802000823:
zz = MapleSquadType.aufheben;
break;
case 211070100:
case 211070101:
case 211070110:
zz = MapleSquadType.vonleon;
break;
case 551030200:
zz = MapleSquadType.scartar;
break;
case 271040100:
zz = MapleSquadType.cygnus;
break;
case 689013000:
zz = MapleSquadType.pinkzak;
break;
case 262030300:
case 262031300:
case 262031310:
zz = MapleSquadType.hillah;
break;
case 272030400:
case 272030420:
zz = MapleSquadType.arkarium;
break;
default:
return null;
}
return ChannelServer.getInstance(this.channel).getMapleSquad(zz);
}
public MapleSquad getSquadBegin() {
if (this.squad != null) {
return ChannelServer.getInstance(this.channel).getMapleSquad(this.squad);
}
return null;
}
public EventManager getEMByMap() {
String em;
switch (this.mapid) {
case 105100400:
em = "BossBalrog_EASY";
break;
case 105100300:
em = "BossBalrog_NORMAL";
break;
case 280030000:
case 280030100:
em = "ZakumBattle";
break;
case 240060200:
em = "HorntailBattle";
break;
case 280030001:
em = "ChaosZakum";
break;
case 240060201:
em = "ChaosHorntail";
break;
case 270050100:
em = "PinkBeanBattle";
break;
case 270051100:
em = "ChaosPinkBean";
break;
case 802000111:
em = "NamelessMagicMonster";
break;
case 802000211:
em = "Vergamot";
break;
case 802000311:
em = "2095_tokyo";
break;
case 802000411:
em = "Dunas";
break;
case 802000611:
em = "Nibergen";
break;
case 802000711:
em = "Dunas2";
break;
case 802000801:
case 802000802:
case 802000803:
em = "CoreBlaze";
break;
case 802000821:
case 802000823:
em = "Aufhaven";
break;
case 211070100:
case 211070101:
case 211070110:
em = "VonLeonBattle";
break;
case 551030200:
em = "ScarTarBattle";
break;
case 271040100:
em = "CygnusBattle";
break;
case 689013000:
em = "PinkZakum";
break;
case 262031300:
case 262031310:
em = "Hillah_170";
break;
case 272030400:
case 272030420:
em = "ArkariumBattle";
break;
case 955000100:
case 955000200:
case 955000300:
em = "AswanOffSeason";
break;
default:
if (mapid >= 262020000 && mapid < 262023000) {
em = "Azwan";
break;
}
return null;
}
return ChannelServer.getInstance(this.channel).getEventSM().getEventManager(em);
}
/**
* 移除玩家离开地图
* @param chr
*/
public void removePlayer(MapleCharacter chr) {
if (this.everlast) {
returnEverLastItem(chr);
}
this.charactersLock.writeLock().lock();
try {
this.characters.remove(chr);
} finally {
this.charactersLock.writeLock().unlock();
}
removeMapObject(chr);
chr.removeExtractor();
if (chr.getSidekick() != null) {
MapleCharacter side = getCharacterById(chr.getSidekick().getCharacter(chr.getSidekick().getCharacter(0).getId() == chr.getId() ? 1 : 0).getId());
}
broadcastMessage(MaplePacketCreator.removePlayerFromMap(chr.getId()));
if (chr.getSummonedFamiliar() != null) {
chr.removeVisibleFamiliar();
}
List<MapleSummon> toCancel = new ArrayList();
Map<Integer,MapleSummon> listSummons = chr.getSummonsReadLock();
try {
for (MapleSummon summon : listSummons.values()) {
broadcastMessage(SummonPacket.removeSummon(summon, true));
removeMapObject(summon);
// 不能移动的召唤物,换地图后就没有了
if ((summon.getMovementType() == SummonMovementType.不会移动) || (summon.getMovementType() == SummonMovementType.CIRCLE_STATIONARY) || (summon.getMovementType() == SummonMovementType.自由移动)) {
((List) toCancel).add(summon);
} else {
summon.setChangedMap(true);
}
}
} finally {
chr.unlockSummonsReadLock();
}
// @TODO 这里应该可以合并到上面去的
for (MapleSummon summon : toCancel) {
chr.removeSummon(summon.getSkillId());
chr.dispelSkill(summon.getSkillId());
}
checkStates(chr.getName());
if (this.mapid == 109020001) {
chr.canTalk(true);
}
chr.leaveMap(this);
}
public void broadcastMessage(byte[] packet) {
broadcastMessage(null, packet, Double.POSITIVE_INFINITY, null);
}
public void broadcastMessage(MapleCharacter source, byte[] packet, boolean repeatToSource) {
broadcastMessage(repeatToSource ? null : source, packet, Double.POSITIVE_INFINITY, source.getTruePosition());
}
public void broadcastMessage(byte[] packet, Point rangedFrom) {
broadcastMessage(null, packet, GameConstants.maxViewRangeSq(), rangedFrom);
}
public void broadcastMessage(MapleCharacter source, byte[] packet, Point rangedFrom) {
broadcastMessage(source, packet, GameConstants.maxViewRangeSq(), rangedFrom);
}
public void broadcastMessage(MapleCharacter source, byte[] packet, double rangeSq, Point rangedFrom) {
this.charactersLock.readLock().lock();
try {
for (MapleCharacter chr : characters) {
if (chr != source) {
if (rangeSq < Double.POSITIVE_INFINITY) {
if (rangedFrom.distance(chr.getTruePosition()) <= rangeSq) {
chr.getClient().getSession().write(packet);
}
} else {
chr.getClient().getSession().write(packet);
}
}
}
} finally {
this.charactersLock.readLock().unlock();
}
}
private void sendObjectPlacement(MapleCharacter chr) { //标记载入地图所有存在的实例 召唤兽第一次载入的包
if (chr == null) {
return;
}
for (MapleMapObject o : getMapObjectsInRange(chr.getTruePosition(), chr.getRange(), GameConstants.rangedMapobjectTypes)) {
if ((o.getType() == MapleMapObjectType.REACTOR) && (!((MapleReactor) o).isAlive())) {
continue;
}
o.sendSpawnData(chr.getClient());
chr.addVisibleMapObject(o);
}
}
public List<MaplePortal> getPortalsInRange(Point from, double rangeSq) {
List ret = new ArrayList();
for (MaplePortal type : this.portals.values()) {
if ((from.distanceSq(type.getPosition()) <= rangeSq) && (type.getTargetMapId() != this.mapid) && (type.getTargetMapId() != 999999999)) {
ret.add(type);
}
}
return ret;
}
public List<MapleMapObject> getMapObjectsInRange(Point from, double rangeSq) {
List ret = new ArrayList();
for (MapleMapObjectType type : MapleMapObjectType.values()) {
mapobjectlocks.get(type).readLock().lock();
try {
Iterator<MapleMapObject> itr = mapobjects.get(type).values().iterator();
while (itr.hasNext()) {
MapleMapObject mmo = (MapleMapObject) itr.next();
if (from.distanceSq(mmo.getTruePosition()) <= rangeSq) {
ret.add(mmo);
}
}
} finally {
mapobjectlocks.get(type).readLock().unlock();
}
}
return ret;
}
public List<MapleMapObject> getItemsInRange(Point from, double rangeSq) {
return getMapObjectsInRange(from, rangeSq, Arrays.asList(new MapleMapObjectType[]{MapleMapObjectType.ITEM}));
}
public List<MapleMapObject> getMonstersInRange(Point from, double rangeSq) {
return getMapObjectsInRange(from, rangeSq, Arrays.asList(new MapleMapObjectType[]{MapleMapObjectType.MONSTER}));
}
public List<MapleMapObject> getMapObjectsInRange(Point from, double rangeSq, List<MapleMapObjectType> MapObject_types) {
List ret = new ArrayList();
for (MapleMapObjectType type : MapObject_types) {
mapobjectlocks.get(type).readLock().lock();
try {
Iterator itr = ((LinkedHashMap) this.mapobjects.get(type)).values().iterator();
while (itr.hasNext()) {
MapleMapObject mmo = (MapleMapObject) itr.next();
if (from.distanceSq(mmo.getTruePosition()) <= rangeSq) {
ret.add(mmo);
}
}
} finally {
mapobjectlocks.get(type).readLock().unlock();
}
}
return ret;
}
/**
* 获取矩形中的怪物信息
* @param box
* @param MapObject_types
* @return
*/
public List<MapleMapObject> getMapObjectsInRect(Rectangle box, List<MapleMapObjectType> MapObject_types) {
List ret = new ArrayList();
for (MapleMapObjectType type : MapObject_types) {
mapobjectlocks.get(type).readLock().lock();
try {
Iterator itr = ((LinkedHashMap) this.mapobjects.get(type)).values().iterator();
while (itr.hasNext()) {
MapleMapObject mmo = (MapleMapObject) itr.next();
if (box.contains(mmo.getTruePosition())) {
ret.add(mmo);
}
}
} finally {
mapobjectlocks.get(type).readLock().unlock();
}
}
return ret;
}
public List<MapleCharacter> getCharactersIntersect(Rectangle box) {
List ret = new ArrayList();
this.charactersLock.readLock().lock();
try {
for (MapleCharacter chr : this.characters) {
if (chr.getBounds().intersects(box)) {
ret.add(chr);
}
}
} finally {
this.charactersLock.readLock().unlock();
}
return ret;
}
public List<MapleCharacter> getPlayersInRectAndInList(Rectangle box, List<MapleCharacter> chrList) {
List character = new LinkedList();
this.charactersLock.readLock().lock();
try {
for (MapleCharacter a : this.characters) {
if ((chrList.contains(a)) && (box.contains(a.getTruePosition()))) {
character.add(a);
}
}
} finally {
this.charactersLock.readLock().unlock();
}
return character;
}
public void addPortal(MaplePortal myPortal) {
this.portals.put(myPortal.getId(), myPortal);
}
public MaplePortal getPortal(String portalname) {
for (MaplePortal port : this.portals.values()) {
if (port.getName().equals(portalname)) {
return port;
}
}
return null;
}
public MaplePortal getPortal(int portalid) {
return (MaplePortal) this.portals.get(portalid);
}
public void resetPortals() {
for (MaplePortal port : this.portals.values()) {
port.setPortalState(true);
}
}
public void setFootholds(MapleFootholdTree footholds) {
this.footholds = footholds;
}
public MapleFootholdTree getFootholds() {
return this.footholds;
}
public int getNumSpawnPoints() {
return this.monsterSpawn.size();
}
public void loadMonsterRate(boolean first) {
int spawnSize = this.monsterSpawn.size();
if ((spawnSize >= 20) || (this.partyBonusRate > 0)) {
this.maxRegularSpawn = Math.round(spawnSize / this.monsterRate);
} else {
this.maxRegularSpawn = (int) Math.ceil(spawnSize * this.monsterRate);
}
if (this.fixedMob > 0) {
this.maxRegularSpawn = this.fixedMob;
} else if (this.maxRegularSpawn <= 2) {
this.maxRegularSpawn = 2;
} else if (this.maxRegularSpawn > spawnSize) {
this.maxRegularSpawn = Math.max(10, spawnSize);
}
Collection newSpawn = new LinkedList();
Collection newBossSpawn = new LinkedList();
for (Spawns s : this.monsterSpawn) {
if (s.getCarnivalTeam() >= 2) {
continue;
}
if (s.getMonster().isBoss()) {
newBossSpawn.add(s);
} else {
newSpawn.add(s);
}
}
this.monsterSpawn.clear();
this.monsterSpawn.addAll(newBossSpawn);
this.monsterSpawn.addAll(newSpawn);
if ((first) && (spawnSize > 0)) {
this.lastSpawnTime = System.currentTimeMillis();
if (GameConstants.isForceRespawn(this.mapid)) {
this.createMobInterval = 15000;
}
respawn(false); // this should do the trick, we don't need to wait upon entering map
}
}
public SpawnPoint addMonsterSpawn(MapleMonster monster, int mobTime, byte carnivalTeam, String msg) {
Point newpos = calcPointBelow(monster.getPosition());
newpos.y -= 1;
SpawnPoint sp = new SpawnPoint(monster, newpos, mobTime, carnivalTeam, msg);
if (carnivalTeam > -1) {
this.monsterSpawn.add(0, sp);
} else {
this.monsterSpawn.add(sp);
}
return sp;
}
public void addAreaMonsterSpawn(MapleMonster monster, Point pos1, Point pos2, Point pos3, int mobTime, String msg, boolean shouldSpawn, boolean sendWorldMsg) {
pos1 = calcPointBelow(pos1);
pos2 = calcPointBelow(pos2);
pos3 = calcPointBelow(pos3);
if (pos1 != null) {
pos1.y -= 1;
}
if (pos2 != null) {
pos2.y -= 1;
}
if (pos3 != null) {
pos3.y -= 1;
}
if ((pos1 == null) && (pos2 == null) && (pos3 == null)) {
FileoutputUtil.log(new StringBuilder().append("WARNING: mapid ").append(this.mapid).append(", monster ").append(monster.getId()).append(" could not be spawned.").toString());
return;
}
if (pos1 != null) {
if (pos2 == null) {
pos2 = new Point(pos1);
}
if (pos3 == null) {
pos3 = new Point(pos1);
}
} else if (pos2 != null) {
if (pos1 == null) {
pos1 = new Point(pos2);
}
if (pos3 == null) {
pos3 = new Point(pos2);
}
} else if (pos3 != null) {
if (pos1 == null) {
pos1 = new Point(pos3);
}
if (pos2 == null) {
pos2 = new Point(pos3);
}
}
this.monsterSpawn.add(new SpawnPointAreaBoss(monster, pos1, pos2, pos3, mobTime, msg, shouldSpawn, sendWorldMsg));
}
public List<MapleCharacter> getCharacters() {
return getCharactersThreadsafe();
}
public List<MapleCharacter> getCharactersThreadsafe() {
List chars = new ArrayList();
this.charactersLock.readLock().lock();
try {
for (MapleCharacter mc : this.characters) {
chars.add(mc);
}
} finally {
this.charactersLock.readLock().unlock();
}
return chars;
}
public MapleCharacter getCharacterByName(String id) {
this.charactersLock.readLock().lock();
try {
for (MapleCharacter mc : this.characters) {
if (mc.getName().equalsIgnoreCase(id)) {
MapleCharacter localMapleCharacter1 = mc;
return localMapleCharacter1;
}
}
} finally {
this.charactersLock.readLock().unlock();
}
return null;
}
public MapleCharacter getCharacterById_InMap(int id) {
return getCharacterById(id);
}
public MapleCharacter getCharacterById(int id) {
this.charactersLock.readLock().lock();
try {
for (MapleCharacter mc : this.characters) {
if (mc.getId() == id) {
MapleCharacter localMapleCharacter1 = mc;
return localMapleCharacter1;
}
}
} finally {
this.charactersLock.readLock().unlock();
}
return null;
}
public void updateMapObjectVisibility(MapleCharacter chr, MapleMapObject mo) {
if (chr == null) {
return;
}
if (!chr.isMapObjectVisible(mo)) {
if ((mo.getType() == MapleMapObjectType.MIST) || (mo.getType() == MapleMapObjectType.EXTRACTOR) || (mo.getType() == MapleMapObjectType.SUMMON) || (mo.getType() == MapleMapObjectType.FAMILIAR) || ((mo instanceof MechDoor)) || (mo.getTruePosition().distance(chr.getTruePosition()) <= mo.getRange())) {
chr.addVisibleMapObject(mo);
mo.sendSpawnData(chr.getClient());
}
} else if (!(mo instanceof MechDoor) && (mo.getType() != MapleMapObjectType.MIST) && (mo.getType() != MapleMapObjectType.EXTRACTOR) && (mo.getType() != MapleMapObjectType.SUMMON) && (mo.getType() != MapleMapObjectType.FAMILIAR) && (mo.getTruePosition().distance(chr.getTruePosition()) > mo.getRange())) {
chr.removeVisibleMapObject(mo);
mo.sendDestroyData(chr.getClient());
} else if ((mo.getType() == MapleMapObjectType.MONSTER) && (chr.getTruePosition().distance(mo.getTruePosition()) <= mo.getRange())) {
updateMonsterController((MapleMonster) mo);
}
}
public void moveMonster(MapleMonster monster, Point reportedPos) {
monster.setPosition(reportedPos);
this.charactersLock.readLock().lock();
try {
for (MapleCharacter mc : this.characters) {
updateMapObjectVisibility(mc, monster);
}
} finally {
this.charactersLock.readLock().unlock();
}
}
public void movePlayer(MapleCharacter player, Point newPosition) {
player.setPosition(newPosition);
Collection<MapleMapObject> visibleObjects;
try {
visibleObjects = player.getAndWriteLockVisibleMapObjects();
ArrayList copy = new ArrayList(visibleObjects);
Iterator itr = copy.iterator();
while (itr.hasNext()) {
MapleMapObject mo = (MapleMapObject) itr.next();
if ((mo != null) && (getMapObject(mo.getObjectId(), mo.getType()) == mo)) {
updateMapObjectVisibility(player, mo);
} else if (mo != null) {
player.removeVisibleMapObject(mo);
}
}
for (MapleMapObject mo : getMapObjectsInRange(player.getTruePosition(), player.getRange())) {
if ((mo != null) && (!visibleObjects.contains(mo))) {
mo.sendSpawnData(player.getClient());
player.addVisibleMapObject(mo);
}
}
} finally {
// Collection visibleObjects;
player.unlockWriteVisibleMapObjects();
}
}
public MaplePortal findClosestSpawnpoint(Point from) {
MaplePortal closest = getPortal(0);
double shortestDistance = (1.0D / 0.0D);
for (MaplePortal portal : this.portals.values()) {
double distance = portal.getPosition().distanceSq(from);
if ((portal.getType() >= 0) && (portal.getType() <= 2) && (distance < shortestDistance) && (portal.getTargetMapId() == 999999999)) {
closest = portal;
shortestDistance = distance;
}
}
return closest;
}
public MaplePortal findClosestPortal(Point from) {
MaplePortal closest = getPortal(0);
double shortestDistance = Double.POSITIVE_INFINITY;
for (MaplePortal portal : this.portals.values()) {
double distance = portal.getPosition().distanceSq(from);
if (distance < shortestDistance) {
closest = portal;
shortestDistance = distance;
}
}
return closest;
}
public String spawnDebug() {
StringBuilder sb = new StringBuilder("Mobs in map : ");
sb.append(getMobsSize());
sb.append(" spawnedMonstersOnMap: ");
sb.append(this.spawnedMonstersOnMap);
sb.append(" spawnpoints: ");
sb.append(this.monsterSpawn.size());
sb.append(" maxRegularSpawn: ");
sb.append(this.maxRegularSpawn);
sb.append(" actual monsters: ");
sb.append(getNumMonsters());
sb.append(" monster rate: ");
sb.append(this.monsterRate);
sb.append(" fixed: ");
sb.append(this.fixedMob);
return sb.toString();
}
public int getMapObjectSize() {
return this.mapobjects.size();
}
public int getCharactersSize() {
this.charactersLock.readLock().lock();
try {
int i = this.characters.size();
return i;
} finally {
this.charactersLock.readLock().unlock();
}
}
public Collection<MaplePortal> getPortals() {
return Collections.unmodifiableCollection(this.portals.values());
}
public int getSpawnedMonstersOnMap() {
return this.spawnedMonstersOnMap.get();
}
public void respawn(boolean force) {
respawn(force, System.currentTimeMillis());
}
public void respawn(boolean force, long now) {
lastSpawnTime = now;
int numShouldSpawn;
int spawned;
if (force) {
numShouldSpawn = this.monsterSpawn.size() - this.spawnedMonstersOnMap.get();
if (numShouldSpawn > 0) {
spawned = 0;
for (Spawns spawnPoint : this.monsterSpawn) {
spawnPoint.spawnMonster(this);
spawned++;
if (spawned >= numShouldSpawn) {
break;
}
}
}
} else {
numShouldSpawn = (GameConstants.isForceRespawn(this.mapid) ? this.monsterSpawn.size() : this.maxRegularSpawn) - this.spawnedMonstersOnMap.get();
if (numShouldSpawn > 0) {
spawned = 0;
List<Spawns> randomSpawn = new ArrayList(this.monsterSpawn);
Collections.shuffle(randomSpawn);
for (Spawns spawnPoint : randomSpawn) {
if (!isSpawns && (spawnPoint.getMobTime() > 0)) {
continue;
}
if ((spawnPoint.shouldSpawn(lastSpawnTime)) || (GameConstants.isForceRespawn(mapid)) || (monsterSpawn.size() < 10 && this.maxRegularSpawn > monsterSpawn.size() && this.partyBonusRate > 0)) {
spawnPoint.spawnMonster(this);
spawned++;
}
if (spawned >= numShouldSpawn) {
break;
}
}
}
}
}
public String getSnowballPortal() {
int[] teamss = new int[2];
this.charactersLock.readLock().lock();
try {
for (MapleCharacter chr : this.characters) {
if (chr.getTruePosition().y > -80) {
teamss[0] += 1;
} else {
teamss[1] += 1;
}
}
} finally {
this.charactersLock.readLock().unlock();
}
if (teamss[0] > teamss[1]) {
return "st01";
}
return "st00";
}
public boolean isDisconnected(int id) {
return this.dced.contains(id);
}
public void addDisconnected(int id) {
this.dced.add(id);
}
public void resetDisconnected() {
this.dced.clear();
}
public void startSpeedRun() {
MapleSquad squads = getSquadByMap();
if (squads != null) {
this.charactersLock.readLock().lock();
try {
for (MapleCharacter chr : this.characters) {
if ((chr.getName().equals(squads.getLeaderName())) && (!chr.isIntern())) {
startSpeedRun(chr.getName());
return;
}
}
} finally {
this.charactersLock.readLock().unlock();
}
}
}
public void startSpeedRun(String leader) {
this.speedRunStart = System.currentTimeMillis();
this.speedRunLeader = leader;
}
public void endSpeedRun() {
this.speedRunStart = 0L;
this.speedRunLeader = "";
}
public void getRankAndAdd(String leader, String time, ExpeditionType type, long timz, Collection<String> squad) {
try {
long lastTime = SpeedRunner.getSpeedRunData(type) == null ? 0L : (SpeedRunner.getSpeedRunData(type).right);
StringBuilder rett = new StringBuilder();
if (squad != null) {
for (String chr : squad) {
rett.append(chr);
rett.append(",");
}
}
String z = rett.toString();
if (squad != null) {
z = z.substring(0, z.length() - 1);
}
Connection con = DatabaseConnection.getConnection();
try (PreparedStatement ps = con.prepareStatement("INSERT INTO speedruns(`type`, `leader`, `timestring`, `time`, `members`) VALUES (?,?,?,?,?)")) {
ps.setString(1, type.name());
ps.setString(2, leader);
ps.setString(3, time);
ps.setLong(4, timz);
ps.setString(5, z);
ps.executeUpdate();
ps.close();
}
if (lastTime == 0L) {
SpeedRunner.addSpeedRunData(type, SpeedRunner.addSpeedRunData(new StringBuilder(SpeedRunner.getPreamble(type)), new HashMap(), z, leader, 1, time), timz);
} else {
SpeedRunner.removeSpeedRunData(type);
SpeedRunner.loadSpeedRunData(type);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public long getSpeedRunStart() {
return this.speedRunStart;
}
public void disconnectAll() {
for (MapleCharacter chr : getCharactersThreadsafe()) {
if (!chr.isGM()) {
chr.getClient().disconnect(true, false);
chr.getClient().getSession().close(true);
}
}
}
public List<MapleNPC> getAllNPCs() {
return getAllNPCsThreadsafe();
}
public List<MapleNPC> getAllNPCsThreadsafe() {
ArrayList ret = new ArrayList();
mapobjectlocks.get(MapleMapObjectType.NPC).readLock().lock();
try {
for (MapleMapObject mmo : mapobjects.get(MapleMapObjectType.NPC).values()) {
ret.add((MapleNPC) mmo);
}
} finally {
mapobjectlocks.get(MapleMapObjectType.NPC).readLock().unlock();
}
return ret;
}
public List<MapleArrowsTurret> getAllArrowsTurrets() {
return getArrowsTurretsThreadsafe();
}
public List<MapleArrowsTurret> getArrowsTurretsThreadsafe() {
ArrayList ret = new ArrayList();
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.ARROWS_TURRET)).readLock().lock();
try {
for (MapleMapObject mmo : mapobjects.get(MapleMapObjectType.ARROWS_TURRET).values()) {
ret.add((MapleArrowsTurret) mmo);
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.ARROWS_TURRET)).readLock().unlock();
}
return ret;
}
public void resetNPCs() {
removeNpc(-1);
}
public void resetPQ(int level) {
resetFully();
for (MapleMonster mons : getAllMonstersThreadsafe()) {
mons.getStats().setChange(true);
mons.changeLevel(level, true);
}
resetSpawnLevel(level);
}
public void resetSpawnLevel(int level) {
for (Spawns spawn : this.monsterSpawn) {
if ((spawn instanceof SpawnPoint)) {
((SpawnPoint) spawn).setLevel(level);
}
}
}
public void resetFully() {
resetFully(true);
}
public void resetFully(boolean respawn) {
killAllMonsters(false);
reloadReactors();
removeDrops();
resetNPCs();
resetSpawns();
resetDisconnected();
endSpeedRun();
cancelSquadSchedule(true);
resetPortals();
this.environment.clear();
if (respawn) {
respawn(true);
}
}
public void cancelSquadSchedule(boolean interrupt) {
this.squadTimer = false;
this.checkStates = true;
if (this.squadSchedule != null) {
this.squadSchedule.cancel(interrupt);
this.squadSchedule = null;
}
}
public void removeDrops() {
List<MapleMapItem> mapItems = getAllItemsThreadsafe();
for (MapleMapItem mapItem : mapItems) {
mapItem.expire(this);
}
}
public void removeDropsDelay() {
List<MapleMapItem> mapItems = getAllItemsThreadsafe();
int delay = 0;
int i = 0;
for (MapleMapItem mapItem : mapItems) {
i++;
if (i < 50) {
mapItem.expire(this);
} else {
delay++;
if (mapItem.hasFFA()) {
mapItem.registerFFA(delay * 20);
} else {
mapItem.registerExpire(delay * 30);
}
}
}
}
public void resetAllSpawnPoint(int mobid, int mobTime) {
Collection<Spawns> AllSpawnPoints = new LinkedList(this.monsterSpawn);
resetFully();
this.monsterSpawn.clear();
for (Spawns spawnPoint : AllSpawnPoints) {
MapleMonster newMons = MapleLifeFactory.getMonster(mobid);
newMons.setF(spawnPoint.getF());
newMons.setFh(spawnPoint.getFh());
newMons.setPosition(spawnPoint.getPosition());
addMonsterSpawn(newMons, mobTime, (byte) -1, null);
}
loadMonsterRate(true);
}
public void resetSpawns() {
boolean changed = false;
Iterator AllSpawnPoints = this.monsterSpawn.iterator();
while (AllSpawnPoints.hasNext()) {
if (((Spawns) AllSpawnPoints.next()).getCarnivalId() > -1) {
AllSpawnPoints.remove();
changed = true;
}
}
setSpawns(true);
if (changed) {
loadMonsterRate(true);
}
}
public boolean makeCarnivalSpawn(int team, MapleMonster newMons, int num) {
MapleNodes.MonsterPoint ret = null;
for (MapleNodes.MonsterPoint mp : this.nodes.getMonsterPoints()) {
if ((mp.team == team) || (mp.team == -1)) {
Point newpos = calcPointBelow(new Point(mp.x, mp.y));
newpos.y -= 1;
boolean found = false;
for (Spawns s : this.monsterSpawn) {
if ((s.getCarnivalId() > -1) && ((mp.team == -1) || (s.getCarnivalTeam() == mp.team)) && (s.getPosition().x == newpos.x) && (s.getPosition().y == newpos.y)) {
found = true;
break;
}
}
if (!found) {
ret = mp;
break;
}
}
}
if (ret != null) {
newMons.setCy(ret.cy);
newMons.setF(0);
newMons.setFh(ret.fh);
newMons.setRx0(ret.x + 50);
newMons.setRx1(ret.x - 50);
newMons.setPosition(new Point(ret.x, ret.y));
newMons.setHide(false);
SpawnPoint sp = addMonsterSpawn(newMons, 1, (byte) team, null);
sp.setCarnival(num);
}
return ret != null;
}
public boolean makeCarnivalReactor(int team, int num) {
MapleReactor old = getReactorByName(new StringBuilder().append(team).append("").append(num).toString());
if ((old != null) && (old.getState() < 5)) {
return false;
}
Point guardz = null;
List<MapleReactor> react = getAllReactorsThreadsafe();
for (Pair guard : this.nodes.getGuardians()) {
if ((((Integer) guard.right) == team) || (((Integer) guard.right) == -1)) {
boolean found = false;
for (MapleReactor r : react) {
if ((r.getTruePosition().x == ((Point) guard.left).x) && (r.getTruePosition().y == ((Point) guard.left).y) && (r.getState() < 5)) {
found = true;
break;
}
}
if (!found) {
guardz = (Point) guard.left;
break;
}
}
}
MapleCarnivalFactory.MCSkill skil;
if (guardz != null) {
MapleReactor my = new MapleReactor(MapleReactorFactory.getReactor(9980000 + team), 9980000 + team);
my.setState((byte) 1);
my.setName(new StringBuilder().append(team).append("").append(num).toString());
spawnReactorOnGroundBelow(my, guardz);
skil = MapleCarnivalFactory.getInstance().getGuardian(num);
for (MapleMonster mons : getAllMonstersThreadsafe()) {
if (mons.getCarnivalTeam() == team) {
skil.getSkill().applyEffect(null, mons, false);
}
}
}
return guardz != null;
}
public void blockAllPortal() {
for (MaplePortal p : this.portals.values()) {
p.setPortalState(false);
}
}
public boolean getAndSwitchTeam() {
return getCharactersSize() % 2 != 0;
}
public void setSquad(MapleSquadType s) {
this.squad = s;
}
public int getChannel() {
return this.channel;
}
public int getConsumeItemCoolTime() {
return this.consumeItemCoolTime;
}
public void setConsumeItemCoolTime(int ciit) {
this.consumeItemCoolTime = ciit;
}
public void setPermanentWeather(int pw) {
this.permanentWeather = pw;
}
public int getPermanentWeather() {
return this.permanentWeather;
}
public void checkStates(String chr) {
if (!this.checkStates) {
return;
}
MapleSquad sqd = getSquadByMap();
EventManager em = getEMByMap();
int size = getCharactersSize();
if ((sqd != null) && (sqd.getStatus() == 2)) {
sqd.removeMember(chr);
if (em != null) {
if (sqd.getLeaderName().equalsIgnoreCase(chr)) {
em.setProperty("leader", "false");
}
if ((chr.equals("")) || (size == 0)) {
em.setProperty("state", "0");
em.setProperty("leader", "true");
cancelSquadSchedule(!chr.equals(""));
sqd.clear();
sqd.copy();
}
}
}
if ((em != null) && (em.getProperty("state") != null) && ((sqd == null) || (sqd.getStatus() == 2)) && (size == 0)) {
em.setProperty("state", "0");
if (em.getProperty("leader") != null) {
em.setProperty("leader", "true");
}
}
if ((this.speedRunStart > 0L) && (size == 0)) {
endSpeedRun();
}
}
public void setCheckStates(boolean b) {
this.checkStates = b;
}
public void setNodes(MapleNodes mn) {
this.nodes = mn;
}
public List<MapleNodes.MaplePlatform> getPlatforms() {
return this.nodes.getPlatforms();
}
public Collection<MapleNodes.MapleNodeInfo> getNodes() {
return this.nodes.getNodes();
}
public MapleNodes.MapleNodeInfo getNode(int index) {
return this.nodes.getNode(index);
}
public boolean isLastNode(int index) {
return this.nodes.isLastNode(index);
}
public List<Rectangle> getAreas() {
return this.nodes.getAreas();
}
public Rectangle getArea(int index) {
return this.nodes.getArea(index);
}
public void changeEnvironment(String ms, int type) {
broadcastMessage(MaplePacketCreator.environmentChange(ms, type));
}
public void toggleEnvironment(String ms) {
if (this.environment.containsKey(ms)) {
moveEnvironment(ms, (this.environment.get(ms)) == 1 ? 2 : 1);
} else {
moveEnvironment(ms, 1);
}
}
public void moveEnvironment(String ms, int type) {
broadcastMessage(MaplePacketCreator.environmentMove(ms, type));
this.environment.put(ms, type);
}
public Map<String, Integer> getEnvironment() {
return this.environment;
}
public int getNumPlayersInArea(int index) {
return getNumPlayersInRect(getArea(index));
}
public int getNumPlayersInRect(Rectangle rect) {
int ret = 0;
this.charactersLock.readLock().lock();
try {
Iterator ltr = this.characters.iterator();
while (ltr.hasNext()) {
if (rect.contains(((MapleCharacter) ltr.next()).getTruePosition())) {
ret++;
}
}
} finally {
this.charactersLock.readLock().unlock();
}
return ret;
}
public int getNumPlayersItemsInArea(int index) {
return getNumPlayersItemsInRect(getArea(index));
}
public int getNumPlayersItemsInRect(Rectangle rect) {
int ret = getNumPlayersInRect(rect);
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.ITEM)).readLock().lock();
try {
for (MapleMapObject mmo : mapobjects.get(MapleMapObjectType.ITEM).values()) {
if (rect.contains(mmo.getTruePosition())) {
ret++;
}
}
} finally {
((ReentrantReadWriteLock) this.mapobjectlocks.get(MapleMapObjectType.ITEM)).readLock().unlock();
}
return ret;
}
public void broadcastGMMessage(MapleCharacter source, byte[] packet, boolean repeatToSource) {
broadcastGMMessage(repeatToSource ? null : source, packet);
}
private void broadcastGMMessage(MapleCharacter source, byte[] packet) {
this.charactersLock.readLock().lock();
try {
if (source == null) {
for (MapleCharacter chr : this.characters) {
if (chr.isStaff()) {
chr.getClient().getSession().write(packet);
}
}
} else {
for (MapleCharacter chr : this.characters) {
if ((chr != source) && (chr.getGMLevel() >= source.getGMLevel())) {
chr.getClient().getSession().write(packet);
}
}
}
} finally {
this.charactersLock.readLock().unlock();
}
}
public void broadcastNONGMMessage(MapleCharacter source, byte[] packet, boolean repeatToSource) {
broadcastNONGMMessage(repeatToSource ? null : source, packet);
}
private void broadcastNONGMMessage(MapleCharacter source, byte[] packet) {
charactersLock.readLock().lock();
try {
if (source == null) {
for (MapleCharacter chr : characters) {
if (!chr.isStaff()) {
chr.getClient().getSession().write(packet);
}
}
} else {
for (MapleCharacter chr : characters) {
if (chr != source && (chr.getGMLevel() < source.getGMLevel())) {
chr.getClient().getSession().write(packet);
}
}
}
} finally {
charactersLock.readLock().unlock();
}
}
public List<Pair<Integer, Integer>> getMobsToSpawn() {
return this.nodes.getMobsToSpawn();
}
public List<Integer> getSkillIds() {
return this.nodes.getSkillIds();
}
public boolean canSpawn(long now) {
return (this.lastSpawnTime > 0L) && (this.lastSpawnTime + this.createMobInterval < now);
}
public boolean canHurt(long now) {
if ((this.lastHurtTime > 0L) && (this.lastHurtTime + this.decHPInterval < now)) {
this.lastHurtTime = now;
return true;
}
return false;
}
public void resetShammos(final MapleClient c) {
killAllMonsters(true);
broadcastMessage(MaplePacketCreator.serverMessageNotice("A player has moved too far from Shammos. Shammos is going back to the start."));
EtcTimer.getInstance().schedule(new Runnable() {
@Override
public void run() {
if (c.getPlayer() != null) {
c.getPlayer().changeMap(MapleMap.this, MapleMap.this.getPortal(0));
if (MapleMap.this.getCharactersThreadsafe().size() > 1) {
MapScriptMethods.startScript_FirstUser(c, "shammos_Fenter");
}
}
}
}, 500L);
}
public int getInstanceId() {
return this.instanceid;
}
public void setInstanceId(int ii) {
this.instanceid = ii;
}
public int getPartyBonusRate() {
return this.partyBonusRate;
}
public void setPartyBonusRate(int ii) {
this.partyBonusRate = ii;
}
public short getTop() {
return this.top;
}
public short getBottom() {
return this.bottom;
}
public short getLeft() {
return this.left;
}
public short getRight() {
return this.right;
}
public void setTop(int ii) {
this.top = (short) ii;
}
public void setBottom(int ii) {
this.bottom = (short) ii;
}
public void setLeft(int ii) {
this.left = (short) ii;
}
public void setRight(int ii) {
this.right = (short) ii;
}
public List<Pair<Point, Integer>> getGuardians() {
return this.nodes.getGuardians();
}
public MapleNodes.DirectionInfo getDirectionInfo(int i) {
return this.nodes.getDirection(i);
}
public void AutoNx(int jsNx, boolean isAutoPoints) {
if (this.mapid != 910000000) {
return;
}
for (MapleCharacter chr : this.characters) {
if (chr != null) {
if (isAutoPoints) {
chr.gainPlayerPoints(10);
chr.dropMessage(5, "[系统奖励] 在线时间奖励获得 [10] 点积分.");
} else {
int givNx = chr.getLevel() / 10 + jsNx;
chr.modifyCSPoints(2, givNx);
chr.dropMessage(5, new StringBuilder().append("[系统奖励] 在线时间奖励获得 [").append(givNx).append("] 点抵用券.").toString());
}
}
}
}
public void AutoGain(int rate, int expRate) {
for (MapleCharacter chr : this.characters) {
if (chr == null) {
return;
}
int giveP;
if (Randomizer.isSuccess(40)) {
giveP = Randomizer.rand(4, 5) * 3;
} else {
giveP = Randomizer.rand(2, 3) * 3;
}
giveP *= rate;
chr.modifyCSPoints(2, giveP);
String msg = "在线奖励 [" + giveP + "] 抵用券";
if (chr.getLevel() < 255) {
int givExp = chr.getLevel() <= 10 ? chr.getLevel() ^ 5 : chr.getLevel() * expRate * Randomizer.rand(8, 12);
givExp *= rate;
chr.gainExp(givExp, true, false, true);
msg += "和 [" + givExp + "] 经验";
}
if (rate > 1) {
msg += " (" + rate + "倍)";
}
chr.dropMessage(-5, msg);
}
}
public boolean isMarketMap() {
return (this.mapid >= 910000000) && (this.mapid <= 910000017);
}
public boolean isBossMap() {
switch (this.mapid) {
case 105100300:
case 105100400:
case 211070100:
case 211070101:
case 211070110:
case 220080001:
case 240040700:
case 240060200:
case 240060201:
case 262031300:
case 262031310:
case 270050100:
case 271040100:
case 271040200:
case 272030400:
case 272030420:
case 280030000:
case 280030001:
case 280030100:
case 300030310:
case 551030200:
case 802000111:
case 802000211:
case 802000311:
case 802000411:
case 802000611:
case 802000711:
case 802000801:
case 802000802:
case 802000803:
case 802000821:
case 802000823:
return true;
}
return false;
}
private int hasBoat() {
return docked ? 2 : (boat ? 1 : 0);
}
public void setBoat(boolean hasBoat) {
this.boat = hasBoat;
}
/**
* 设置是否可以停靠船只
* @param isDocked
*/
public void setDocked(boolean isDocked) {
this.docked = isDocked;
}
public void checkMoveMonster(Point from, boolean fly, MapleCharacter chr) {
if ((this.maxRegularSpawn <= 2) || (this.monsterSpawn.isEmpty()) || (this.monsterRate <= 1.0D) || (chr == null)) {
return;
}
//检测吸怪
/*int check = (int) ((fly ? 70 : 60) / 100.0D * this.maxRegularSpawn);
if (getMonstersInRange(from, 5000.0D).size() >= check) {
for (MapleMapObject obj : getMonstersInRange(from, (1.0D / 0.0D))) {
MapleMonster mob = (MapleMonster) obj;
killMonster(mob, chr, false, false, (byte) 1);
}
}*/
}
private static abstract interface DelayedPacketCreation {
public abstract void sendPackets(MapleClient paramMapleClient);
}
private class ActivateItemReactor implements Runnable {
private final MapleMapItem mapitem;
private final MapleReactor reactor;
private final MapleClient c;
public ActivateItemReactor(MapleMapItem mapitem, MapleReactor reactor, MapleClient c) {
this.mapitem = mapitem;
this.reactor = reactor;
this.c = c;
}
@Override
public void run() {
if ((this.mapitem != null) && (this.mapitem == MapleMap.this.getMapObject(this.mapitem.getObjectId(), this.mapitem.getType())) && (!this.mapitem.isPickedUp())) {
this.mapitem.expire(MapleMap.this);
this.reactor.hitReactor(this.c);
this.reactor.setTimerActive(false);
if (this.reactor.getDelay() > 0) {
MapTimer.getInstance().schedule(new Runnable() {
@Override
public void run() {
MapleMap.ActivateItemReactor.this.reactor.forceHitReactor((byte) 0);
}
}, this.reactor.getDelay());
}
} else {
this.reactor.setTimerActive(false);
}
}
}
}